blob: 11c266cde2a72f55798881defcf018cbde1e0cf6 [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;
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +0000815#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
816 defined(__NetBSD__) || defined(_LIBCPP_HAS_MUSL_LIBC)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000817 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000818#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000819 return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000820#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000821}
822
823const wchar_t*
824ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
825{
826 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000827#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
828 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +0000829#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
830 defined(__NetBSD__) || defined(_LIBCPP_HAS_MUSL_LIBC)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000831 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
832 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000833#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000834 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000835#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000836 return low;
837}
838
839wchar_t
840ctype<wchar_t>::do_tolower(char_type c) const
841{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000842#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
843 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +0000844#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
845 defined(__NetBSD__) || defined(_LIBCPP_HAS_MUSL_LIBC)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000846 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000847#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000848 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000849#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000850}
851
852const wchar_t*
853ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
854{
855 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000856#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
857 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +0000858#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \
859 defined(__NetBSD__) || defined(_LIBCPP_HAS_MUSL_LIBC)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000860 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
861 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000862#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000863 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000864#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000865 return low;
866}
867
868wchar_t
869ctype<wchar_t>::do_widen(char c) const
870{
871 return c;
872}
873
874const char*
875ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
876{
877 for (; low != high; ++low, ++dest)
878 *dest = *low;
879 return low;
880}
881
882char
883ctype<wchar_t>::do_narrow(char_type c, char dfault) const
884{
885 if (isascii(c))
886 return static_cast<char>(c);
887 return dfault;
888}
889
890const wchar_t*
891ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
892{
893 for (; low != high; ++low, ++dest)
894 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000895 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000896 else
897 *dest = dfault;
898 return low;
899}
900
901// template <> class ctype<char>;
902
903locale::id ctype<char>::id;
904
905ctype<char>::ctype(const mask* tab, bool del, size_t refs)
906 : locale::facet(refs),
907 __tab_(tab),
908 __del_(del)
909{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000910 if (__tab_ == 0)
911 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000912}
913
914ctype<char>::~ctype()
915{
916 if (__tab_ && __del_)
917 delete [] __tab_;
918}
919
920char
921ctype<char>::do_toupper(char_type c) const
922{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000923#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000924 return isascii(c) ?
925 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000926#elif defined(__NetBSD__)
927 return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +0000928#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC)
929 return isascii(c) ?
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000930 static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000931#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000932 return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000933#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000934}
935
936const char*
937ctype<char>::do_toupper(char_type* low, const char_type* high) const
938{
939 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000940#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000941 *low = isascii(*low) ?
942 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000943#elif defined(__NetBSD__)
944 *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +0000945#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC)
Marshall Clow88c31902013-02-07 14:22:51 +0000946 *low = isascii(*low) ?
947 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000948#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000949 *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000950#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000951 return low;
952}
953
954char
955ctype<char>::do_tolower(char_type c) const
956{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000957#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000958 return isascii(c) ?
959 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000960#elif defined(__NetBSD__)
961 return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]);
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +0000962#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC)
Marshall Clow88c31902013-02-07 14:22:51 +0000963 return isascii(c) ?
964 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000965#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000966 return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000967#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000968}
969
970const char*
971ctype<char>::do_tolower(char_type* low, const char_type* high) const
972{
973 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000974#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000975 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +0000976#elif defined(__NetBSD__)
977 *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]);
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +0000978#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC)
Marshall Clow88c31902013-02-07 14:22:51 +0000979 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000980#else
Ed Schouten9e97eb82015-07-06 15:37:40 +0000981 *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000982#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000983 return low;
984}
985
986char
987ctype<char>::do_widen(char c) const
988{
989 return c;
990}
991
992const char*
993ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
994{
995 for (; low != high; ++low, ++dest)
996 *dest = *low;
997 return low;
998}
999
1000char
1001ctype<char>::do_narrow(char_type c, char dfault) const
1002{
1003 if (isascii(c))
1004 return static_cast<char>(c);
1005 return dfault;
1006}
1007
1008const char*
1009ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1010{
1011 for (; low != high; ++low, ++dest)
1012 if (isascii(*low))
1013 *dest = *low;
1014 else
1015 *dest = dfault;
1016 return low;
1017}
1018
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +00001019#if defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001020extern "C" const unsigned short ** __ctype_b_loc();
1021extern "C" const int ** __ctype_tolower_loc();
1022extern "C" const int ** __ctype_toupper_loc();
1023#endif
1024
Marshall Clowe917d802015-03-04 16:50:02 +00001025#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
Marshall Clow8291a762015-03-04 16:10:14 +00001026const ctype<char>::mask*
1027ctype<char>::classic_table() _NOEXCEPT
1028{
1029 static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = {
1030 cntrl, cntrl,
1031 cntrl, cntrl,
1032 cntrl, cntrl,
1033 cntrl, cntrl,
1034 cntrl, cntrl | space | blank,
1035 cntrl | space, cntrl | space,
1036 cntrl | space, cntrl | space,
1037 cntrl, cntrl,
1038 cntrl, cntrl,
1039 cntrl, cntrl,
1040 cntrl, cntrl,
1041 cntrl, cntrl,
1042 cntrl, cntrl,
1043 cntrl, cntrl,
1044 cntrl, cntrl,
1045 cntrl, cntrl,
1046 space | blank | print, punct | print,
1047 punct | print, punct | print,
1048 punct | print, punct | print,
1049 punct | print, punct | print,
1050 punct | print, punct | print,
1051 punct | print, punct | print,
1052 punct | print, punct | print,
1053 punct | print, punct | print,
1054 digit | print | xdigit, digit | print | xdigit,
1055 digit | print | xdigit, digit | print | xdigit,
1056 digit | print | xdigit, digit | print | xdigit,
1057 digit | print | xdigit, digit | print | xdigit,
1058 digit | print | xdigit, digit | print | xdigit,
1059 punct | print, punct | print,
1060 punct | print, punct | print,
1061 punct | print, punct | print,
1062 punct | print, upper | xdigit | print | alpha,
1063 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1064 upper | xdigit | print | alpha, upper | xdigit | print | alpha,
1065 upper | xdigit | 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, upper | print | alpha,
1072 upper | print | alpha, upper | print | alpha,
1073 upper | print | alpha, upper | print | alpha,
1074 upper | print | alpha, upper | print | alpha,
1075 upper | print | alpha, punct | print,
1076 punct | print, punct | print,
1077 punct | print, punct | print,
1078 punct | print, lower | xdigit | print | alpha,
1079 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1080 lower | xdigit | print | alpha, lower | xdigit | print | alpha,
1081 lower | xdigit | 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, lower | print | alpha,
1088 lower | print | alpha, lower | print | alpha,
1089 lower | print | alpha, lower | print | alpha,
1090 lower | print | alpha, lower | print | alpha,
1091 lower | print | alpha, punct | print,
1092 punct | print, punct | print,
1093 punct | print, cntrl,
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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1099 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1100 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1102 };
1103 return builtin_table;
1104}
1105#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001106const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +00001107ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001108{
David Chisnallc512df12011-09-21 08:39:44 +00001109#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001110 return _DefaultRuneLocale.__runetype;
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001111#elif defined(__NetBSD__)
1112 return _C_ctype_tab_ + 1;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001113#elif defined(__GLIBC__)
Ed Schouten9e97eb82015-07-06 15:37:40 +00001114 return _LIBCPP_GET_C_LOCALE->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +00001115#elif __sun__
1116 return __ctype_mask;
Howard Hinnantef5aa932013-09-17 01:34:47 +00001117#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001118 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +00001119// This is assumed to be safe, which is a nonsense assumption because we're
1120// going to end up dereferencing it later...
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +00001121#elif defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001122 return *__ctype_b_loc();
JF Bastiena14f7cb2015-02-25 22:16:46 +00001123#elif defined(_NEWLIB_VERSION)
1124 // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
1125 return _ctype_ + 1;
Howard Hinnant7f764502013-08-14 18:00:20 +00001126#elif defined(_AIX)
Marshall Clow016d4e82013-11-19 19:16:03 +00001127 return (const unsigned int *)__lc_ctype_ptr->obj->mask;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001128#else
David Chisnall997e4542012-02-29 13:05:08 +00001129 // Platform not supported: abort so the person doing the port knows what to
1130 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001131# warning ctype<char>::classic_table() is not implemented
Howard Hinnanted14a762013-07-23 16:05:56 +00001132 printf("ctype<char>::classic_table() is not implemented\n");
David Chisnall997e4542012-02-29 13:05:08 +00001133 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001134 return NULL;
1135#endif
1136}
Marshall Clow8291a762015-03-04 16:10:14 +00001137#endif
Sean Hunt62a6ac32011-07-09 00:56:23 +00001138
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001139#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001140const int*
1141ctype<char>::__classic_lower_table() _NOEXCEPT
1142{
Ed Schouten9e97eb82015-07-06 15:37:40 +00001143 return _LIBCPP_GET_C_LOCALE->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001144}
1145
1146const int*
1147ctype<char>::__classic_upper_table() _NOEXCEPT
1148{
Ed Schouten9e97eb82015-07-06 15:37:40 +00001149 return _LIBCPP_GET_C_LOCALE->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001150}
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001151#elif __NetBSD__
1152const short*
1153ctype<char>::__classic_lower_table() _NOEXCEPT
1154{
1155 return _C_tolower_tab_ + 1;
1156}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001157
Joerg Sonnenbergera71a9522013-05-17 21:17:34 +00001158const short*
1159ctype<char>::__classic_upper_table() _NOEXCEPT
1160{
1161 return _C_toupper_tab_ + 1;
1162}
1163
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +00001164#elif defined(__EMSCRIPTEN__) || defined(_LIBCPP_HAS_MUSL_LIBC)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001165const int*
1166ctype<char>::__classic_lower_table() _NOEXCEPT
1167{
1168 return *__ctype_tolower_loc();
1169}
1170
1171const int*
1172ctype<char>::__classic_upper_table() _NOEXCEPT
1173{
1174 return *__ctype_toupper_loc();
1175}
Vasileios Kalintiris579b42b2015-11-09 10:21:04 +00001176#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ || defined(_LIBCPP_HAS_MUSL_LIBC)
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001177
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001178// template <> class ctype_byname<char>
1179
1180ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1181 : ctype<char>(0, false, refs),
1182 __l(newlocale(LC_ALL_MASK, name, 0))
1183{
Howard Hinnantd4444702010-08-11 17:04:31 +00001184#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001185 if (__l == 0)
1186 throw runtime_error("ctype_byname<char>::ctype_byname"
1187 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001188#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001189}
1190
1191ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1192 : ctype<char>(0, false, refs),
1193 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1194{
Howard Hinnantd4444702010-08-11 17:04:31 +00001195#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001196 if (__l == 0)
1197 throw runtime_error("ctype_byname<char>::ctype_byname"
1198 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001199#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001200}
1201
1202ctype_byname<char>::~ctype_byname()
1203{
1204 freelocale(__l);
1205}
1206
1207char
1208ctype_byname<char>::do_toupper(char_type c) const
1209{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001210 return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001211}
1212
1213const char*
1214ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1215{
1216 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001217 *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001218 return low;
1219}
1220
1221char
1222ctype_byname<char>::do_tolower(char_type c) const
1223{
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001224 return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001225}
1226
1227const char*
1228ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1229{
1230 for (; low != high; ++low)
Joerg Sonnenberger63d8f7e2013-05-02 19:17:48 +00001231 *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001232 return low;
1233}
1234
1235// template <> class ctype_byname<wchar_t>
1236
1237ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1238 : ctype<wchar_t>(refs),
1239 __l(newlocale(LC_ALL_MASK, name, 0))
1240{
Howard Hinnantd4444702010-08-11 17:04:31 +00001241#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001242 if (__l == 0)
1243 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1244 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001245#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001246}
1247
1248ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1249 : ctype<wchar_t>(refs),
1250 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1251{
Howard Hinnantd4444702010-08-11 17:04:31 +00001252#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001253 if (__l == 0)
1254 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1255 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001256#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001257}
1258
1259ctype_byname<wchar_t>::~ctype_byname()
1260{
1261 freelocale(__l);
1262}
1263
1264bool
1265ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1266{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001267#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001268 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001269#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001270 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001271 wint_t ch = static_cast<wint_t>(c);
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001272 if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0);
1273 if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0);
1274 if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1275 if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0);
1276 if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0);
1277 if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0);
1278 if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0);
1279 if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0);
1280 if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1281 if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001282 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001283#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001284}
1285
1286const wchar_t*
1287ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1288{
1289 for (; low != high; ++low, ++vec)
1290 {
1291 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001292 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001293 else
1294 {
1295 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001296 wint_t ch = static_cast<wint_t>(*low);
1297 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001298 *vec |= space;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001299#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
Marshall Clow88c31902013-02-07 14:22:51 +00001300 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001301 *vec |= print;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001302#endif
Marshall Clow88c31902013-02-07 14:22:51 +00001303 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001304 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001305 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001306 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001307 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001308 *vec |= lower;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001309#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
Marshall Clow88c31902013-02-07 14:22:51 +00001310 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001311 *vec |= alpha;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001312#endif
Marshall Clow88c31902013-02-07 14:22:51 +00001313 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001314 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001315 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001316 *vec |= punct;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001317#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
Marshall Clow88c31902013-02-07 14:22:51 +00001318 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001319 *vec |= xdigit;
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001320#endif
Jonathan Roelofsf77031d2015-03-13 15:09:42 +00001321#if !defined(__sun__)
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001322 if (iswblank_l(ch, __l))
1323 *vec |= blank;
Jonathan Roelofsf77031d2015-03-13 15:09:42 +00001324#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001325 }
1326 }
1327 return low;
1328}
1329
1330const wchar_t*
1331ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1332{
1333 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001334 {
1335#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001336 if (iswctype_l(*low, m, __l))
1337 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001338#else
Marshall Clow88c31902013-02-07 14:22:51 +00001339 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001340 if ((m & space) == space && iswspace_l(ch, __l)) break;
1341 if ((m & print) == print && iswprint_l(ch, __l)) break;
1342 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break;
1343 if ((m & upper) == upper && iswupper_l(ch, __l)) break;
1344 if ((m & lower) == lower && iswlower_l(ch, __l)) break;
1345 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break;
1346 if ((m & digit) == digit && iswdigit_l(ch, __l)) break;
1347 if ((m & punct) == punct && iswpunct_l(ch, __l)) break;
1348 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break;
1349 if ((m & blank) == blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001350#endif
1351 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001352 return low;
1353}
1354
1355const wchar_t*
1356ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1357{
1358 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001359 {
1360#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001361 if (!iswctype_l(*low, m, __l))
1362 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001363#else
Marshall Clow88c31902013-02-07 14:22:51 +00001364 wint_t ch = static_cast<wint_t>(*low);
Jonathan Roelofs6fb33ea2015-03-11 17:00:28 +00001365 if ((m & space) == space && iswspace_l(ch, __l)) continue;
1366 if ((m & print) == print && iswprint_l(ch, __l)) continue;
1367 if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue;
1368 if ((m & upper) == upper && iswupper_l(ch, __l)) continue;
1369 if ((m & lower) == lower && iswlower_l(ch, __l)) continue;
1370 if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue;
1371 if ((m & digit) == digit && iswdigit_l(ch, __l)) continue;
1372 if ((m & punct) == punct && iswpunct_l(ch, __l)) continue;
1373 if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue;
1374 if ((m & blank) == blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001375 break;
1376#endif
1377 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001378 return low;
1379}
1380
1381wchar_t
1382ctype_byname<wchar_t>::do_toupper(char_type c) const
1383{
1384 return towupper_l(c, __l);
1385}
1386
1387const wchar_t*
1388ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1389{
1390 for (; low != high; ++low)
1391 *low = towupper_l(*low, __l);
1392 return low;
1393}
1394
1395wchar_t
1396ctype_byname<wchar_t>::do_tolower(char_type c) const
1397{
1398 return towlower_l(c, __l);
1399}
1400
1401const wchar_t*
1402ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1403{
1404 for (; low != high; ++low)
1405 *low = towlower_l(*low, __l);
1406 return low;
1407}
1408
1409wchar_t
1410ctype_byname<wchar_t>::do_widen(char c) const
1411{
Howard Hinnant866569b2011-09-28 23:39:33 +00001412#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001413 return btowc_l(c, __l);
1414#else
1415 return __btowc_l(c, __l);
1416#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001417}
1418
1419const char*
1420ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1421{
1422 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001423#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001424 *dest = btowc_l(*low, __l);
1425#else
1426 *dest = __btowc_l(*low, __l);
1427#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001428 return low;
1429}
1430
1431char
1432ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1433{
Howard Hinnant866569b2011-09-28 23:39:33 +00001434#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001435 int r = wctob_l(c, __l);
1436#else
1437 int r = __wctob_l(c, __l);
1438#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001439 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001440}
1441
1442const wchar_t*
1443ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1444{
1445 for (; low != high; ++low, ++dest)
1446 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001447#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001448 int r = wctob_l(*low, __l);
1449#else
1450 int r = __wctob_l(*low, __l);
1451#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001452 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001453 }
1454 return low;
1455}
1456
1457// template <> class codecvt<char, char, mbstate_t>
1458
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001459locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001460
1461codecvt<char, char, mbstate_t>::~codecvt()
1462{
1463}
1464
1465codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001466codecvt<char, char, mbstate_t>::do_out(state_type&,
1467 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001468 extern_type* to, extern_type*, extern_type*& to_nxt) const
1469{
1470 frm_nxt = frm;
1471 to_nxt = to;
1472 return noconv;
1473}
1474
1475codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001476codecvt<char, char, mbstate_t>::do_in(state_type&,
1477 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001478 intern_type* to, intern_type*, intern_type*& to_nxt) const
1479{
1480 frm_nxt = frm;
1481 to_nxt = to;
1482 return noconv;
1483}
1484
1485codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001486codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001487 extern_type* to, extern_type*, extern_type*& to_nxt) const
1488{
1489 to_nxt = to;
1490 return noconv;
1491}
1492
1493int
Howard Hinnantc9834542011-05-31 15:34:58 +00001494codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001495{
1496 return 1;
1497}
1498
1499bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001500codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001501{
1502 return true;
1503}
1504
1505int
1506codecvt<char, char, mbstate_t>::do_length(state_type&,
1507 const extern_type* frm, const extern_type* end, size_t mx) const
1508{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001509 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001510}
1511
1512int
Howard Hinnantc9834542011-05-31 15:34:58 +00001513codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001514{
1515 return 1;
1516}
1517
1518// template <> class codecvt<wchar_t, char, mbstate_t>
1519
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001520locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001521
1522codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1523 : locale::facet(refs),
Joerg Sonnenberger5328cd32013-05-09 19:00:18 +00001524 __l(_LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001525{
1526}
1527
1528codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1529 : locale::facet(refs),
1530 __l(newlocale(LC_ALL_MASK, nm, 0))
1531{
Howard Hinnantd4444702010-08-11 17:04:31 +00001532#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001533 if (__l == 0)
1534 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1535 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001536#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001537}
1538
1539codecvt<wchar_t, char, mbstate_t>::~codecvt()
1540{
Joerg Sonnenbergerbe764c92013-05-09 23:06:35 +00001541 if (__l != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001542 freelocale(__l);
1543}
1544
1545codecvt<wchar_t, char, mbstate_t>::result
1546codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001547 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001548 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1549{
1550 // look for first internal null in frm
1551 const intern_type* fend = frm;
1552 for (; fend != frm_end; ++fend)
1553 if (*fend == 0)
1554 break;
1555 // loop over all null-terminated sequences in frm
1556 to_nxt = to;
1557 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1558 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001559 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001560 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001561#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001562 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1563 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001564#else
1565 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1566#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001567 if (n == size_t(-1))
1568 {
1569 // need to recover to_nxt
1570 for (to_nxt = to; frm != frm_nxt; ++frm)
1571 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001572#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001573 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1574#else
1575 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1576#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001577 if (n == size_t(-1))
1578 break;
1579 to_nxt += n;
1580 }
1581 frm_nxt = frm;
1582 return error;
1583 }
1584 if (n == 0)
1585 return partial;
1586 to_nxt += n;
1587 if (to_nxt == to_end)
1588 break;
1589 if (fend != frm_end) // set up next null terminated sequence
1590 {
1591 // Try to write the terminating null
1592 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001593#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001594 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1595#else
1596 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1597#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001598 if (n == size_t(-1)) // on error
1599 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001600 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001601 return partial;
1602 for (extern_type* p = tmp; n; --n) // write it
1603 *to_nxt++ = *p++;
1604 ++frm_nxt;
1605 // look for next null in frm
1606 for (fend = frm_nxt; fend != frm_end; ++fend)
1607 if (*fend == 0)
1608 break;
1609 }
1610 }
1611 return frm_nxt == frm_end ? ok : partial;
1612}
1613
1614codecvt<wchar_t, char, mbstate_t>::result
1615codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001616 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001617 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1618{
1619 // look for first internal null in frm
1620 const extern_type* fend = frm;
1621 for (; fend != frm_end; ++fend)
1622 if (*fend == 0)
1623 break;
1624 // loop over all null-terminated sequences in frm
1625 to_nxt = to;
1626 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1627 {
Joerg Sonnenbergerdf418212013-04-26 09:40:18 +00001628 // save state in case it is needed to recover to_nxt on error
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001629 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001630#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001631 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1632 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001633#else
1634 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1635#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001636 if (n == size_t(-1))
1637 {
1638 // need to recover to_nxt
1639 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1640 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001641#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001642 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1643 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001644#else
1645 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1646#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001647 switch (n)
1648 {
1649 case 0:
1650 ++frm;
1651 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001652 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001653 frm_nxt = frm;
1654 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001655 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001656 frm_nxt = frm;
1657 return partial;
1658 default:
1659 frm += n;
1660 break;
1661 }
1662 }
1663 frm_nxt = frm;
1664 return frm_nxt == frm_end ? ok : partial;
1665 }
Joerg Sonnenberger64c62482015-06-05 15:54:26 +00001666 if (n == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001667 return error;
1668 to_nxt += n;
1669 if (to_nxt == to_end)
1670 break;
1671 if (fend != frm_end) // set up next null terminated sequence
1672 {
1673 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001674#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001675 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1676#else
1677 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1678#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001679 if (n != 0) // on error
1680 return error;
1681 ++to_nxt;
1682 ++frm_nxt;
1683 // look for next null in frm
1684 for (fend = frm_nxt; fend != frm_end; ++fend)
1685 if (*fend == 0)
1686 break;
1687 }
1688 }
1689 return frm_nxt == frm_end ? ok : partial;
1690}
1691
1692codecvt<wchar_t, char, mbstate_t>::result
1693codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1694 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1695{
1696 to_nxt = to;
1697 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001698#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001699 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1700#else
1701 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1702#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001703 if (n == size_t(-1) || n == 0) // on error
1704 return error;
1705 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001706 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001707 return partial;
1708 for (extern_type* p = tmp; n; --n) // write it
1709 *to_nxt++ = *p++;
1710 return ok;
1711}
1712
1713int
Howard Hinnantc9834542011-05-31 15:34:58 +00001714codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001715{
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001716#ifndef __CloudABI__
Howard Hinnant866569b2011-09-28 23:39:33 +00001717#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001718 if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Sean Huntf3907e62011-07-15 05:40:33 +00001719#else
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001720 if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0)
Sean Huntf3907e62011-07-15 05:40:33 +00001721#endif
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001722 return -1;
1723#endif
1724
1725 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001726#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001727 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
Sean Huntf3907e62011-07-15 05:40:33 +00001728#else
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001729 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
Sean Huntf3907e62011-07-15 05:40:33 +00001730#endif
Ed Schouten7c1ebcf2015-07-06 15:39:36 +00001731 return 1; // which take more than 1 char to form a wchar_t
1732 return 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001733}
1734
1735bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001736codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001737{
1738 return false;
1739}
1740
1741int
1742codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1743 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1744{
1745 int nbytes = 0;
1746 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1747 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001748#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001749 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001750#else
1751 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1752#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001753 switch (n)
1754 {
1755 case 0:
1756 ++nbytes;
1757 ++frm;
1758 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001759 case size_t(-1):
1760 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001761 return nbytes;
1762 default:
1763 nbytes += n;
1764 frm += n;
1765 break;
1766 }
1767 }
1768 return nbytes;
1769}
1770
1771int
Howard Hinnantc9834542011-05-31 15:34:58 +00001772codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001773{
Howard Hinnant866569b2011-09-28 23:39:33 +00001774#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001775 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001776#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001777 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001778#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001779}
1780
1781// Valid UTF ranges
1782// UTF-32 UTF-16 UTF-8 # of code points
1783// first second first second third fourth
1784// 000000 - 00007F 0000 - 007F 00 - 7F 127
1785// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1786// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1787// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1788// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1789// 00D800 - 00DFFF invalid
1790// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1791// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1792// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1793// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1794
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001795static
1796codecvt_base::result
1797utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1798 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1799 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1800{
1801 frm_nxt = frm;
1802 to_nxt = to;
1803 if (mode & generate_header)
1804 {
1805 if (to_end-to_nxt < 3)
1806 return codecvt_base::partial;
1807 *to_nxt++ = static_cast<uint8_t>(0xEF);
1808 *to_nxt++ = static_cast<uint8_t>(0xBB);
1809 *to_nxt++ = static_cast<uint8_t>(0xBF);
1810 }
1811 for (; frm_nxt < frm_end; ++frm_nxt)
1812 {
1813 uint16_t wc1 = *frm_nxt;
1814 if (wc1 > Maxcode)
1815 return codecvt_base::error;
1816 if (wc1 < 0x0080)
1817 {
1818 if (to_end-to_nxt < 1)
1819 return codecvt_base::partial;
1820 *to_nxt++ = static_cast<uint8_t>(wc1);
1821 }
1822 else if (wc1 < 0x0800)
1823 {
1824 if (to_end-to_nxt < 2)
1825 return codecvt_base::partial;
1826 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1827 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1828 }
1829 else if (wc1 < 0xD800)
1830 {
1831 if (to_end-to_nxt < 3)
1832 return codecvt_base::partial;
1833 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1834 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1835 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1836 }
1837 else if (wc1 < 0xDC00)
1838 {
1839 if (frm_end-frm_nxt < 2)
1840 return codecvt_base::partial;
1841 uint16_t wc2 = frm_nxt[1];
1842 if ((wc2 & 0xFC00) != 0xDC00)
1843 return codecvt_base::error;
1844 if (to_end-to_nxt < 4)
1845 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001846 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1847 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001848 return codecvt_base::error;
1849 ++frm_nxt;
1850 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1851 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1852 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1853 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1854 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1855 }
1856 else if (wc1 < 0xE000)
1857 {
1858 return codecvt_base::error;
1859 }
1860 else
1861 {
1862 if (to_end-to_nxt < 3)
1863 return codecvt_base::partial;
1864 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1865 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1866 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1867 }
1868 }
1869 return codecvt_base::ok;
1870}
1871
1872static
1873codecvt_base::result
1874utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1875 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1876 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1877{
1878 frm_nxt = frm;
1879 to_nxt = to;
1880 if (mode & generate_header)
1881 {
1882 if (to_end-to_nxt < 3)
1883 return codecvt_base::partial;
1884 *to_nxt++ = static_cast<uint8_t>(0xEF);
1885 *to_nxt++ = static_cast<uint8_t>(0xBB);
1886 *to_nxt++ = static_cast<uint8_t>(0xBF);
1887 }
1888 for (; frm_nxt < frm_end; ++frm_nxt)
1889 {
1890 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1891 if (wc1 > Maxcode)
1892 return codecvt_base::error;
1893 if (wc1 < 0x0080)
1894 {
1895 if (to_end-to_nxt < 1)
1896 return codecvt_base::partial;
1897 *to_nxt++ = static_cast<uint8_t>(wc1);
1898 }
1899 else if (wc1 < 0x0800)
1900 {
1901 if (to_end-to_nxt < 2)
1902 return codecvt_base::partial;
1903 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1904 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1905 }
1906 else if (wc1 < 0xD800)
1907 {
1908 if (to_end-to_nxt < 3)
1909 return codecvt_base::partial;
1910 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1911 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1912 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1913 }
1914 else if (wc1 < 0xDC00)
1915 {
1916 if (frm_end-frm_nxt < 2)
1917 return codecvt_base::partial;
1918 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1919 if ((wc2 & 0xFC00) != 0xDC00)
1920 return codecvt_base::error;
1921 if (to_end-to_nxt < 4)
1922 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00001923 if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) +
1924 ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001925 return codecvt_base::error;
1926 ++frm_nxt;
1927 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1928 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1929 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1930 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1931 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1932 }
1933 else if (wc1 < 0xE000)
1934 {
1935 return codecvt_base::error;
1936 }
1937 else
1938 {
1939 if (to_end-to_nxt < 3)
1940 return codecvt_base::partial;
1941 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1942 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1943 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1944 }
1945 }
1946 return codecvt_base::ok;
1947}
1948
1949static
1950codecvt_base::result
1951utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1952 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1953 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1954{
1955 frm_nxt = frm;
1956 to_nxt = to;
1957 if (mode & consume_header)
1958 {
1959 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1960 frm_nxt[2] == 0xBF)
1961 frm_nxt += 3;
1962 }
1963 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1964 {
1965 uint8_t c1 = *frm_nxt;
1966 if (c1 > Maxcode)
1967 return codecvt_base::error;
1968 if (c1 < 0x80)
1969 {
1970 *to_nxt = static_cast<uint16_t>(c1);
1971 ++frm_nxt;
1972 }
1973 else if (c1 < 0xC2)
1974 {
1975 return codecvt_base::error;
1976 }
1977 else if (c1 < 0xE0)
1978 {
1979 if (frm_end-frm_nxt < 2)
1980 return codecvt_base::partial;
1981 uint8_t c2 = frm_nxt[1];
1982 if ((c2 & 0xC0) != 0x80)
1983 return codecvt_base::error;
1984 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1985 if (t > Maxcode)
1986 return codecvt_base::error;
1987 *to_nxt = t;
1988 frm_nxt += 2;
1989 }
1990 else if (c1 < 0xF0)
1991 {
1992 if (frm_end-frm_nxt < 3)
1993 return codecvt_base::partial;
1994 uint8_t c2 = frm_nxt[1];
1995 uint8_t c3 = frm_nxt[2];
1996 switch (c1)
1997 {
1998 case 0xE0:
1999 if ((c2 & 0xE0) != 0xA0)
2000 return codecvt_base::error;
2001 break;
2002 case 0xED:
2003 if ((c2 & 0xE0) != 0x80)
2004 return codecvt_base::error;
2005 break;
2006 default:
2007 if ((c2 & 0xC0) != 0x80)
2008 return codecvt_base::error;
2009 break;
2010 }
2011 if ((c3 & 0xC0) != 0x80)
2012 return codecvt_base::error;
2013 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2014 | ((c2 & 0x3F) << 6)
2015 | (c3 & 0x3F));
2016 if (t > Maxcode)
2017 return codecvt_base::error;
2018 *to_nxt = t;
2019 frm_nxt += 3;
2020 }
2021 else if (c1 < 0xF5)
2022 {
2023 if (frm_end-frm_nxt < 4)
2024 return codecvt_base::partial;
2025 uint8_t c2 = frm_nxt[1];
2026 uint8_t c3 = frm_nxt[2];
2027 uint8_t c4 = frm_nxt[3];
2028 switch (c1)
2029 {
2030 case 0xF0:
2031 if (!(0x90 <= c2 && c2 <= 0xBF))
2032 return codecvt_base::error;
2033 break;
2034 case 0xF4:
2035 if ((c2 & 0xF0) != 0x80)
2036 return codecvt_base::error;
2037 break;
2038 default:
2039 if ((c2 & 0xC0) != 0x80)
2040 return codecvt_base::error;
2041 break;
2042 }
2043 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2044 return codecvt_base::error;
2045 if (to_end-to_nxt < 2)
2046 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002047 if ((((c1 & 7UL) << 18) +
2048 ((c2 & 0x3FUL) << 12) +
2049 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002050 return codecvt_base::error;
2051 *to_nxt = static_cast<uint16_t>(
2052 0xD800
2053 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2054 | ((c2 & 0x0F) << 2)
2055 | ((c3 & 0x30) >> 4));
2056 *++to_nxt = static_cast<uint16_t>(
2057 0xDC00
2058 | ((c3 & 0x0F) << 6)
2059 | (c4 & 0x3F));
2060 frm_nxt += 4;
2061 }
2062 else
2063 {
2064 return codecvt_base::error;
2065 }
2066 }
2067 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2068}
2069
2070static
2071codecvt_base::result
2072utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2073 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2074 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2075{
2076 frm_nxt = frm;
2077 to_nxt = to;
2078 if (mode & consume_header)
2079 {
2080 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2081 frm_nxt[2] == 0xBF)
2082 frm_nxt += 3;
2083 }
2084 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2085 {
2086 uint8_t c1 = *frm_nxt;
2087 if (c1 > Maxcode)
2088 return codecvt_base::error;
2089 if (c1 < 0x80)
2090 {
2091 *to_nxt = static_cast<uint32_t>(c1);
2092 ++frm_nxt;
2093 }
2094 else if (c1 < 0xC2)
2095 {
2096 return codecvt_base::error;
2097 }
2098 else if (c1 < 0xE0)
2099 {
2100 if (frm_end-frm_nxt < 2)
2101 return codecvt_base::partial;
2102 uint8_t c2 = frm_nxt[1];
2103 if ((c2 & 0xC0) != 0x80)
2104 return codecvt_base::error;
2105 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
2106 if (t > Maxcode)
2107 return codecvt_base::error;
2108 *to_nxt = static_cast<uint32_t>(t);
2109 frm_nxt += 2;
2110 }
2111 else if (c1 < 0xF0)
2112 {
2113 if (frm_end-frm_nxt < 3)
2114 return codecvt_base::partial;
2115 uint8_t c2 = frm_nxt[1];
2116 uint8_t c3 = frm_nxt[2];
2117 switch (c1)
2118 {
2119 case 0xE0:
2120 if ((c2 & 0xE0) != 0xA0)
2121 return codecvt_base::error;
2122 break;
2123 case 0xED:
2124 if ((c2 & 0xE0) != 0x80)
2125 return codecvt_base::error;
2126 break;
2127 default:
2128 if ((c2 & 0xC0) != 0x80)
2129 return codecvt_base::error;
2130 break;
2131 }
2132 if ((c3 & 0xC0) != 0x80)
2133 return codecvt_base::error;
2134 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2135 | ((c2 & 0x3F) << 6)
2136 | (c3 & 0x3F));
2137 if (t > Maxcode)
2138 return codecvt_base::error;
2139 *to_nxt = static_cast<uint32_t>(t);
2140 frm_nxt += 3;
2141 }
2142 else if (c1 < 0xF5)
2143 {
2144 if (frm_end-frm_nxt < 4)
2145 return codecvt_base::partial;
2146 uint8_t c2 = frm_nxt[1];
2147 uint8_t c3 = frm_nxt[2];
2148 uint8_t c4 = frm_nxt[3];
2149 switch (c1)
2150 {
2151 case 0xF0:
2152 if (!(0x90 <= c2 && c2 <= 0xBF))
2153 return codecvt_base::error;
2154 break;
2155 case 0xF4:
2156 if ((c2 & 0xF0) != 0x80)
2157 return codecvt_base::error;
2158 break;
2159 default:
2160 if ((c2 & 0xC0) != 0x80)
2161 return codecvt_base::error;
2162 break;
2163 }
2164 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2165 return codecvt_base::error;
2166 if (to_end-to_nxt < 2)
2167 return codecvt_base::partial;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002168 if ((((c1 & 7UL) << 18) +
2169 ((c2 & 0x3FUL) << 12) +
2170 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002171 return codecvt_base::error;
2172 *to_nxt = static_cast<uint32_t>(
2173 0xD800
2174 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2175 | ((c2 & 0x0F) << 2)
2176 | ((c3 & 0x30) >> 4));
2177 *++to_nxt = static_cast<uint32_t>(
2178 0xDC00
2179 | ((c3 & 0x0F) << 6)
2180 | (c4 & 0x3F));
2181 frm_nxt += 4;
2182 }
2183 else
2184 {
2185 return codecvt_base::error;
2186 }
2187 }
2188 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2189}
2190
2191static
2192int
2193utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2194 size_t mx, unsigned long Maxcode = 0x10FFFF,
2195 codecvt_mode mode = codecvt_mode(0))
2196{
2197 const uint8_t* frm_nxt = frm;
2198 if (mode & consume_header)
2199 {
2200 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2201 frm_nxt[2] == 0xBF)
2202 frm_nxt += 3;
2203 }
2204 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2205 {
2206 uint8_t c1 = *frm_nxt;
2207 if (c1 > Maxcode)
2208 break;
2209 if (c1 < 0x80)
2210 {
2211 ++frm_nxt;
2212 }
2213 else if (c1 < 0xC2)
2214 {
2215 break;
2216 }
2217 else if (c1 < 0xE0)
2218 {
2219 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2220 break;
2221 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2222 if (t > Maxcode)
2223 break;
2224 frm_nxt += 2;
2225 }
2226 else if (c1 < 0xF0)
2227 {
2228 if (frm_end-frm_nxt < 3)
2229 break;
2230 uint8_t c2 = frm_nxt[1];
2231 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002232 switch (c1)
2233 {
2234 case 0xE0:
2235 if ((c2 & 0xE0) != 0xA0)
2236 return static_cast<int>(frm_nxt - frm);
2237 break;
2238 case 0xED:
2239 if ((c2 & 0xE0) != 0x80)
2240 return static_cast<int>(frm_nxt - frm);
2241 break;
2242 default:
2243 if ((c2 & 0xC0) != 0x80)
2244 return static_cast<int>(frm_nxt - frm);
2245 break;
2246 }
2247 if ((c3 & 0xC0) != 0x80)
2248 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002249 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002250 break;
2251 frm_nxt += 3;
2252 }
2253 else if (c1 < 0xF5)
2254 {
2255 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2256 break;
2257 uint8_t c2 = frm_nxt[1];
2258 uint8_t c3 = frm_nxt[2];
2259 uint8_t c4 = frm_nxt[3];
2260 switch (c1)
2261 {
2262 case 0xF0:
2263 if (!(0x90 <= c2 && c2 <= 0xBF))
2264 return static_cast<int>(frm_nxt - frm);
2265 break;
2266 case 0xF4:
2267 if ((c2 & 0xF0) != 0x80)
2268 return static_cast<int>(frm_nxt - frm);
2269 break;
2270 default:
2271 if ((c2 & 0xC0) != 0x80)
2272 return static_cast<int>(frm_nxt - frm);
2273 break;
2274 }
2275 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2276 break;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +00002277 if ((((c1 & 7UL) << 18) +
2278 ((c2 & 0x3FUL) << 12) +
2279 ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002280 break;
2281 ++nchar16_t;
2282 frm_nxt += 4;
2283 }
2284 else
2285 {
2286 break;
2287 }
2288 }
2289 return static_cast<int>(frm_nxt - frm);
2290}
2291
2292static
2293codecvt_base::result
2294ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2295 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2296 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2297{
2298 frm_nxt = frm;
2299 to_nxt = to;
2300 if (mode & generate_header)
2301 {
2302 if (to_end-to_nxt < 3)
2303 return codecvt_base::partial;
2304 *to_nxt++ = static_cast<uint8_t>(0xEF);
2305 *to_nxt++ = static_cast<uint8_t>(0xBB);
2306 *to_nxt++ = static_cast<uint8_t>(0xBF);
2307 }
2308 for (; frm_nxt < frm_end; ++frm_nxt)
2309 {
2310 uint32_t wc = *frm_nxt;
2311 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2312 return codecvt_base::error;
2313 if (wc < 0x000080)
2314 {
2315 if (to_end-to_nxt < 1)
2316 return codecvt_base::partial;
2317 *to_nxt++ = static_cast<uint8_t>(wc);
2318 }
2319 else if (wc < 0x000800)
2320 {
2321 if (to_end-to_nxt < 2)
2322 return codecvt_base::partial;
2323 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2324 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2325 }
2326 else if (wc < 0x010000)
2327 {
2328 if (to_end-to_nxt < 3)
2329 return codecvt_base::partial;
2330 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2331 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2332 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2333 }
2334 else // if (wc < 0x110000)
2335 {
2336 if (to_end-to_nxt < 4)
2337 return codecvt_base::partial;
2338 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2339 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2340 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2341 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2342 }
2343 }
2344 return codecvt_base::ok;
2345}
2346
2347static
2348codecvt_base::result
2349utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2350 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2351 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2352{
2353 frm_nxt = frm;
2354 to_nxt = to;
2355 if (mode & consume_header)
2356 {
2357 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2358 frm_nxt[2] == 0xBF)
2359 frm_nxt += 3;
2360 }
2361 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2362 {
2363 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2364 if (c1 < 0x80)
2365 {
2366 if (c1 > Maxcode)
2367 return codecvt_base::error;
2368 *to_nxt = static_cast<uint32_t>(c1);
2369 ++frm_nxt;
2370 }
2371 else if (c1 < 0xC2)
2372 {
2373 return codecvt_base::error;
2374 }
2375 else if (c1 < 0xE0)
2376 {
2377 if (frm_end-frm_nxt < 2)
2378 return codecvt_base::partial;
2379 uint8_t c2 = frm_nxt[1];
2380 if ((c2 & 0xC0) != 0x80)
2381 return codecvt_base::error;
2382 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2383 | (c2 & 0x3F));
2384 if (t > Maxcode)
2385 return codecvt_base::error;
2386 *to_nxt = t;
2387 frm_nxt += 2;
2388 }
2389 else if (c1 < 0xF0)
2390 {
2391 if (frm_end-frm_nxt < 3)
2392 return codecvt_base::partial;
2393 uint8_t c2 = frm_nxt[1];
2394 uint8_t c3 = frm_nxt[2];
2395 switch (c1)
2396 {
2397 case 0xE0:
2398 if ((c2 & 0xE0) != 0xA0)
2399 return codecvt_base::error;
2400 break;
2401 case 0xED:
2402 if ((c2 & 0xE0) != 0x80)
2403 return codecvt_base::error;
2404 break;
2405 default:
2406 if ((c2 & 0xC0) != 0x80)
2407 return codecvt_base::error;
2408 break;
2409 }
2410 if ((c3 & 0xC0) != 0x80)
2411 return codecvt_base::error;
2412 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2413 | ((c2 & 0x3F) << 6)
2414 | (c3 & 0x3F));
2415 if (t > Maxcode)
2416 return codecvt_base::error;
2417 *to_nxt = t;
2418 frm_nxt += 3;
2419 }
2420 else if (c1 < 0xF5)
2421 {
2422 if (frm_end-frm_nxt < 4)
2423 return codecvt_base::partial;
2424 uint8_t c2 = frm_nxt[1];
2425 uint8_t c3 = frm_nxt[2];
2426 uint8_t c4 = frm_nxt[3];
2427 switch (c1)
2428 {
2429 case 0xF0:
2430 if (!(0x90 <= c2 && c2 <= 0xBF))
2431 return codecvt_base::error;
2432 break;
2433 case 0xF4:
2434 if ((c2 & 0xF0) != 0x80)
2435 return codecvt_base::error;
2436 break;
2437 default:
2438 if ((c2 & 0xC0) != 0x80)
2439 return codecvt_base::error;
2440 break;
2441 }
2442 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2443 return codecvt_base::error;
2444 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2445 | ((c2 & 0x3F) << 12)
2446 | ((c3 & 0x3F) << 6)
2447 | (c4 & 0x3F));
2448 if (t > Maxcode)
2449 return codecvt_base::error;
2450 *to_nxt = t;
2451 frm_nxt += 4;
2452 }
2453 else
2454 {
2455 return codecvt_base::error;
2456 }
2457 }
2458 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2459}
2460
2461static
2462int
2463utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2464 size_t mx, unsigned long Maxcode = 0x10FFFF,
2465 codecvt_mode mode = codecvt_mode(0))
2466{
2467 const uint8_t* frm_nxt = frm;
2468 if (mode & consume_header)
2469 {
2470 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2471 frm_nxt[2] == 0xBF)
2472 frm_nxt += 3;
2473 }
2474 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2475 {
2476 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2477 if (c1 < 0x80)
2478 {
2479 if (c1 > Maxcode)
2480 break;
2481 ++frm_nxt;
2482 }
2483 else if (c1 < 0xC2)
2484 {
2485 break;
2486 }
2487 else if (c1 < 0xE0)
2488 {
2489 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2490 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002491 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002492 break;
2493 frm_nxt += 2;
2494 }
2495 else if (c1 < 0xF0)
2496 {
2497 if (frm_end-frm_nxt < 3)
2498 break;
2499 uint8_t c2 = frm_nxt[1];
2500 uint8_t c3 = frm_nxt[2];
2501 switch (c1)
2502 {
2503 case 0xE0:
2504 if ((c2 & 0xE0) != 0xA0)
2505 return static_cast<int>(frm_nxt - frm);
2506 break;
2507 case 0xED:
2508 if ((c2 & 0xE0) != 0x80)
2509 return static_cast<int>(frm_nxt - frm);
2510 break;
2511 default:
2512 if ((c2 & 0xC0) != 0x80)
2513 return static_cast<int>(frm_nxt - frm);
2514 break;
2515 }
2516 if ((c3 & 0xC0) != 0x80)
2517 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002518 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002519 break;
2520 frm_nxt += 3;
2521 }
2522 else if (c1 < 0xF5)
2523 {
2524 if (frm_end-frm_nxt < 4)
2525 break;
2526 uint8_t c2 = frm_nxt[1];
2527 uint8_t c3 = frm_nxt[2];
2528 uint8_t c4 = frm_nxt[3];
2529 switch (c1)
2530 {
2531 case 0xF0:
2532 if (!(0x90 <= c2 && c2 <= 0xBF))
2533 return static_cast<int>(frm_nxt - frm);
2534 break;
2535 case 0xF4:
2536 if ((c2 & 0xF0) != 0x80)
2537 return static_cast<int>(frm_nxt - frm);
2538 break;
2539 default:
2540 if ((c2 & 0xC0) != 0x80)
2541 return static_cast<int>(frm_nxt - frm);
2542 break;
2543 }
2544 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2545 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002546 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2547 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002548 break;
2549 frm_nxt += 4;
2550 }
2551 else
2552 {
2553 break;
2554 }
2555 }
2556 return static_cast<int>(frm_nxt - frm);
2557}
2558
2559static
2560codecvt_base::result
2561ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2562 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2563 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2564{
2565 frm_nxt = frm;
2566 to_nxt = to;
2567 if (mode & generate_header)
2568 {
2569 if (to_end-to_nxt < 3)
2570 return codecvt_base::partial;
2571 *to_nxt++ = static_cast<uint8_t>(0xEF);
2572 *to_nxt++ = static_cast<uint8_t>(0xBB);
2573 *to_nxt++ = static_cast<uint8_t>(0xBF);
2574 }
2575 for (; frm_nxt < frm_end; ++frm_nxt)
2576 {
2577 uint16_t wc = *frm_nxt;
2578 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2579 return codecvt_base::error;
2580 if (wc < 0x0080)
2581 {
2582 if (to_end-to_nxt < 1)
2583 return codecvt_base::partial;
2584 *to_nxt++ = static_cast<uint8_t>(wc);
2585 }
2586 else if (wc < 0x0800)
2587 {
2588 if (to_end-to_nxt < 2)
2589 return codecvt_base::partial;
2590 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2591 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2592 }
2593 else // if (wc <= 0xFFFF)
2594 {
2595 if (to_end-to_nxt < 3)
2596 return codecvt_base::partial;
2597 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2598 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2599 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2600 }
2601 }
2602 return codecvt_base::ok;
2603}
2604
2605static
2606codecvt_base::result
2607utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2608 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2609 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2610{
2611 frm_nxt = frm;
2612 to_nxt = to;
2613 if (mode & consume_header)
2614 {
2615 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2616 frm_nxt[2] == 0xBF)
2617 frm_nxt += 3;
2618 }
2619 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2620 {
2621 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2622 if (c1 < 0x80)
2623 {
2624 if (c1 > Maxcode)
2625 return codecvt_base::error;
2626 *to_nxt = static_cast<uint16_t>(c1);
2627 ++frm_nxt;
2628 }
2629 else if (c1 < 0xC2)
2630 {
2631 return codecvt_base::error;
2632 }
2633 else if (c1 < 0xE0)
2634 {
2635 if (frm_end-frm_nxt < 2)
2636 return codecvt_base::partial;
2637 uint8_t c2 = frm_nxt[1];
2638 if ((c2 & 0xC0) != 0x80)
2639 return codecvt_base::error;
2640 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2641 | (c2 & 0x3F));
2642 if (t > Maxcode)
2643 return codecvt_base::error;
2644 *to_nxt = t;
2645 frm_nxt += 2;
2646 }
2647 else if (c1 < 0xF0)
2648 {
2649 if (frm_end-frm_nxt < 3)
2650 return codecvt_base::partial;
2651 uint8_t c2 = frm_nxt[1];
2652 uint8_t c3 = frm_nxt[2];
2653 switch (c1)
2654 {
2655 case 0xE0:
2656 if ((c2 & 0xE0) != 0xA0)
2657 return codecvt_base::error;
2658 break;
2659 case 0xED:
2660 if ((c2 & 0xE0) != 0x80)
2661 return codecvt_base::error;
2662 break;
2663 default:
2664 if ((c2 & 0xC0) != 0x80)
2665 return codecvt_base::error;
2666 break;
2667 }
2668 if ((c3 & 0xC0) != 0x80)
2669 return codecvt_base::error;
2670 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2671 | ((c2 & 0x3F) << 6)
2672 | (c3 & 0x3F));
2673 if (t > Maxcode)
2674 return codecvt_base::error;
2675 *to_nxt = t;
2676 frm_nxt += 3;
2677 }
2678 else
2679 {
2680 return codecvt_base::error;
2681 }
2682 }
2683 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2684}
2685
2686static
2687int
2688utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2689 size_t mx, unsigned long Maxcode = 0x10FFFF,
2690 codecvt_mode mode = codecvt_mode(0))
2691{
2692 const uint8_t* frm_nxt = frm;
2693 if (mode & consume_header)
2694 {
2695 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2696 frm_nxt[2] == 0xBF)
2697 frm_nxt += 3;
2698 }
2699 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2700 {
2701 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2702 if (c1 < 0x80)
2703 {
2704 if (c1 > Maxcode)
2705 break;
2706 ++frm_nxt;
2707 }
2708 else if (c1 < 0xC2)
2709 {
2710 break;
2711 }
2712 else if (c1 < 0xE0)
2713 {
2714 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2715 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002716 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002717 break;
2718 frm_nxt += 2;
2719 }
2720 else if (c1 < 0xF0)
2721 {
2722 if (frm_end-frm_nxt < 3)
2723 break;
2724 uint8_t c2 = frm_nxt[1];
2725 uint8_t c3 = frm_nxt[2];
2726 switch (c1)
2727 {
2728 case 0xE0:
2729 if ((c2 & 0xE0) != 0xA0)
2730 return static_cast<int>(frm_nxt - frm);
2731 break;
2732 case 0xED:
2733 if ((c2 & 0xE0) != 0x80)
2734 return static_cast<int>(frm_nxt - frm);
2735 break;
2736 default:
2737 if ((c2 & 0xC0) != 0x80)
2738 return static_cast<int>(frm_nxt - frm);
2739 break;
2740 }
2741 if ((c3 & 0xC0) != 0x80)
2742 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002743 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002744 break;
2745 frm_nxt += 3;
2746 }
2747 else
2748 {
2749 break;
2750 }
2751 }
2752 return static_cast<int>(frm_nxt - frm);
2753}
2754
2755static
2756codecvt_base::result
2757ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2758 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2759 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2760{
2761 frm_nxt = frm;
2762 to_nxt = to;
2763 if (mode & generate_header)
2764 {
2765 if (to_end-to_nxt < 2)
2766 return codecvt_base::partial;
2767 *to_nxt++ = static_cast<uint8_t>(0xFE);
2768 *to_nxt++ = static_cast<uint8_t>(0xFF);
2769 }
2770 for (; frm_nxt < frm_end; ++frm_nxt)
2771 {
2772 uint32_t wc = *frm_nxt;
2773 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2774 return codecvt_base::error;
2775 if (wc < 0x010000)
2776 {
2777 if (to_end-to_nxt < 2)
2778 return codecvt_base::partial;
2779 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2780 *to_nxt++ = static_cast<uint8_t>(wc);
2781 }
2782 else
2783 {
2784 if (to_end-to_nxt < 4)
2785 return codecvt_base::partial;
2786 uint16_t t = static_cast<uint16_t>(
2787 0xD800
2788 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2789 | ((wc & 0x00FC00) >> 10));
2790 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2791 *to_nxt++ = static_cast<uint8_t>(t);
2792 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2793 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2794 *to_nxt++ = static_cast<uint8_t>(t);
2795 }
2796 }
2797 return codecvt_base::ok;
2798}
2799
2800static
2801codecvt_base::result
2802utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2803 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2804 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2805{
2806 frm_nxt = frm;
2807 to_nxt = to;
2808 if (mode & consume_header)
2809 {
2810 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2811 frm_nxt += 2;
2812 }
2813 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2814 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002815 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002816 if ((c1 & 0xFC00) == 0xDC00)
2817 return codecvt_base::error;
2818 if ((c1 & 0xFC00) != 0xD800)
2819 {
2820 if (c1 > Maxcode)
2821 return codecvt_base::error;
2822 *to_nxt = static_cast<uint32_t>(c1);
2823 frm_nxt += 2;
2824 }
2825 else
2826 {
2827 if (frm_end-frm_nxt < 4)
2828 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002829 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002830 if ((c2 & 0xFC00) != 0xDC00)
2831 return codecvt_base::error;
2832 uint32_t t = static_cast<uint32_t>(
2833 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2834 | ((c1 & 0x003F) << 10)
2835 | (c2 & 0x03FF));
2836 if (t > Maxcode)
2837 return codecvt_base::error;
2838 *to_nxt = t;
2839 frm_nxt += 4;
2840 }
2841 }
2842 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2843}
2844
2845static
2846int
2847utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2848 size_t mx, unsigned long Maxcode = 0x10FFFF,
2849 codecvt_mode mode = codecvt_mode(0))
2850{
2851 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002852 if (mode & consume_header)
2853 {
2854 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2855 frm_nxt += 2;
2856 }
2857 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2858 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002859 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002860 if ((c1 & 0xFC00) == 0xDC00)
2861 break;
2862 if ((c1 & 0xFC00) != 0xD800)
2863 {
2864 if (c1 > Maxcode)
2865 break;
2866 frm_nxt += 2;
2867 }
2868 else
2869 {
2870 if (frm_end-frm_nxt < 4)
2871 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002872 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002873 if ((c2 & 0xFC00) != 0xDC00)
2874 break;
2875 uint32_t t = static_cast<uint32_t>(
2876 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2877 | ((c1 & 0x003F) << 10)
2878 | (c2 & 0x03FF));
2879 if (t > Maxcode)
2880 break;
2881 frm_nxt += 4;
2882 }
2883 }
2884 return static_cast<int>(frm_nxt - frm);
2885}
2886
2887static
2888codecvt_base::result
2889ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2890 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2891 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2892{
2893 frm_nxt = frm;
2894 to_nxt = to;
2895 if (mode & generate_header)
2896 {
2897 if (to_end-to_nxt < 2)
2898 return codecvt_base::partial;
2899 *to_nxt++ = static_cast<uint8_t>(0xFF);
2900 *to_nxt++ = static_cast<uint8_t>(0xFE);
2901 }
2902 for (; frm_nxt < frm_end; ++frm_nxt)
2903 {
2904 uint32_t wc = *frm_nxt;
2905 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2906 return codecvt_base::error;
2907 if (wc < 0x010000)
2908 {
2909 if (to_end-to_nxt < 2)
2910 return codecvt_base::partial;
2911 *to_nxt++ = static_cast<uint8_t>(wc);
2912 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2913 }
2914 else
2915 {
2916 if (to_end-to_nxt < 4)
2917 return codecvt_base::partial;
2918 uint16_t t = static_cast<uint16_t>(
2919 0xD800
2920 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2921 | ((wc & 0x00FC00) >> 10));
2922 *to_nxt++ = static_cast<uint8_t>(t);
2923 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2924 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2925 *to_nxt++ = static_cast<uint8_t>(t);
2926 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2927 }
2928 }
2929 return codecvt_base::ok;
2930}
2931
2932static
2933codecvt_base::result
2934utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2935 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2936 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2937{
2938 frm_nxt = frm;
2939 to_nxt = to;
2940 if (mode & consume_header)
2941 {
2942 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2943 frm_nxt += 2;
2944 }
2945 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2946 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002947 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002948 if ((c1 & 0xFC00) == 0xDC00)
2949 return codecvt_base::error;
2950 if ((c1 & 0xFC00) != 0xD800)
2951 {
2952 if (c1 > Maxcode)
2953 return codecvt_base::error;
2954 *to_nxt = static_cast<uint32_t>(c1);
2955 frm_nxt += 2;
2956 }
2957 else
2958 {
2959 if (frm_end-frm_nxt < 4)
2960 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002961 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002962 if ((c2 & 0xFC00) != 0xDC00)
2963 return codecvt_base::error;
2964 uint32_t t = static_cast<uint32_t>(
2965 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2966 | ((c1 & 0x003F) << 10)
2967 | (c2 & 0x03FF));
2968 if (t > Maxcode)
2969 return codecvt_base::error;
2970 *to_nxt = t;
2971 frm_nxt += 4;
2972 }
2973 }
2974 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2975}
2976
2977static
2978int
2979utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2980 size_t mx, unsigned long Maxcode = 0x10FFFF,
2981 codecvt_mode mode = codecvt_mode(0))
2982{
2983 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002984 if (mode & consume_header)
2985 {
2986 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2987 frm_nxt += 2;
2988 }
2989 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2990 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002991 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002992 if ((c1 & 0xFC00) == 0xDC00)
2993 break;
2994 if ((c1 & 0xFC00) != 0xD800)
2995 {
2996 if (c1 > Maxcode)
2997 break;
2998 frm_nxt += 2;
2999 }
3000 else
3001 {
3002 if (frm_end-frm_nxt < 4)
3003 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00003004 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003005 if ((c2 & 0xFC00) != 0xDC00)
3006 break;
3007 uint32_t t = static_cast<uint32_t>(
3008 ((((c1 & 0x03C0) >> 6) + 1) << 16)
3009 | ((c1 & 0x003F) << 10)
3010 | (c2 & 0x03FF));
3011 if (t > Maxcode)
3012 break;
3013 frm_nxt += 4;
3014 }
3015 }
3016 return static_cast<int>(frm_nxt - frm);
3017}
3018
3019static
3020codecvt_base::result
3021ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3022 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3023 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3024{
3025 frm_nxt = frm;
3026 to_nxt = to;
3027 if (mode & generate_header)
3028 {
3029 if (to_end-to_nxt < 2)
3030 return codecvt_base::partial;
3031 *to_nxt++ = static_cast<uint8_t>(0xFE);
3032 *to_nxt++ = static_cast<uint8_t>(0xFF);
3033 }
3034 for (; frm_nxt < frm_end; ++frm_nxt)
3035 {
3036 uint16_t wc = *frm_nxt;
3037 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3038 return codecvt_base::error;
3039 if (to_end-to_nxt < 2)
3040 return codecvt_base::partial;
3041 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3042 *to_nxt++ = static_cast<uint8_t>(wc);
3043 }
3044 return codecvt_base::ok;
3045}
3046
3047static
3048codecvt_base::result
3049utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3050 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3051 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3052{
3053 frm_nxt = frm;
3054 to_nxt = to;
3055 if (mode & consume_header)
3056 {
3057 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3058 frm_nxt += 2;
3059 }
3060 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3061 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003062 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003063 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3064 return codecvt_base::error;
3065 *to_nxt = c1;
3066 frm_nxt += 2;
3067 }
3068 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3069}
3070
3071static
3072int
3073utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3074 size_t mx, unsigned long Maxcode = 0x10FFFF,
3075 codecvt_mode mode = codecvt_mode(0))
3076{
3077 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003078 if (mode & consume_header)
3079 {
3080 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
3081 frm_nxt += 2;
3082 }
3083 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3084 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003085 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003086 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3087 break;
3088 frm_nxt += 2;
3089 }
3090 return static_cast<int>(frm_nxt - frm);
3091}
3092
3093static
3094codecvt_base::result
3095ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
3096 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
3097 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3098{
3099 frm_nxt = frm;
3100 to_nxt = to;
3101 if (mode & generate_header)
3102 {
3103 if (to_end-to_nxt < 2)
3104 return codecvt_base::partial;
3105 *to_nxt++ = static_cast<uint8_t>(0xFF);
3106 *to_nxt++ = static_cast<uint8_t>(0xFE);
3107 }
3108 for (; frm_nxt < frm_end; ++frm_nxt)
3109 {
3110 uint16_t wc = *frm_nxt;
3111 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
3112 return codecvt_base::error;
3113 if (to_end-to_nxt < 2)
3114 return codecvt_base::partial;
3115 *to_nxt++ = static_cast<uint8_t>(wc);
3116 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
3117 }
3118 return codecvt_base::ok;
3119}
3120
3121static
3122codecvt_base::result
3123utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
3124 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
3125 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
3126{
3127 frm_nxt = frm;
3128 to_nxt = to;
3129 if (mode & consume_header)
3130 {
3131 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3132 frm_nxt += 2;
3133 }
3134 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
3135 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003136 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003137 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3138 return codecvt_base::error;
3139 *to_nxt = c1;
3140 frm_nxt += 2;
3141 }
3142 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
3143}
3144
3145static
3146int
3147utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
3148 size_t mx, unsigned long Maxcode = 0x10FFFF,
3149 codecvt_mode mode = codecvt_mode(0))
3150{
3151 const uint8_t* frm_nxt = frm;
3152 frm_nxt = frm;
3153 if (mode & consume_header)
3154 {
3155 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3156 frm_nxt += 2;
3157 }
3158 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3159 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003160 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003161 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3162 break;
3163 frm_nxt += 2;
3164 }
3165 return static_cast<int>(frm_nxt - frm);
3166}
3167
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003168// template <> class codecvt<char16_t, char, mbstate_t>
3169
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003170locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003171
3172codecvt<char16_t, char, mbstate_t>::~codecvt()
3173{
3174}
3175
3176codecvt<char16_t, char, mbstate_t>::result
3177codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003178 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003179 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3180{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003181 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3182 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3183 const uint16_t* _frm_nxt = _frm;
3184 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3185 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3186 uint8_t* _to_nxt = _to;
3187 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3188 frm_nxt = frm + (_frm_nxt - _frm);
3189 to_nxt = to + (_to_nxt - _to);
3190 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003191}
3192
3193codecvt<char16_t, char, mbstate_t>::result
3194codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003195 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003196 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3197{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003198 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3199 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3200 const uint8_t* _frm_nxt = _frm;
3201 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3202 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3203 uint16_t* _to_nxt = _to;
3204 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3205 frm_nxt = frm + (_frm_nxt - _frm);
3206 to_nxt = to + (_to_nxt - _to);
3207 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003208}
3209
3210codecvt<char16_t, char, mbstate_t>::result
3211codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3212 extern_type* to, extern_type*, extern_type*& to_nxt) const
3213{
3214 to_nxt = to;
3215 return noconv;
3216}
3217
3218int
Howard Hinnantc9834542011-05-31 15:34:58 +00003219codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003220{
3221 return 0;
3222}
3223
3224bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003225codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003226{
3227 return false;
3228}
3229
3230int
3231codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3232 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3233{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003234 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3235 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3236 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003237}
3238
3239int
Howard Hinnantc9834542011-05-31 15:34:58 +00003240codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003241{
3242 return 4;
3243}
3244
3245// template <> class codecvt<char32_t, char, mbstate_t>
3246
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003247locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003248
3249codecvt<char32_t, char, mbstate_t>::~codecvt()
3250{
3251}
3252
3253codecvt<char32_t, char, mbstate_t>::result
3254codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003255 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003256 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3257{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003258 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3259 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3260 const uint32_t* _frm_nxt = _frm;
3261 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3262 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3263 uint8_t* _to_nxt = _to;
3264 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3265 frm_nxt = frm + (_frm_nxt - _frm);
3266 to_nxt = to + (_to_nxt - _to);
3267 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003268}
3269
3270codecvt<char32_t, char, mbstate_t>::result
3271codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003272 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003273 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3274{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003275 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3276 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3277 const uint8_t* _frm_nxt = _frm;
3278 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3279 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3280 uint32_t* _to_nxt = _to;
3281 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3282 frm_nxt = frm + (_frm_nxt - _frm);
3283 to_nxt = to + (_to_nxt - _to);
3284 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003285}
3286
3287codecvt<char32_t, char, mbstate_t>::result
3288codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3289 extern_type* to, extern_type*, extern_type*& to_nxt) const
3290{
3291 to_nxt = to;
3292 return noconv;
3293}
3294
3295int
Howard Hinnantc9834542011-05-31 15:34:58 +00003296codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003297{
3298 return 0;
3299}
3300
3301bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003302codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003303{
3304 return false;
3305}
3306
3307int
3308codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3309 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3310{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003311 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3312 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3313 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003314}
3315
3316int
Howard Hinnantc9834542011-05-31 15:34:58 +00003317codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003318{
3319 return 4;
3320}
3321
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003322// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003323
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003324__codecvt_utf8<wchar_t>::result
3325__codecvt_utf8<wchar_t>::do_out(state_type&,
3326 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003327 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3328{
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003329#if _WIN32
3330 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3331 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3332 const uint16_t* _frm_nxt = _frm;
3333#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003334 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3335 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3336 const uint32_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003337#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003338 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3339 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3340 uint8_t* _to_nxt = _to;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003341#if _WIN32
3342 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3343 _Maxcode_, _Mode_);
3344#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003345 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3346 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003347#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003348 frm_nxt = frm + (_frm_nxt - _frm);
3349 to_nxt = to + (_to_nxt - _to);
3350 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003351}
3352
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003353__codecvt_utf8<wchar_t>::result
3354__codecvt_utf8<wchar_t>::do_in(state_type&,
3355 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003356 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3357{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003358 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3359 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3360 const uint8_t* _frm_nxt = _frm;
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003361#if _WIN32
3362 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3363 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3364 uint16_t* _to_nxt = _to;
3365 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3366 _Maxcode_, _Mode_);
3367#else
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003368 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3369 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3370 uint32_t* _to_nxt = _to;
3371 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3372 _Maxcode_, _Mode_);
Howard Hinnant0769e6a2013-07-08 19:03:07 +00003373#endif
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003374 frm_nxt = frm + (_frm_nxt - _frm);
3375 to_nxt = to + (_to_nxt - _to);
3376 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003377}
3378
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003379__codecvt_utf8<wchar_t>::result
3380__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003381 extern_type* to, extern_type*, extern_type*& to_nxt) const
3382{
3383 to_nxt = to;
3384 return noconv;
3385}
3386
3387int
Howard Hinnantc9834542011-05-31 15:34:58 +00003388__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003389{
3390 return 0;
3391}
3392
3393bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003394__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003395{
3396 return false;
3397}
3398
3399int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003400__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003401 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3402{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003403 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3404 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3405 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003406}
3407
3408int
Howard Hinnantc9834542011-05-31 15:34:58 +00003409__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003410{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003411 if (_Mode_ & consume_header)
3412 return 7;
3413 return 4;
3414}
3415
3416// __codecvt_utf8<char16_t>
3417
3418__codecvt_utf8<char16_t>::result
3419__codecvt_utf8<char16_t>::do_out(state_type&,
3420 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3421 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3422{
3423 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3424 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3425 const uint16_t* _frm_nxt = _frm;
3426 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3427 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3428 uint8_t* _to_nxt = _to;
3429 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3430 _Maxcode_, _Mode_);
3431 frm_nxt = frm + (_frm_nxt - _frm);
3432 to_nxt = to + (_to_nxt - _to);
3433 return r;
3434}
3435
3436__codecvt_utf8<char16_t>::result
3437__codecvt_utf8<char16_t>::do_in(state_type&,
3438 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3439 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3440{
3441 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3442 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3443 const uint8_t* _frm_nxt = _frm;
3444 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3445 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3446 uint16_t* _to_nxt = _to;
3447 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3448 _Maxcode_, _Mode_);
3449 frm_nxt = frm + (_frm_nxt - _frm);
3450 to_nxt = to + (_to_nxt - _to);
3451 return r;
3452}
3453
3454__codecvt_utf8<char16_t>::result
3455__codecvt_utf8<char16_t>::do_unshift(state_type&,
3456 extern_type* to, extern_type*, extern_type*& to_nxt) const
3457{
3458 to_nxt = to;
3459 return noconv;
3460}
3461
3462int
Howard Hinnantc9834542011-05-31 15:34:58 +00003463__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003464{
3465 return 0;
3466}
3467
3468bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003469__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003470{
3471 return false;
3472}
3473
3474int
3475__codecvt_utf8<char16_t>::do_length(state_type&,
3476 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3477{
3478 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3479 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3480 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3481}
3482
3483int
Howard Hinnantc9834542011-05-31 15:34:58 +00003484__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003485{
3486 if (_Mode_ & consume_header)
3487 return 6;
3488 return 3;
3489}
3490
3491// __codecvt_utf8<char32_t>
3492
3493__codecvt_utf8<char32_t>::result
3494__codecvt_utf8<char32_t>::do_out(state_type&,
3495 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3496 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3497{
3498 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3499 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3500 const uint32_t* _frm_nxt = _frm;
3501 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3502 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3503 uint8_t* _to_nxt = _to;
3504 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3505 _Maxcode_, _Mode_);
3506 frm_nxt = frm + (_frm_nxt - _frm);
3507 to_nxt = to + (_to_nxt - _to);
3508 return r;
3509}
3510
3511__codecvt_utf8<char32_t>::result
3512__codecvt_utf8<char32_t>::do_in(state_type&,
3513 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3514 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3515{
3516 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3517 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3518 const uint8_t* _frm_nxt = _frm;
3519 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3520 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3521 uint32_t* _to_nxt = _to;
3522 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3523 _Maxcode_, _Mode_);
3524 frm_nxt = frm + (_frm_nxt - _frm);
3525 to_nxt = to + (_to_nxt - _to);
3526 return r;
3527}
3528
3529__codecvt_utf8<char32_t>::result
3530__codecvt_utf8<char32_t>::do_unshift(state_type&,
3531 extern_type* to, extern_type*, extern_type*& to_nxt) const
3532{
3533 to_nxt = to;
3534 return noconv;
3535}
3536
3537int
Howard Hinnantc9834542011-05-31 15:34:58 +00003538__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003539{
3540 return 0;
3541}
3542
3543bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003544__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003545{
3546 return false;
3547}
3548
3549int
3550__codecvt_utf8<char32_t>::do_length(state_type&,
3551 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3552{
3553 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3554 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3555 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3556}
3557
3558int
Howard Hinnantc9834542011-05-31 15:34:58 +00003559__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003560{
3561 if (_Mode_ & consume_header)
3562 return 7;
3563 return 4;
3564}
3565
3566// __codecvt_utf16<wchar_t, false>
3567
3568__codecvt_utf16<wchar_t, false>::result
3569__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3570 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3571 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3572{
3573 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3574 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3575 const uint32_t* _frm_nxt = _frm;
3576 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3577 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3578 uint8_t* _to_nxt = _to;
3579 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3580 _Maxcode_, _Mode_);
3581 frm_nxt = frm + (_frm_nxt - _frm);
3582 to_nxt = to + (_to_nxt - _to);
3583 return r;
3584}
3585
3586__codecvt_utf16<wchar_t, false>::result
3587__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3588 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3589 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3590{
3591 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3592 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3593 const uint8_t* _frm_nxt = _frm;
3594 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3595 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3596 uint32_t* _to_nxt = _to;
3597 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3598 _Maxcode_, _Mode_);
3599 frm_nxt = frm + (_frm_nxt - _frm);
3600 to_nxt = to + (_to_nxt - _to);
3601 return r;
3602}
3603
3604__codecvt_utf16<wchar_t, false>::result
3605__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3606 extern_type* to, extern_type*, extern_type*& to_nxt) const
3607{
3608 to_nxt = to;
3609 return noconv;
3610}
3611
3612int
Howard Hinnantc9834542011-05-31 15:34:58 +00003613__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003614{
3615 return 0;
3616}
3617
3618bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003619__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003620{
3621 return false;
3622}
3623
3624int
3625__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3626 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3627{
3628 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3629 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3630 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3631}
3632
3633int
Howard Hinnantc9834542011-05-31 15:34:58 +00003634__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003635{
3636 if (_Mode_ & consume_header)
3637 return 6;
3638 return 4;
3639}
3640
3641// __codecvt_utf16<wchar_t, true>
3642
3643__codecvt_utf16<wchar_t, true>::result
3644__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3645 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3646 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3647{
3648 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3649 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3650 const uint32_t* _frm_nxt = _frm;
3651 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3652 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3653 uint8_t* _to_nxt = _to;
3654 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3655 _Maxcode_, _Mode_);
3656 frm_nxt = frm + (_frm_nxt - _frm);
3657 to_nxt = to + (_to_nxt - _to);
3658 return r;
3659}
3660
3661__codecvt_utf16<wchar_t, true>::result
3662__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3663 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3664 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3665{
3666 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3667 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3668 const uint8_t* _frm_nxt = _frm;
3669 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3670 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3671 uint32_t* _to_nxt = _to;
3672 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3673 _Maxcode_, _Mode_);
3674 frm_nxt = frm + (_frm_nxt - _frm);
3675 to_nxt = to + (_to_nxt - _to);
3676 return r;
3677}
3678
3679__codecvt_utf16<wchar_t, true>::result
3680__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3681 extern_type* to, extern_type*, extern_type*& to_nxt) const
3682{
3683 to_nxt = to;
3684 return noconv;
3685}
3686
3687int
Howard Hinnantc9834542011-05-31 15:34:58 +00003688__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003689{
3690 return 0;
3691}
3692
3693bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003694__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003695{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003696 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003697}
3698
3699int
3700__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3701 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3702{
3703 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3704 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3705 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3706}
3707
3708int
Howard Hinnantc9834542011-05-31 15:34:58 +00003709__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003710{
3711 if (_Mode_ & consume_header)
3712 return 6;
3713 return 4;
3714}
3715
3716// __codecvt_utf16<char16_t, false>
3717
3718__codecvt_utf16<char16_t, false>::result
3719__codecvt_utf16<char16_t, false>::do_out(state_type&,
3720 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3721 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3722{
3723 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3724 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3725 const uint16_t* _frm_nxt = _frm;
3726 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3727 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3728 uint8_t* _to_nxt = _to;
3729 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3730 _Maxcode_, _Mode_);
3731 frm_nxt = frm + (_frm_nxt - _frm);
3732 to_nxt = to + (_to_nxt - _to);
3733 return r;
3734}
3735
3736__codecvt_utf16<char16_t, false>::result
3737__codecvt_utf16<char16_t, false>::do_in(state_type&,
3738 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3739 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3740{
3741 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3742 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3743 const uint8_t* _frm_nxt = _frm;
3744 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3745 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3746 uint16_t* _to_nxt = _to;
3747 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3748 _Maxcode_, _Mode_);
3749 frm_nxt = frm + (_frm_nxt - _frm);
3750 to_nxt = to + (_to_nxt - _to);
3751 return r;
3752}
3753
3754__codecvt_utf16<char16_t, false>::result
3755__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3756 extern_type* to, extern_type*, extern_type*& to_nxt) const
3757{
3758 to_nxt = to;
3759 return noconv;
3760}
3761
3762int
Howard Hinnantc9834542011-05-31 15:34:58 +00003763__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003764{
3765 return 0;
3766}
3767
3768bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003769__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003770{
3771 return false;
3772}
3773
3774int
3775__codecvt_utf16<char16_t, false>::do_length(state_type&,
3776 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3777{
3778 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3779 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3780 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3781}
3782
3783int
Howard Hinnantc9834542011-05-31 15:34:58 +00003784__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003785{
3786 if (_Mode_ & consume_header)
3787 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003788 return 2;
3789}
3790
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003791// __codecvt_utf16<char16_t, true>
3792
3793__codecvt_utf16<char16_t, true>::result
3794__codecvt_utf16<char16_t, true>::do_out(state_type&,
3795 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3796 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3797{
3798 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3799 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3800 const uint16_t* _frm_nxt = _frm;
3801 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3802 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3803 uint8_t* _to_nxt = _to;
3804 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3805 _Maxcode_, _Mode_);
3806 frm_nxt = frm + (_frm_nxt - _frm);
3807 to_nxt = to + (_to_nxt - _to);
3808 return r;
3809}
3810
3811__codecvt_utf16<char16_t, true>::result
3812__codecvt_utf16<char16_t, true>::do_in(state_type&,
3813 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3814 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3815{
3816 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3817 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3818 const uint8_t* _frm_nxt = _frm;
3819 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3820 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3821 uint16_t* _to_nxt = _to;
3822 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3823 _Maxcode_, _Mode_);
3824 frm_nxt = frm + (_frm_nxt - _frm);
3825 to_nxt = to + (_to_nxt - _to);
3826 return r;
3827}
3828
3829__codecvt_utf16<char16_t, true>::result
3830__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3831 extern_type* to, extern_type*, extern_type*& to_nxt) const
3832{
3833 to_nxt = to;
3834 return noconv;
3835}
3836
3837int
Howard Hinnantc9834542011-05-31 15:34:58 +00003838__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003839{
3840 return 0;
3841}
3842
3843bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003844__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003845{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003846 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003847}
3848
3849int
3850__codecvt_utf16<char16_t, true>::do_length(state_type&,
3851 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3852{
3853 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3854 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3855 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3856}
3857
3858int
Howard Hinnantc9834542011-05-31 15:34:58 +00003859__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003860{
3861 if (_Mode_ & consume_header)
3862 return 4;
3863 return 2;
3864}
3865
3866// __codecvt_utf16<char32_t, false>
3867
3868__codecvt_utf16<char32_t, false>::result
3869__codecvt_utf16<char32_t, false>::do_out(state_type&,
3870 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3871 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3872{
3873 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3874 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3875 const uint32_t* _frm_nxt = _frm;
3876 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3877 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3878 uint8_t* _to_nxt = _to;
3879 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3880 _Maxcode_, _Mode_);
3881 frm_nxt = frm + (_frm_nxt - _frm);
3882 to_nxt = to + (_to_nxt - _to);
3883 return r;
3884}
3885
3886__codecvt_utf16<char32_t, false>::result
3887__codecvt_utf16<char32_t, false>::do_in(state_type&,
3888 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3889 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3890{
3891 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3892 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3893 const uint8_t* _frm_nxt = _frm;
3894 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3895 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3896 uint32_t* _to_nxt = _to;
3897 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3898 _Maxcode_, _Mode_);
3899 frm_nxt = frm + (_frm_nxt - _frm);
3900 to_nxt = to + (_to_nxt - _to);
3901 return r;
3902}
3903
3904__codecvt_utf16<char32_t, false>::result
3905__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3906 extern_type* to, extern_type*, extern_type*& to_nxt) const
3907{
3908 to_nxt = to;
3909 return noconv;
3910}
3911
3912int
Howard Hinnantc9834542011-05-31 15:34:58 +00003913__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003914{
3915 return 0;
3916}
3917
3918bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003919__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003920{
3921 return false;
3922}
3923
3924int
3925__codecvt_utf16<char32_t, false>::do_length(state_type&,
3926 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3927{
3928 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3929 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3930 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3931}
3932
3933int
Howard Hinnantc9834542011-05-31 15:34:58 +00003934__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003935{
3936 if (_Mode_ & consume_header)
3937 return 6;
3938 return 4;
3939}
3940
3941// __codecvt_utf16<char32_t, true>
3942
3943__codecvt_utf16<char32_t, true>::result
3944__codecvt_utf16<char32_t, true>::do_out(state_type&,
3945 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3946 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3947{
3948 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3949 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3950 const uint32_t* _frm_nxt = _frm;
3951 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3952 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3953 uint8_t* _to_nxt = _to;
3954 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3955 _Maxcode_, _Mode_);
3956 frm_nxt = frm + (_frm_nxt - _frm);
3957 to_nxt = to + (_to_nxt - _to);
3958 return r;
3959}
3960
3961__codecvt_utf16<char32_t, true>::result
3962__codecvt_utf16<char32_t, true>::do_in(state_type&,
3963 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3964 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3965{
3966 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3967 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3968 const uint8_t* _frm_nxt = _frm;
3969 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3970 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3971 uint32_t* _to_nxt = _to;
3972 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3973 _Maxcode_, _Mode_);
3974 frm_nxt = frm + (_frm_nxt - _frm);
3975 to_nxt = to + (_to_nxt - _to);
3976 return r;
3977}
3978
3979__codecvt_utf16<char32_t, true>::result
3980__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3981 extern_type* to, extern_type*, extern_type*& to_nxt) const
3982{
3983 to_nxt = to;
3984 return noconv;
3985}
3986
3987int
Howard Hinnantc9834542011-05-31 15:34:58 +00003988__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003989{
3990 return 0;
3991}
3992
3993bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003994__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003995{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003996 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003997}
3998
3999int
4000__codecvt_utf16<char32_t, true>::do_length(state_type&,
4001 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4002{
4003 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4004 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4005 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4006}
4007
4008int
Howard Hinnantc9834542011-05-31 15:34:58 +00004009__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004010{
4011 if (_Mode_ & consume_header)
4012 return 6;
4013 return 4;
4014}
4015
4016// __codecvt_utf8_utf16<wchar_t>
4017
4018__codecvt_utf8_utf16<wchar_t>::result
4019__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
4020 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4021 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4022{
4023 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4024 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4025 const uint32_t* _frm_nxt = _frm;
4026 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4027 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4028 uint8_t* _to_nxt = _to;
4029 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4030 _Maxcode_, _Mode_);
4031 frm_nxt = frm + (_frm_nxt - _frm);
4032 to_nxt = to + (_to_nxt - _to);
4033 return r;
4034}
4035
4036__codecvt_utf8_utf16<wchar_t>::result
4037__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
4038 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4039 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4040{
4041 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4042 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4043 const uint8_t* _frm_nxt = _frm;
4044 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4045 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4046 uint32_t* _to_nxt = _to;
4047 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4048 _Maxcode_, _Mode_);
4049 frm_nxt = frm + (_frm_nxt - _frm);
4050 to_nxt = to + (_to_nxt - _to);
4051 return r;
4052}
4053
4054__codecvt_utf8_utf16<wchar_t>::result
4055__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
4056 extern_type* to, extern_type*, extern_type*& to_nxt) const
4057{
4058 to_nxt = to;
4059 return noconv;
4060}
4061
4062int
Howard Hinnantc9834542011-05-31 15:34:58 +00004063__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004064{
4065 return 0;
4066}
4067
4068bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004069__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004070{
4071 return false;
4072}
4073
4074int
4075__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
4076 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4077{
4078 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4079 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4080 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4081}
4082
4083int
Howard Hinnantc9834542011-05-31 15:34:58 +00004084__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004085{
4086 if (_Mode_ & consume_header)
4087 return 7;
4088 return 4;
4089}
4090
4091// __codecvt_utf8_utf16<char16_t>
4092
4093__codecvt_utf8_utf16<char16_t>::result
4094__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
4095 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4096 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4097{
4098 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
4099 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
4100 const uint16_t* _frm_nxt = _frm;
4101 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4102 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4103 uint8_t* _to_nxt = _to;
4104 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4105 _Maxcode_, _Mode_);
4106 frm_nxt = frm + (_frm_nxt - _frm);
4107 to_nxt = to + (_to_nxt - _to);
4108 return r;
4109}
4110
4111__codecvt_utf8_utf16<char16_t>::result
4112__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
4113 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4114 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4115{
4116 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4117 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4118 const uint8_t* _frm_nxt = _frm;
4119 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
4120 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
4121 uint16_t* _to_nxt = _to;
4122 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4123 _Maxcode_, _Mode_);
4124 frm_nxt = frm + (_frm_nxt - _frm);
4125 to_nxt = to + (_to_nxt - _to);
4126 return r;
4127}
4128
4129__codecvt_utf8_utf16<char16_t>::result
4130__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
4131 extern_type* to, extern_type*, extern_type*& to_nxt) const
4132{
4133 to_nxt = to;
4134 return noconv;
4135}
4136
4137int
Howard Hinnantc9834542011-05-31 15:34:58 +00004138__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004139{
4140 return 0;
4141}
4142
4143bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004144__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004145{
4146 return false;
4147}
4148
4149int
4150__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
4151 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4152{
4153 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4154 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4155 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4156}
4157
4158int
Howard Hinnantc9834542011-05-31 15:34:58 +00004159__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004160{
4161 if (_Mode_ & consume_header)
4162 return 7;
4163 return 4;
4164}
4165
4166// __codecvt_utf8_utf16<char32_t>
4167
4168__codecvt_utf8_utf16<char32_t>::result
4169__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4170 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4171 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4172{
4173 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4174 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4175 const uint32_t* _frm_nxt = _frm;
4176 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4177 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4178 uint8_t* _to_nxt = _to;
4179 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4180 _Maxcode_, _Mode_);
4181 frm_nxt = frm + (_frm_nxt - _frm);
4182 to_nxt = to + (_to_nxt - _to);
4183 return r;
4184}
4185
4186__codecvt_utf8_utf16<char32_t>::result
4187__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4188 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4189 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4190{
4191 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4192 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4193 const uint8_t* _frm_nxt = _frm;
4194 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4195 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4196 uint32_t* _to_nxt = _to;
4197 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4198 _Maxcode_, _Mode_);
4199 frm_nxt = frm + (_frm_nxt - _frm);
4200 to_nxt = to + (_to_nxt - _to);
4201 return r;
4202}
4203
4204__codecvt_utf8_utf16<char32_t>::result
4205__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4206 extern_type* to, extern_type*, extern_type*& to_nxt) const
4207{
4208 to_nxt = to;
4209 return noconv;
4210}
4211
4212int
Howard Hinnantc9834542011-05-31 15:34:58 +00004213__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004214{
4215 return 0;
4216}
4217
4218bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004219__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004220{
4221 return false;
4222}
4223
4224int
4225__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4226 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4227{
4228 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4229 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4230 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4231}
4232
4233int
Howard Hinnantc9834542011-05-31 15:34:58 +00004234__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004235{
4236 if (_Mode_ & consume_header)
4237 return 7;
4238 return 4;
4239}
4240
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004241// __narrow_to_utf8<16>
4242
4243__narrow_to_utf8<16>::~__narrow_to_utf8()
4244{
4245}
4246
4247// __narrow_to_utf8<32>
4248
4249__narrow_to_utf8<32>::~__narrow_to_utf8()
4250{
4251}
4252
4253// __widen_from_utf8<16>
4254
4255__widen_from_utf8<16>::~__widen_from_utf8()
4256{
4257}
4258
4259// __widen_from_utf8<32>
4260
4261__widen_from_utf8<32>::~__widen_from_utf8()
4262{
4263}
4264
4265// numpunct<char> && numpunct<wchar_t>
4266
4267locale::id numpunct< char >::id;
4268locale::id numpunct<wchar_t>::id;
4269
4270numpunct<char>::numpunct(size_t refs)
4271 : locale::facet(refs),
4272 __decimal_point_('.'),
4273 __thousands_sep_(',')
4274{
4275}
4276
4277numpunct<wchar_t>::numpunct(size_t refs)
4278 : locale::facet(refs),
4279 __decimal_point_(L'.'),
4280 __thousands_sep_(L',')
4281{
4282}
4283
4284numpunct<char>::~numpunct()
4285{
4286}
4287
4288numpunct<wchar_t>::~numpunct()
4289{
4290}
4291
4292 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4293wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4294
4295 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4296wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4297
4298string numpunct< char >::do_grouping() const {return __grouping_;}
4299string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4300
4301 string numpunct< char >::do_truename() const {return "true";}
4302wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4303
4304 string numpunct< char >::do_falsename() const {return "false";}
4305wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4306
4307// numpunct_byname<char>
4308
4309numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4310 : numpunct<char>(refs)
4311{
4312 __init(nm);
4313}
4314
4315numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4316 : numpunct<char>(refs)
4317{
4318 __init(nm.c_str());
4319}
4320
4321numpunct_byname<char>::~numpunct_byname()
4322{
4323}
4324
4325void
4326numpunct_byname<char>::__init(const char* nm)
4327{
4328 if (strcmp(nm, "C") != 0)
4329 {
Sean Huntf3907e62011-07-15 05:40:33 +00004330 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004331#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004332 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004333 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4334 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004335#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004336#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004337 lconv* lc = localeconv_l(loc.get());
4338#else
4339 lconv* lc = __localeconv_l(loc.get());
4340#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004341 if (*lc->decimal_point)
4342 __decimal_point_ = *lc->decimal_point;
4343 if (*lc->thousands_sep)
4344 __thousands_sep_ = *lc->thousands_sep;
4345 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004346 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004347 }
4348}
4349
4350// numpunct_byname<wchar_t>
4351
4352numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4353 : numpunct<wchar_t>(refs)
4354{
4355 __init(nm);
4356}
4357
4358numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4359 : numpunct<wchar_t>(refs)
4360{
4361 __init(nm.c_str());
4362}
4363
4364numpunct_byname<wchar_t>::~numpunct_byname()
4365{
4366}
4367
4368void
4369numpunct_byname<wchar_t>::__init(const char* nm)
4370{
4371 if (strcmp(nm, "C") != 0)
4372 {
Sean Huntf3907e62011-07-15 05:40:33 +00004373 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004374#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004375 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004376 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4377 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004378#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004379#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004380 lconv* lc = localeconv_l(loc.get());
4381#else
4382 lconv* lc = __localeconv_l(loc.get());
4383#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004384 if (*lc->decimal_point)
4385 __decimal_point_ = *lc->decimal_point;
4386 if (*lc->thousands_sep)
4387 __thousands_sep_ = *lc->thousands_sep;
4388 __grouping_ = lc->grouping;
4389 // locallization for truename and falsename is not available
4390 }
4391}
4392
4393// num_get helpers
4394
4395int
4396__num_get_base::__get_base(ios_base& iob)
4397{
4398 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4399 if (__basefield == ios_base::oct)
4400 return 8;
4401 else if (__basefield == ios_base::hex)
4402 return 16;
4403 else if (__basefield == 0)
4404 return 0;
4405 return 10;
4406}
4407
4408const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4409
4410void
4411__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4412 ios_base::iostate& __err)
4413{
4414 if (__grouping.size() != 0)
4415 {
4416 reverse(__g, __g_end);
4417 const char* __ig = __grouping.data();
4418 const char* __eg = __ig + __grouping.size();
4419 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4420 {
4421 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4422 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004423 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004424 {
4425 __err = ios_base::failbit;
4426 return;
4427 }
4428 }
4429 if (__eg - __ig > 1)
4430 ++__ig;
4431 }
4432 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4433 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004434 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004435 __err = ios_base::failbit;
4436 }
4437 }
4438}
4439
4440void
4441__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4442 ios_base::fmtflags __flags)
4443{
4444 if (__flags & ios_base::showpos)
4445 *__fmtp++ = '+';
4446 if (__flags & ios_base::showbase)
4447 *__fmtp++ = '#';
4448 while(*__len)
4449 *__fmtp++ = *__len++;
4450 if ((__flags & ios_base::basefield) == ios_base::oct)
4451 *__fmtp = 'o';
4452 else if ((__flags & ios_base::basefield) == ios_base::hex)
4453 {
4454 if (__flags & ios_base::uppercase)
4455 *__fmtp = 'X';
4456 else
4457 *__fmtp = 'x';
4458 }
4459 else if (__signd)
4460 *__fmtp = 'd';
4461 else
4462 *__fmtp = 'u';
4463}
4464
4465bool
4466__num_put_base::__format_float(char* __fmtp, const char* __len,
4467 ios_base::fmtflags __flags)
4468{
4469 bool specify_precision = true;
4470 if (__flags & ios_base::showpos)
4471 *__fmtp++ = '+';
4472 if (__flags & ios_base::showpoint)
4473 *__fmtp++ = '#';
4474 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
Marshall Clowa3645132013-10-21 15:07:28 +00004475 bool uppercase = (__flags & ios_base::uppercase) != 0;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004476 if (floatfield == (ios_base::fixed | ios_base::scientific))
4477 specify_precision = false;
4478 else
4479 {
4480 *__fmtp++ = '.';
4481 *__fmtp++ = '*';
4482 }
4483 while(*__len)
4484 *__fmtp++ = *__len++;
4485 if (floatfield == ios_base::fixed)
4486 {
4487 if (uppercase)
4488 *__fmtp = 'F';
4489 else
4490 *__fmtp = 'f';
4491 }
4492 else if (floatfield == ios_base::scientific)
4493 {
4494 if (uppercase)
4495 *__fmtp = 'E';
4496 else
4497 *__fmtp = 'e';
4498 }
4499 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4500 {
4501 if (uppercase)
4502 *__fmtp = 'A';
4503 else
4504 *__fmtp = 'a';
4505 }
4506 else
4507 {
4508 if (uppercase)
4509 *__fmtp = 'G';
4510 else
4511 *__fmtp = 'g';
4512 }
4513 return specify_precision;
4514}
4515
4516char*
4517__num_put_base::__identify_padding(char* __nb, char* __ne,
4518 const ios_base& __iob)
4519{
4520 switch (__iob.flags() & ios_base::adjustfield)
4521 {
4522 case ios_base::internal:
4523 if (__nb[0] == '-' || __nb[0] == '+')
4524 return __nb+1;
4525 if (__ne - __nb >= 2 && __nb[0] == '0'
4526 && (__nb[1] == 'x' || __nb[1] == 'X'))
4527 return __nb+2;
4528 break;
4529 case ios_base::left:
4530 return __ne;
4531 case ios_base::right:
4532 default:
4533 break;
4534 }
4535 return __nb;
4536}
4537
4538// time_get
4539
4540static
4541string*
4542init_weeks()
4543{
4544 static string weeks[14];
4545 weeks[0] = "Sunday";
4546 weeks[1] = "Monday";
4547 weeks[2] = "Tuesday";
4548 weeks[3] = "Wednesday";
4549 weeks[4] = "Thursday";
4550 weeks[5] = "Friday";
4551 weeks[6] = "Saturday";
4552 weeks[7] = "Sun";
4553 weeks[8] = "Mon";
4554 weeks[9] = "Tue";
4555 weeks[10] = "Wed";
4556 weeks[11] = "Thu";
4557 weeks[12] = "Fri";
4558 weeks[13] = "Sat";
4559 return weeks;
4560}
4561
4562static
4563wstring*
4564init_wweeks()
4565{
4566 static wstring weeks[14];
4567 weeks[0] = L"Sunday";
4568 weeks[1] = L"Monday";
4569 weeks[2] = L"Tuesday";
4570 weeks[3] = L"Wednesday";
4571 weeks[4] = L"Thursday";
4572 weeks[5] = L"Friday";
4573 weeks[6] = L"Saturday";
4574 weeks[7] = L"Sun";
4575 weeks[8] = L"Mon";
4576 weeks[9] = L"Tue";
4577 weeks[10] = L"Wed";
4578 weeks[11] = L"Thu";
4579 weeks[12] = L"Fri";
4580 weeks[13] = L"Sat";
4581 return weeks;
4582}
4583
4584template <>
4585const string*
4586__time_get_c_storage<char>::__weeks() const
4587{
4588 static const string* weeks = init_weeks();
4589 return weeks;
4590}
4591
4592template <>
4593const wstring*
4594__time_get_c_storage<wchar_t>::__weeks() const
4595{
4596 static const wstring* weeks = init_wweeks();
4597 return weeks;
4598}
4599
4600static
4601string*
4602init_months()
4603{
4604 static string months[24];
4605 months[0] = "January";
4606 months[1] = "February";
4607 months[2] = "March";
4608 months[3] = "April";
4609 months[4] = "May";
4610 months[5] = "June";
4611 months[6] = "July";
4612 months[7] = "August";
4613 months[8] = "September";
4614 months[9] = "October";
4615 months[10] = "November";
4616 months[11] = "December";
4617 months[12] = "Jan";
4618 months[13] = "Feb";
4619 months[14] = "Mar";
4620 months[15] = "Apr";
4621 months[16] = "May";
4622 months[17] = "Jun";
4623 months[18] = "Jul";
4624 months[19] = "Aug";
4625 months[20] = "Sep";
4626 months[21] = "Oct";
4627 months[22] = "Nov";
4628 months[23] = "Dec";
4629 return months;
4630}
4631
4632static
4633wstring*
4634init_wmonths()
4635{
4636 static wstring months[24];
4637 months[0] = L"January";
4638 months[1] = L"February";
4639 months[2] = L"March";
4640 months[3] = L"April";
4641 months[4] = L"May";
4642 months[5] = L"June";
4643 months[6] = L"July";
4644 months[7] = L"August";
4645 months[8] = L"September";
4646 months[9] = L"October";
4647 months[10] = L"November";
4648 months[11] = L"December";
4649 months[12] = L"Jan";
4650 months[13] = L"Feb";
4651 months[14] = L"Mar";
4652 months[15] = L"Apr";
4653 months[16] = L"May";
4654 months[17] = L"Jun";
4655 months[18] = L"Jul";
4656 months[19] = L"Aug";
4657 months[20] = L"Sep";
4658 months[21] = L"Oct";
4659 months[22] = L"Nov";
4660 months[23] = L"Dec";
4661 return months;
4662}
4663
4664template <>
4665const string*
4666__time_get_c_storage<char>::__months() const
4667{
4668 static const string* months = init_months();
4669 return months;
4670}
4671
4672template <>
4673const wstring*
4674__time_get_c_storage<wchar_t>::__months() const
4675{
4676 static const wstring* months = init_wmonths();
4677 return months;
4678}
4679
4680static
4681string*
4682init_am_pm()
4683{
4684 static string am_pm[24];
4685 am_pm[0] = "AM";
4686 am_pm[1] = "PM";
4687 return am_pm;
4688}
4689
4690static
4691wstring*
4692init_wam_pm()
4693{
4694 static wstring am_pm[24];
4695 am_pm[0] = L"AM";
4696 am_pm[1] = L"PM";
4697 return am_pm;
4698}
4699
4700template <>
4701const string*
4702__time_get_c_storage<char>::__am_pm() const
4703{
4704 static const string* am_pm = init_am_pm();
4705 return am_pm;
4706}
4707
4708template <>
4709const wstring*
4710__time_get_c_storage<wchar_t>::__am_pm() const
4711{
4712 static const wstring* am_pm = init_wam_pm();
4713 return am_pm;
4714}
4715
4716template <>
4717const string&
4718__time_get_c_storage<char>::__x() const
4719{
4720 static string s("%m/%d/%y");
4721 return s;
4722}
4723
4724template <>
4725const wstring&
4726__time_get_c_storage<wchar_t>::__x() const
4727{
4728 static wstring s(L"%m/%d/%y");
4729 return s;
4730}
4731
4732template <>
4733const string&
4734__time_get_c_storage<char>::__X() const
4735{
4736 static string s("%H:%M:%S");
4737 return s;
4738}
4739
4740template <>
4741const wstring&
4742__time_get_c_storage<wchar_t>::__X() const
4743{
4744 static wstring s(L"%H:%M:%S");
4745 return s;
4746}
4747
4748template <>
4749const string&
4750__time_get_c_storage<char>::__c() const
4751{
4752 static string s("%a %b %d %H:%M:%S %Y");
4753 return s;
4754}
4755
4756template <>
4757const wstring&
4758__time_get_c_storage<wchar_t>::__c() const
4759{
4760 static wstring s(L"%a %b %d %H:%M:%S %Y");
4761 return s;
4762}
4763
4764template <>
4765const string&
4766__time_get_c_storage<char>::__r() const
4767{
4768 static string s("%I:%M:%S %p");
4769 return s;
4770}
4771
4772template <>
4773const wstring&
4774__time_get_c_storage<wchar_t>::__r() const
4775{
4776 static wstring s(L"%I:%M:%S %p");
4777 return s;
4778}
4779
4780// time_get_byname
4781
4782__time_get::__time_get(const char* nm)
4783 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4784{
Howard Hinnantd4444702010-08-11 17:04:31 +00004785#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004786 if (__loc_ == 0)
4787 throw runtime_error("time_get_byname"
4788 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004789#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004790}
4791
4792__time_get::__time_get(const string& nm)
4793 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4794{
Howard Hinnantd4444702010-08-11 17:04:31 +00004795#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004796 if (__loc_ == 0)
4797 throw runtime_error("time_get_byname"
4798 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004799#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004800}
4801
4802__time_get::~__time_get()
4803{
4804 freelocale(__loc_);
4805}
Marshall Clowa3645132013-10-21 15:07:28 +00004806#if defined(__clang__)
Howard Hinnant335b1512012-02-20 16:51:43 +00004807#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004808#endif
4809#if defined(__GNUG__)
Howard Hinnant21772ec2012-12-28 18:15:01 +00004810#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Marshall Clowa3645132013-10-21 15:07:28 +00004811#endif
Howard Hinnant335b1512012-02-20 16:51:43 +00004812
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004813template <>
4814string
4815__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4816{
Howard Hinnant3074a052012-02-19 14:55:32 +00004817 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004818 t.tm_sec = 59;
4819 t.tm_min = 55;
4820 t.tm_hour = 23;
4821 t.tm_mday = 31;
4822 t.tm_mon = 11;
4823 t.tm_year = 161;
4824 t.tm_wday = 6;
4825 t.tm_yday = 364;
4826 t.tm_isdst = -1;
4827 char buf[100];
4828 char f[3] = {0};
4829 f[0] = '%';
4830 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004831 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004832 char* bb = buf;
4833 char* be = buf + n;
4834 string result;
4835 while (bb != be)
4836 {
4837 if (ct.is(ctype_base::space, *bb))
4838 {
4839 result.push_back(' ');
4840 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4841 ;
4842 continue;
4843 }
4844 char* w = bb;
4845 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004846 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004847 ct, err, false)
4848 - this->__weeks_;
4849 if (i < 14)
4850 {
4851 result.push_back('%');
4852 if (i < 7)
4853 result.push_back('A');
4854 else
4855 result.push_back('a');
4856 bb = w;
4857 continue;
4858 }
4859 w = bb;
4860 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4861 ct, err, false)
4862 - this->__months_;
4863 if (i < 24)
4864 {
4865 result.push_back('%');
4866 if (i < 12)
4867 result.push_back('B');
4868 else
4869 result.push_back('b');
4870 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4871 result.back() = 'm';
4872 bb = w;
4873 continue;
4874 }
4875 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4876 {
4877 w = bb;
4878 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4879 ct, err, false) - this->__am_pm_;
4880 if (i < 2)
4881 {
4882 result.push_back('%');
4883 result.push_back('p');
4884 bb = w;
4885 continue;
4886 }
4887 }
4888 w = bb;
4889 if (ct.is(ctype_base::digit, *bb))
4890 {
4891 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4892 {
4893 case 6:
4894 result.push_back('%');
4895 result.push_back('w');
4896 break;
4897 case 7:
4898 result.push_back('%');
4899 result.push_back('u');
4900 break;
4901 case 11:
4902 result.push_back('%');
4903 result.push_back('I');
4904 break;
4905 case 12:
4906 result.push_back('%');
4907 result.push_back('m');
4908 break;
4909 case 23:
4910 result.push_back('%');
4911 result.push_back('H');
4912 break;
4913 case 31:
4914 result.push_back('%');
4915 result.push_back('d');
4916 break;
4917 case 55:
4918 result.push_back('%');
4919 result.push_back('M');
4920 break;
4921 case 59:
4922 result.push_back('%');
4923 result.push_back('S');
4924 break;
4925 case 61:
4926 result.push_back('%');
4927 result.push_back('y');
4928 break;
4929 case 364:
4930 result.push_back('%');
4931 result.push_back('j');
4932 break;
4933 case 2061:
4934 result.push_back('%');
4935 result.push_back('Y');
4936 break;
4937 default:
4938 for (; w != bb; ++w)
4939 result.push_back(*w);
4940 break;
4941 }
4942 continue;
4943 }
4944 if (*bb == '%')
4945 {
4946 result.push_back('%');
4947 result.push_back('%');
4948 ++bb;
4949 continue;
4950 }
4951 result.push_back(*bb);
4952 ++bb;
4953 }
4954 return result;
4955}
4956
Marshall Clowa3645132013-10-21 15:07:28 +00004957#if defined(__clang__)
Howard Hinnantec3773c2011-12-01 20:21:04 +00004958#pragma clang diagnostic ignored "-Wmissing-braces"
Marshall Clowa3645132013-10-21 15:07:28 +00004959#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004960
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004961template <>
4962wstring
4963__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4964{
Howard Hinnant3074a052012-02-19 14:55:32 +00004965 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004966 t.tm_sec = 59;
4967 t.tm_min = 55;
4968 t.tm_hour = 23;
4969 t.tm_mday = 31;
4970 t.tm_mon = 11;
4971 t.tm_year = 161;
4972 t.tm_wday = 6;
4973 t.tm_yday = 364;
4974 t.tm_isdst = -1;
4975 char buf[100];
4976 char f[3] = {0};
4977 f[0] = '%';
4978 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004979 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004980 wchar_t wbuf[100];
4981 wchar_t* wbb = wbuf;
4982 mbstate_t mb = {0};
4983 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004984#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004985 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004986#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004987 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004988#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004989 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004990 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004991 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004992 wstring result;
4993 while (wbb != wbe)
4994 {
4995 if (ct.is(ctype_base::space, *wbb))
4996 {
4997 result.push_back(L' ');
4998 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4999 ;
5000 continue;
5001 }
5002 wchar_t* w = wbb;
5003 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00005004 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005005 ct, err, false)
5006 - this->__weeks_;
5007 if (i < 14)
5008 {
5009 result.push_back(L'%');
5010 if (i < 7)
5011 result.push_back(L'A');
5012 else
5013 result.push_back(L'a');
5014 wbb = w;
5015 continue;
5016 }
5017 w = wbb;
5018 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
5019 ct, err, false)
5020 - this->__months_;
5021 if (i < 24)
5022 {
5023 result.push_back(L'%');
5024 if (i < 12)
5025 result.push_back(L'B');
5026 else
5027 result.push_back(L'b');
5028 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
5029 result.back() = L'm';
5030 wbb = w;
5031 continue;
5032 }
5033 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
5034 {
5035 w = wbb;
5036 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
5037 ct, err, false) - this->__am_pm_;
5038 if (i < 2)
5039 {
5040 result.push_back(L'%');
5041 result.push_back(L'p');
5042 wbb = w;
5043 continue;
5044 }
5045 }
5046 w = wbb;
5047 if (ct.is(ctype_base::digit, *wbb))
5048 {
5049 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
5050 {
5051 case 6:
5052 result.push_back(L'%');
5053 result.push_back(L'w');
5054 break;
5055 case 7:
5056 result.push_back(L'%');
5057 result.push_back(L'u');
5058 break;
5059 case 11:
5060 result.push_back(L'%');
5061 result.push_back(L'I');
5062 break;
5063 case 12:
5064 result.push_back(L'%');
5065 result.push_back(L'm');
5066 break;
5067 case 23:
5068 result.push_back(L'%');
5069 result.push_back(L'H');
5070 break;
5071 case 31:
5072 result.push_back(L'%');
5073 result.push_back(L'd');
5074 break;
5075 case 55:
5076 result.push_back(L'%');
5077 result.push_back(L'M');
5078 break;
5079 case 59:
5080 result.push_back(L'%');
5081 result.push_back(L'S');
5082 break;
5083 case 61:
5084 result.push_back(L'%');
5085 result.push_back(L'y');
5086 break;
5087 case 364:
5088 result.push_back(L'%');
5089 result.push_back(L'j');
5090 break;
5091 case 2061:
5092 result.push_back(L'%');
5093 result.push_back(L'Y');
5094 break;
5095 default:
5096 for (; w != wbb; ++w)
5097 result.push_back(*w);
5098 break;
5099 }
5100 continue;
5101 }
5102 if (ct.narrow(*wbb, 0) == '%')
5103 {
5104 result.push_back(L'%');
5105 result.push_back(L'%');
5106 ++wbb;
5107 continue;
5108 }
5109 result.push_back(*wbb);
5110 ++wbb;
5111 }
5112 return result;
5113}
5114
5115template <>
5116void
5117__time_get_storage<char>::init(const ctype<char>& ct)
5118{
Howard Hinnantcd992362012-08-02 18:44:17 +00005119 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005120 char buf[100];
5121 // __weeks_
5122 for (int i = 0; i < 7; ++i)
5123 {
5124 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005125 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005126 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005127 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005128 __weeks_[i+7] = buf;
5129 }
5130 // __months_
5131 for (int i = 0; i < 12; ++i)
5132 {
5133 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005134 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005135 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005136 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005137 __months_[i+12] = buf;
5138 }
5139 // __am_pm_
5140 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005141 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005142 __am_pm_[0] = buf;
5143 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005144 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005145 __am_pm_[1] = buf;
5146 __c_ = __analyze('c', ct);
5147 __r_ = __analyze('r', ct);
5148 __x_ = __analyze('x', ct);
5149 __X_ = __analyze('X', ct);
5150}
5151
5152template <>
5153void
5154__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
5155{
5156 tm t = {0};
5157 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005158 wchar_t wbuf[100];
5159 wchar_t* wbe;
5160 mbstate_t mb = {0};
5161 // __weeks_
5162 for (int i = 0; i < 7; ++i)
5163 {
5164 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005165 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005166 mb = mbstate_t();
5167 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005168#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005169 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005170#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005171 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005172#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005173 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005174 __throw_runtime_error("locale not supported");
5175 wbe = wbuf + j;
5176 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005177 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005178 mb = mbstate_t();
5179 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005180#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005181 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005182#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005183 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005184#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005185 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005186 __throw_runtime_error("locale not supported");
5187 wbe = wbuf + j;
5188 __weeks_[i+7].assign(wbuf, wbe);
5189 }
5190 // __months_
5191 for (int i = 0; i < 12; ++i)
5192 {
5193 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005194 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005195 mb = mbstate_t();
5196 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005197#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005198 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005199#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005200 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005201#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005202 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005203 __throw_runtime_error("locale not supported");
5204 wbe = wbuf + j;
5205 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005206 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005207 mb = mbstate_t();
5208 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005209#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005210 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005211#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005212 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005213#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005214 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005215 __throw_runtime_error("locale not supported");
5216 wbe = wbuf + j;
5217 __months_[i+12].assign(wbuf, wbe);
5218 }
5219 // __am_pm_
5220 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005221 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005222 mb = mbstate_t();
5223 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005224#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005225 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005226#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005227 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005228#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005229 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005230 __throw_runtime_error("locale not supported");
5231 wbe = wbuf + j;
5232 __am_pm_[0].assign(wbuf, wbe);
5233 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005234 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005235 mb = mbstate_t();
5236 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005237#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005238 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005239#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005240 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005241#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005242 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005243 __throw_runtime_error("locale not supported");
5244 wbe = wbuf + j;
5245 __am_pm_[1].assign(wbuf, wbe);
5246 __c_ = __analyze('c', ct);
5247 __r_ = __analyze('r', ct);
5248 __x_ = __analyze('x', ct);
5249 __X_ = __analyze('X', ct);
5250}
5251
5252template <class CharT>
5253struct _LIBCPP_HIDDEN __time_get_temp
5254 : public ctype_byname<CharT>
5255{
5256 explicit __time_get_temp(const char* nm)
5257 : ctype_byname<CharT>(nm, 1) {}
5258 explicit __time_get_temp(const string& nm)
5259 : ctype_byname<CharT>(nm, 1) {}
5260};
5261
5262template <>
5263__time_get_storage<char>::__time_get_storage(const char* __nm)
5264 : __time_get(__nm)
5265{
5266 const __time_get_temp<char> ct(__nm);
5267 init(ct);
5268}
5269
5270template <>
5271__time_get_storage<char>::__time_get_storage(const string& __nm)
5272 : __time_get(__nm)
5273{
5274 const __time_get_temp<char> ct(__nm);
5275 init(ct);
5276}
5277
5278template <>
5279__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5280 : __time_get(__nm)
5281{
5282 const __time_get_temp<wchar_t> ct(__nm);
5283 init(ct);
5284}
5285
5286template <>
5287__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5288 : __time_get(__nm)
5289{
5290 const __time_get_temp<wchar_t> ct(__nm);
5291 init(ct);
5292}
5293
5294template <>
5295time_base::dateorder
5296__time_get_storage<char>::__do_date_order() const
5297{
5298 unsigned i;
5299 for (i = 0; i < __x_.size(); ++i)
5300 if (__x_[i] == '%')
5301 break;
5302 ++i;
5303 switch (__x_[i])
5304 {
5305 case 'y':
5306 case 'Y':
5307 for (++i; i < __x_.size(); ++i)
5308 if (__x_[i] == '%')
5309 break;
5310 if (i == __x_.size())
5311 break;
5312 ++i;
5313 switch (__x_[i])
5314 {
5315 case 'm':
5316 for (++i; i < __x_.size(); ++i)
5317 if (__x_[i] == '%')
5318 break;
5319 if (i == __x_.size())
5320 break;
5321 ++i;
5322 if (__x_[i] == 'd')
5323 return time_base::ymd;
5324 break;
5325 case 'd':
5326 for (++i; i < __x_.size(); ++i)
5327 if (__x_[i] == '%')
5328 break;
5329 if (i == __x_.size())
5330 break;
5331 ++i;
5332 if (__x_[i] == 'm')
5333 return time_base::ydm;
5334 break;
5335 }
5336 break;
5337 case 'm':
5338 for (++i; i < __x_.size(); ++i)
5339 if (__x_[i] == '%')
5340 break;
5341 if (i == __x_.size())
5342 break;
5343 ++i;
5344 if (__x_[i] == 'd')
5345 {
5346 for (++i; i < __x_.size(); ++i)
5347 if (__x_[i] == '%')
5348 break;
5349 if (i == __x_.size())
5350 break;
5351 ++i;
5352 if (__x_[i] == 'y' || __x_[i] == 'Y')
5353 return time_base::mdy;
5354 break;
5355 }
5356 break;
5357 case 'd':
5358 for (++i; i < __x_.size(); ++i)
5359 if (__x_[i] == '%')
5360 break;
5361 if (i == __x_.size())
5362 break;
5363 ++i;
5364 if (__x_[i] == 'm')
5365 {
5366 for (++i; i < __x_.size(); ++i)
5367 if (__x_[i] == '%')
5368 break;
5369 if (i == __x_.size())
5370 break;
5371 ++i;
5372 if (__x_[i] == 'y' || __x_[i] == 'Y')
5373 return time_base::dmy;
5374 break;
5375 }
5376 break;
5377 }
5378 return time_base::no_order;
5379}
5380
5381template <>
5382time_base::dateorder
5383__time_get_storage<wchar_t>::__do_date_order() const
5384{
5385 unsigned i;
5386 for (i = 0; i < __x_.size(); ++i)
5387 if (__x_[i] == L'%')
5388 break;
5389 ++i;
5390 switch (__x_[i])
5391 {
5392 case L'y':
5393 case L'Y':
5394 for (++i; i < __x_.size(); ++i)
5395 if (__x_[i] == L'%')
5396 break;
5397 if (i == __x_.size())
5398 break;
5399 ++i;
5400 switch (__x_[i])
5401 {
5402 case L'm':
5403 for (++i; i < __x_.size(); ++i)
5404 if (__x_[i] == L'%')
5405 break;
5406 if (i == __x_.size())
5407 break;
5408 ++i;
5409 if (__x_[i] == L'd')
5410 return time_base::ymd;
5411 break;
5412 case L'd':
5413 for (++i; i < __x_.size(); ++i)
5414 if (__x_[i] == L'%')
5415 break;
5416 if (i == __x_.size())
5417 break;
5418 ++i;
5419 if (__x_[i] == L'm')
5420 return time_base::ydm;
5421 break;
5422 }
5423 break;
5424 case L'm':
5425 for (++i; i < __x_.size(); ++i)
5426 if (__x_[i] == L'%')
5427 break;
5428 if (i == __x_.size())
5429 break;
5430 ++i;
5431 if (__x_[i] == L'd')
5432 {
5433 for (++i; i < __x_.size(); ++i)
5434 if (__x_[i] == L'%')
5435 break;
5436 if (i == __x_.size())
5437 break;
5438 ++i;
5439 if (__x_[i] == L'y' || __x_[i] == L'Y')
5440 return time_base::mdy;
5441 break;
5442 }
5443 break;
5444 case L'd':
5445 for (++i; i < __x_.size(); ++i)
5446 if (__x_[i] == L'%')
5447 break;
5448 if (i == __x_.size())
5449 break;
5450 ++i;
5451 if (__x_[i] == L'm')
5452 {
5453 for (++i; i < __x_.size(); ++i)
5454 if (__x_[i] == L'%')
5455 break;
5456 if (i == __x_.size())
5457 break;
5458 ++i;
5459 if (__x_[i] == L'y' || __x_[i] == L'Y')
5460 return time_base::dmy;
5461 break;
5462 }
5463 break;
5464 }
5465 return time_base::no_order;
5466}
5467
5468// time_put
5469
5470__time_put::__time_put(const char* nm)
5471 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5472{
Howard Hinnantd4444702010-08-11 17:04:31 +00005473#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005474 if (__loc_ == 0)
5475 throw runtime_error("time_put_byname"
5476 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005477#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005478}
5479
5480__time_put::__time_put(const string& nm)
5481 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5482{
Howard Hinnantd4444702010-08-11 17:04:31 +00005483#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005484 if (__loc_ == 0)
5485 throw runtime_error("time_put_byname"
5486 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005487#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005488}
5489
5490__time_put::~__time_put()
5491{
Joerg Sonnenberger9a06b9d2013-07-02 19:46:18 +00005492 if (__loc_ != _LIBCPP_GET_C_LOCALE)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005493 freelocale(__loc_);
5494}
5495
5496void
5497__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5498 char __fmt, char __mod) const
5499{
5500 char fmt[] = {'%', __fmt, __mod, 0};
5501 if (__mod != 0)
5502 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005503 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005504 __ne = __nb + n;
5505}
5506
5507void
5508__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5509 char __fmt, char __mod) const
5510{
5511 char __nar[100];
5512 char* __ne = __nar + 100;
5513 __do_put(__nar, __ne, __tm, __fmt, __mod);
5514 mbstate_t mb = {0};
5515 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005516#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005517 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005518#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005519 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005520#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005521 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005522 __throw_runtime_error("locale not supported");
5523 __we = __wb + j;
5524}
5525
5526// moneypunct_byname
5527
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005528template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005529static
5530void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005531__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5532 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5533 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005534{
5535 const char sign = static_cast<char>(money_base::sign);
5536 const char space = static_cast<char>(money_base::space);
5537 const char none = static_cast<char>(money_base::none);
5538 const char symbol = static_cast<char>(money_base::symbol);
5539 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005540 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5541
5542 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5543 // function'. "Space between sign and symbol or value" means that
5544 // if the sign is adjacent to the symbol, there's a space between
5545 // them, and otherwise there's a space between the sign and value.
5546 //
5547 // C11's localeconv specifies that the fourth character of an
5548 // international curr_symbol is used to separate the sign and
5549 // value when sep_by_space says to do so. C++ can't represent
5550 // that, so we just use a space. When sep_by_space says to
5551 // separate the symbol and value-or-sign with a space, we rearrange the
5552 // curr_symbol to put its spacing character on the correct side of
5553 // the symbol.
5554 //
5555 // We also need to avoid adding an extra space between the sign
5556 // and value when the currency symbol is suppressed (by not
5557 // setting showbase). We match glibc's strfmon by interpreting
5558 // sep_by_space==1 as "omit the space when the currency symbol is
5559 // absent".
5560 //
5561 // Users who want to get this right should use ICU instead.
5562
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005563 switch (cs_precedes)
5564 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005565 case 0: // value before curr_symbol
5566 if (symbol_contains_sep) {
5567 // Move the separator to before the symbol, to place it
5568 // between the value and symbol.
5569 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5570 __curr_symbol_.end());
5571 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005572 switch (sign_posn)
5573 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005574 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005575 pat.field[0] = sign;
5576 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005577 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005578 pat.field[3] = symbol;
5579 switch (sep_by_space)
5580 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005581 case 0: // No space separates the currency symbol and value.
5582 // This case may have changed between C99 and C11;
5583 // assume the currency symbol matches the intention.
5584 case 2: // Space between sign and currency or value.
5585 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005586 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005587 case 1: // Space between currency-and-sign or currency and value.
5588 if (!symbol_contains_sep) {
5589 // We insert the space into the symbol instead of
5590 // setting pat.field[2]=space so that when
5591 // showbase is not set, the space goes away too.
5592 __curr_symbol_.insert(0, 1, space_char);
5593 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005594 return;
5595 default:
5596 break;
5597 }
5598 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005599 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005600 pat.field[0] = sign;
5601 pat.field[3] = symbol;
5602 switch (sep_by_space)
5603 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005604 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005605 pat.field[1] = value;
5606 pat.field[2] = none;
5607 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005608 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005609 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005610 pat.field[2] = none;
5611 if (!symbol_contains_sep) {
5612 // We insert the space into the symbol instead of
5613 // setting pat.field[2]=space so that when
5614 // showbase is not set, the space goes away too.
5615 __curr_symbol_.insert(0, 1, space_char);
5616 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005617 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005618 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005619 pat.field[1] = space;
5620 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005621 if (symbol_contains_sep) {
5622 // Remove the separator from the symbol, since it
5623 // has already appeared after the sign.
5624 __curr_symbol_.erase(__curr_symbol_.begin());
5625 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005626 return;
5627 default:
5628 break;
5629 }
5630 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005631 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005632 pat.field[0] = value;
5633 pat.field[3] = sign;
5634 switch (sep_by_space)
5635 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005636 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005637 pat.field[1] = none;
5638 pat.field[2] = symbol;
5639 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005640 case 1: // Space between currency-and-sign or currency and value.
5641 if (!symbol_contains_sep) {
5642 // We insert the space into the symbol instead of
5643 // setting pat.field[1]=space so that when
5644 // showbase is not set, the space goes away too.
5645 __curr_symbol_.insert(0, 1, space_char);
5646 }
5647 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005648 pat.field[2] = symbol;
5649 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005650 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005651 pat.field[1] = symbol;
5652 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005653 if (symbol_contains_sep) {
5654 // Remove the separator from the symbol, since it
5655 // should not be removed if showbase is absent.
5656 __curr_symbol_.erase(__curr_symbol_.begin());
5657 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005658 return;
5659 default:
5660 break;
5661 }
5662 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005663 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005664 pat.field[0] = value;
5665 pat.field[3] = symbol;
5666 switch (sep_by_space)
5667 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005668 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005669 pat.field[1] = none;
5670 pat.field[2] = sign;
5671 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005672 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005673 pat.field[1] = space;
5674 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005675 if (symbol_contains_sep) {
5676 // Remove the separator from the symbol, since it
5677 // has already appeared before the sign.
5678 __curr_symbol_.erase(__curr_symbol_.begin());
5679 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005680 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005681 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005682 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005683 pat.field[2] = none;
5684 if (!symbol_contains_sep) {
5685 // We insert the space into the symbol instead of
5686 // setting pat.field[2]=space so that when
5687 // showbase is not set, the space goes away too.
5688 __curr_symbol_.insert(0, 1, space_char);
5689 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005690 return;
5691 default:
5692 break;
5693 }
5694 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005695 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005696 pat.field[0] = value;
5697 pat.field[3] = sign;
5698 switch (sep_by_space)
5699 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005700 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005701 pat.field[1] = none;
5702 pat.field[2] = symbol;
5703 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005704 case 1: // Space between currency-and-sign or currency and value.
5705 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005706 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005707 if (!symbol_contains_sep) {
5708 // We insert the space into the symbol instead of
5709 // setting pat.field[1]=space so that when
5710 // showbase is not set, the space goes away too.
5711 __curr_symbol_.insert(0, 1, space_char);
5712 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005713 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005714 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005715 pat.field[1] = symbol;
5716 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005717 if (symbol_contains_sep) {
5718 // Remove the separator from the symbol, since it
5719 // should not disappear when showbase is absent.
5720 __curr_symbol_.erase(__curr_symbol_.begin());
5721 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005722 return;
5723 default:
5724 break;
5725 }
5726 break;
5727 default:
5728 break;
5729 }
5730 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005731 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005732 switch (sign_posn)
5733 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005734 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005735 pat.field[0] = sign;
5736 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005737 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005738 pat.field[3] = value;
5739 switch (sep_by_space)
5740 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005741 case 0: // No space separates the currency symbol and value.
5742 // This case may have changed between C99 and C11;
5743 // assume the currency symbol matches the intention.
5744 case 2: // Space between sign and currency or value.
5745 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005746 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005747 case 1: // Space between currency-and-sign or currency and value.
5748 if (!symbol_contains_sep) {
5749 // We insert the space into the symbol instead of
5750 // setting pat.field[2]=space so that when
5751 // showbase is not set, the space goes away too.
5752 __curr_symbol_.insert(0, 1, space_char);
5753 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005754 return;
5755 default:
5756 break;
5757 }
5758 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005759 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005760 pat.field[0] = sign;
5761 pat.field[3] = value;
5762 switch (sep_by_space)
5763 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005764 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005765 pat.field[1] = symbol;
5766 pat.field[2] = none;
5767 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005768 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005769 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005770 pat.field[2] = none;
5771 if (!symbol_contains_sep) {
5772 // We insert the space into the symbol instead of
5773 // setting pat.field[2]=space so that when
5774 // showbase is not set, the space goes away too.
5775 __curr_symbol_.push_back(space_char);
5776 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005777 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005778 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005779 pat.field[1] = space;
5780 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005781 if (symbol_contains_sep) {
5782 // Remove the separator from the symbol, since it
5783 // has already appeared after the sign.
5784 __curr_symbol_.pop_back();
5785 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005786 return;
5787 default:
5788 break;
5789 }
5790 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005791 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005792 pat.field[0] = symbol;
5793 pat.field[3] = sign;
5794 switch (sep_by_space)
5795 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005796 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005797 pat.field[1] = none;
5798 pat.field[2] = value;
5799 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005800 case 1: // Space between currency-and-sign or currency and value.
5801 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005802 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005803 if (!symbol_contains_sep) {
5804 // We insert the space into the symbol instead of
5805 // setting pat.field[1]=space so that when
5806 // showbase is not set, the space goes away too.
5807 __curr_symbol_.push_back(space_char);
5808 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005809 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005810 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005811 pat.field[1] = value;
5812 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005813 if (symbol_contains_sep) {
5814 // Remove the separator from the symbol, since it
5815 // will appear before the sign.
5816 __curr_symbol_.pop_back();
5817 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005818 return;
5819 default:
5820 break;
5821 }
5822 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005823 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005824 pat.field[0] = sign;
5825 pat.field[3] = value;
5826 switch (sep_by_space)
5827 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005828 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005829 pat.field[1] = symbol;
5830 pat.field[2] = none;
5831 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005832 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005833 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005834 pat.field[2] = none;
5835 if (!symbol_contains_sep) {
5836 // We insert the space into the symbol instead of
5837 // setting pat.field[2]=space so that when
5838 // showbase is not set, the space goes away too.
5839 __curr_symbol_.push_back(space_char);
5840 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005841 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005842 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005843 pat.field[1] = space;
5844 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005845 if (symbol_contains_sep) {
5846 // Remove the separator from the symbol, since it
5847 // has already appeared after the sign.
5848 __curr_symbol_.pop_back();
5849 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005850 return;
5851 default:
5852 break;
5853 }
5854 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005855 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005856 pat.field[0] = symbol;
5857 pat.field[3] = value;
5858 switch (sep_by_space)
5859 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005860 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005861 pat.field[1] = sign;
5862 pat.field[2] = none;
5863 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005864 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005865 pat.field[1] = sign;
5866 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005867 if (symbol_contains_sep) {
5868 // Remove the separator from the symbol, since it
5869 // should not disappear when showbase is absent.
5870 __curr_symbol_.pop_back();
5871 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005872 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005873 case 2: // Space between sign and currency or value.
5874 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005875 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005876 if (!symbol_contains_sep) {
5877 // We insert the space into the symbol instead of
5878 // setting pat.field[1]=space so that when
5879 // showbase is not set, the space goes away too.
5880 __curr_symbol_.push_back(space_char);
5881 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005882 return;
5883 default:
5884 break;
5885 }
5886 break;
5887 default:
5888 break;
5889 }
5890 break;
5891 default:
5892 break;
5893 }
5894 pat.field[0] = symbol;
5895 pat.field[1] = sign;
5896 pat.field[2] = none;
5897 pat.field[3] = value;
5898}
5899
5900template<>
5901void
5902moneypunct_byname<char, false>::init(const char* nm)
5903{
5904 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005905 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005906#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005907 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005908 throw runtime_error("moneypunct_byname"
5909 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005910#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005911#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005912 lconv* lc = localeconv_l(loc.get());
5913#else
5914 lconv* lc = __localeconv_l(loc.get());
5915#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005916 if (*lc->mon_decimal_point)
5917 __decimal_point_ = *lc->mon_decimal_point;
5918 else
5919 __decimal_point_ = base::do_decimal_point();
5920 if (*lc->mon_thousands_sep)
5921 __thousands_sep_ = *lc->mon_thousands_sep;
5922 else
5923 __thousands_sep_ = base::do_thousands_sep();
5924 __grouping_ = lc->mon_grouping;
5925 __curr_symbol_ = lc->currency_symbol;
5926 if (lc->frac_digits != CHAR_MAX)
5927 __frac_digits_ = lc->frac_digits;
5928 else
5929 __frac_digits_ = base::do_frac_digits();
5930 if (lc->p_sign_posn == 0)
5931 __positive_sign_ = "()";
5932 else
5933 __positive_sign_ = lc->positive_sign;
5934 if (lc->n_sign_posn == 0)
5935 __negative_sign_ = "()";
5936 else
5937 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005938 // Assume the positive and negative formats will want spaces in
5939 // the same places in curr_symbol since there's no way to
5940 // represent anything else.
5941 string_type __dummy_curr_symbol = __curr_symbol_;
5942 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5943 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5944 __init_pat(__neg_format_, __curr_symbol_, false,
5945 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005946}
5947
5948template<>
5949void
5950moneypunct_byname<char, true>::init(const char* nm)
5951{
5952 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005953 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005954#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005955 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005956 throw runtime_error("moneypunct_byname"
5957 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005958#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005959#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005960 lconv* lc = localeconv_l(loc.get());
5961#else
5962 lconv* lc = __localeconv_l(loc.get());
5963#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005964 if (*lc->mon_decimal_point)
5965 __decimal_point_ = *lc->mon_decimal_point;
5966 else
5967 __decimal_point_ = base::do_decimal_point();
5968 if (*lc->mon_thousands_sep)
5969 __thousands_sep_ = *lc->mon_thousands_sep;
5970 else
5971 __thousands_sep_ = base::do_thousands_sep();
5972 __grouping_ = lc->mon_grouping;
5973 __curr_symbol_ = lc->int_curr_symbol;
5974 if (lc->int_frac_digits != CHAR_MAX)
5975 __frac_digits_ = lc->int_frac_digits;
5976 else
5977 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00005978#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005979 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005980#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005981 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005982#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005983 __positive_sign_ = "()";
5984 else
5985 __positive_sign_ = lc->positive_sign;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005986#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005987 if(lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005988#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005989 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00005990#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005991 __negative_sign_ = "()";
5992 else
5993 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005994 // Assume the positive and negative formats will want spaces in
5995 // the same places in curr_symbol since there's no way to
5996 // represent anything else.
5997 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00005998#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005999 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6000 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
6001 __init_pat(__neg_format_, __curr_symbol_, true,
6002 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006003#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006004 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6005 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6006 lc->int_p_sign_posn, ' ');
6007 __init_pat(__neg_format_, __curr_symbol_, true,
6008 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6009 lc->int_n_sign_posn, ' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006010#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006011}
6012
6013template<>
6014void
6015moneypunct_byname<wchar_t, false>::init(const char* nm)
6016{
6017 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00006018 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00006019#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00006020 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006021 throw runtime_error("moneypunct_byname"
6022 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00006023#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00006024#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00006025 lconv* lc = localeconv_l(loc.get());
6026#else
6027 lconv* lc = __localeconv_l(loc.get());
6028#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006029 if (*lc->mon_decimal_point)
6030 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6031 else
6032 __decimal_point_ = base::do_decimal_point();
6033 if (*lc->mon_thousands_sep)
6034 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6035 else
6036 __thousands_sep_ = base::do_thousands_sep();
6037 __grouping_ = lc->mon_grouping;
6038 wchar_t wbuf[100];
6039 mbstate_t mb = {0};
6040 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00006041#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006042 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006043#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006044 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006045#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006046 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006047 __throw_runtime_error("locale not supported");
6048 wchar_t* wbe = wbuf + j;
6049 __curr_symbol_.assign(wbuf, wbe);
6050 if (lc->frac_digits != CHAR_MAX)
6051 __frac_digits_ = lc->frac_digits;
6052 else
6053 __frac_digits_ = base::do_frac_digits();
6054 if (lc->p_sign_posn == 0)
6055 __positive_sign_ = L"()";
6056 else
6057 {
6058 mb = mbstate_t();
6059 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006060#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006061 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006062#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006063 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006064#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006065 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006066 __throw_runtime_error("locale not supported");
6067 wbe = wbuf + j;
6068 __positive_sign_.assign(wbuf, wbe);
6069 }
6070 if (lc->n_sign_posn == 0)
6071 __negative_sign_ = L"()";
6072 else
6073 {
6074 mb = mbstate_t();
6075 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006076#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006077 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006078#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006079 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006080#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006081 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006082 __throw_runtime_error("locale not supported");
6083 wbe = wbuf + j;
6084 __negative_sign_.assign(wbuf, wbe);
6085 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006086 // Assume the positive and negative formats will want spaces in
6087 // the same places in curr_symbol since there's no way to
6088 // represent anything else.
6089 string_type __dummy_curr_symbol = __curr_symbol_;
6090 __init_pat(__pos_format_, __dummy_curr_symbol, false,
6091 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6092 __init_pat(__neg_format_, __curr_symbol_, false,
6093 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006094}
6095
6096template<>
6097void
6098moneypunct_byname<wchar_t, true>::init(const char* nm)
6099{
6100 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00006101 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00006102#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00006103 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006104 throw runtime_error("moneypunct_byname"
6105 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00006106#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00006107#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00006108 lconv* lc = localeconv_l(loc.get());
6109#else
6110 lconv* lc = __localeconv_l(loc.get());
6111#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006112 if (*lc->mon_decimal_point)
6113 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
6114 else
6115 __decimal_point_ = base::do_decimal_point();
6116 if (*lc->mon_thousands_sep)
6117 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
6118 else
6119 __thousands_sep_ = base::do_thousands_sep();
6120 __grouping_ = lc->mon_grouping;
6121 wchar_t wbuf[100];
6122 mbstate_t mb = {0};
6123 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00006124#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006125 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006126#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006127 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006128#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006129 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006130 __throw_runtime_error("locale not supported");
6131 wchar_t* wbe = wbuf + j;
6132 __curr_symbol_.assign(wbuf, wbe);
6133 if (lc->int_frac_digits != CHAR_MAX)
6134 __frac_digits_ = lc->int_frac_digits;
6135 else
6136 __frac_digits_ = base::do_frac_digits();
Howard Hinnantef5aa932013-09-17 01:34:47 +00006137#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006138 if (lc->p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006139#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006140 if (lc->int_p_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006141#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006142 __positive_sign_ = L"()";
6143 else
6144 {
6145 mb = mbstate_t();
6146 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006147#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006148 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006149#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006150 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006151#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006152 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006153 __throw_runtime_error("locale not supported");
6154 wbe = wbuf + j;
6155 __positive_sign_.assign(wbuf, wbe);
6156 }
Howard Hinnantef5aa932013-09-17 01:34:47 +00006157#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006158 if (lc->n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006159#else // _LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006160 if (lc->int_n_sign_posn == 0)
Howard Hinnante9df0a52013-08-01 18:17:34 +00006161#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006162 __negative_sign_ = L"()";
6163 else
6164 {
6165 mb = mbstate_t();
6166 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00006167#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006168 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006169#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00006170 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00006171#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00006172 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006173 __throw_runtime_error("locale not supported");
6174 wbe = wbuf + j;
6175 __negative_sign_.assign(wbuf, wbe);
6176 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006177 // Assume the positive and negative formats will want spaces in
6178 // the same places in curr_symbol since there's no way to
6179 // represent anything else.
6180 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnantef5aa932013-09-17 01:34:47 +00006181#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006182 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6183 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6184 __init_pat(__neg_format_, __curr_symbol_, true,
6185 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006186#else // _LIBCPP_MSVCRT
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006187 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6188 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6189 lc->int_p_sign_posn, L' ');
6190 __init_pat(__neg_format_, __curr_symbol_, true,
6191 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6192 lc->int_n_sign_posn, L' ');
Howard Hinnante9df0a52013-08-01 18:17:34 +00006193#endif // !_LIBCPP_MSVCRT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006194}
6195
6196void __do_nothing(void*) {}
6197
6198void __throw_runtime_error(const char* msg)
6199{
Howard Hinnantd4444702010-08-11 17:04:31 +00006200#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006201 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006202#else
6203 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006204#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006205}
6206
6207template class collate<char>;
6208template class collate<wchar_t>;
6209
6210template class num_get<char>;
6211template class num_get<wchar_t>;
6212
Howard Hinnantec3773c2011-12-01 20:21:04 +00006213template struct __num_get<char>;
6214template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006215
6216template class num_put<char>;
6217template class num_put<wchar_t>;
6218
Howard Hinnantec3773c2011-12-01 20:21:04 +00006219template struct __num_put<char>;
6220template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006221
6222template class time_get<char>;
6223template class time_get<wchar_t>;
6224
6225template class time_get_byname<char>;
6226template class time_get_byname<wchar_t>;
6227
6228template class time_put<char>;
6229template class time_put<wchar_t>;
6230
6231template class time_put_byname<char>;
6232template class time_put_byname<wchar_t>;
6233
6234template class moneypunct<char, false>;
6235template class moneypunct<char, true>;
6236template class moneypunct<wchar_t, false>;
6237template class moneypunct<wchar_t, true>;
6238
6239template class moneypunct_byname<char, false>;
6240template class moneypunct_byname<char, true>;
6241template class moneypunct_byname<wchar_t, false>;
6242template class moneypunct_byname<wchar_t, true>;
6243
6244template class money_get<char>;
6245template class money_get<wchar_t>;
6246
6247template class __money_get<char>;
6248template class __money_get<wchar_t>;
6249
6250template class money_put<char>;
6251template class money_put<wchar_t>;
6252
6253template class __money_put<char>;
6254template class __money_put<wchar_t>;
6255
6256template class messages<char>;
6257template class messages<wchar_t>;
6258
6259template class messages_byname<char>;
6260template class messages_byname<wchar_t>;
6261
6262template class codecvt_byname<char, char, mbstate_t>;
6263template class codecvt_byname<wchar_t, char, mbstate_t>;
6264template class codecvt_byname<char16_t, char, mbstate_t>;
6265template class codecvt_byname<char32_t, char, mbstate_t>;
6266
6267template class __vector_base_common<true>;
6268
6269_LIBCPP_END_NAMESPACE_STD