blob: db24e7e985097cd0a93596c46029bec59420b0ac [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"
21#include "algorithm"
22#include "typeinfo"
Howard Hinnantd318d492011-06-30 14:21:55 +000023#include "type_traits"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000024#include "clocale"
25#include "cstring"
26#include "cwctype"
27#include "__sso_allocator"
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000028#if _WIN32
Howard Hinnant14fa9f92011-09-29 20:33:10 +000029#include <support/win32/locale_win32.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000030#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000031#include <langinfo.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000032#endif // _!WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000033#include <stdlib.h>
34
35_LIBCPP_BEGIN_NAMESPACE_STD
36
Howard Hinnant866569b2011-09-28 23:39:33 +000037#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000038locale_t __cloc() {
39 // In theory this could create a race condition. In practice
40 // the race condition is non-fatal since it will just create
41 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000042 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
43 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000044}
Howard Hinnant866569b2011-09-28 23:39:33 +000045#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000046
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000047namespace {
48
49struct release
50{
51 void operator()(locale::facet* p) {p->__release_shared();}
52};
53
54template <class T, class A0>
55inline
56T&
57make(A0 a0)
58{
59 static typename aligned_storage<sizeof(T)>::type buf;
60 ::new (&buf) T(a0);
61 return *(T*)&buf;
62}
63
64template <class T, class A0, class A1>
65inline
66T&
67make(A0 a0, A1 a1)
68{
69 static typename aligned_storage<sizeof(T)>::type buf;
70 ::new (&buf) T(a0, a1);
71 return *(T*)&buf;
72}
73
74template <class T, class A0, class A1, class A2>
75inline
76T&
77make(A0 a0, A1 a1, A2 a2)
78{
79 static typename aligned_storage<sizeof(T)>::type buf;
80 ::new (&buf) T(a0, a1, a2);
81 return *(T*)&buf;
82}
83
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000084template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000085inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000086_LIBCPP_CONSTEXPR
87size_t
88countof(const T (&)[N])
89{
90 return N;
91}
92
93template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +000094inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000095_LIBCPP_CONSTEXPR
96size_t
97countof(const T * const begin, const T * const end)
98{
99 return static_cast<size_t>(end - begin);
100}
101
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000102}
103
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000104const locale::category locale::none;
105const locale::category locale::collate;
106const locale::category locale::ctype;
107const locale::category locale::monetary;
108const locale::category locale::numeric;
109const locale::category locale::time;
110const locale::category locale::messages;
111const locale::category locale::all;
112
Howard Hinnantec3773c2011-12-01 20:21:04 +0000113#pragma clang diagnostic push
114#pragma clang diagnostic ignored "-Wpadded"
115
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116class _LIBCPP_HIDDEN locale::__imp
117 : public facet
118{
119 enum {N = 28};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000120 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000121 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000122public:
123 explicit __imp(size_t refs = 0);
124 explicit __imp(const string& name, size_t refs = 0);
125 __imp(const __imp&);
126 __imp(const __imp&, const string&, locale::category c);
127 __imp(const __imp& other, const __imp& one, locale::category c);
128 __imp(const __imp&, facet* f, long id);
129 ~__imp();
130
131 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000132 bool has_facet(long id) const
133 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000134 const locale::facet* use_facet(long id) const;
135
136 static const locale& make_classic();
137 static locale& make_global();
138private:
139 void install(facet* f, long id);
140 template <class F> void install(F* f) {install(f, f->id.__get());}
141 template <class F> void install_from(const __imp& other);
142};
143
Howard Hinnantec3773c2011-12-01 20:21:04 +0000144#pragma clang diagnostic pop
145
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000146locale::__imp::__imp(size_t refs)
147 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000148 facets_(N),
149 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000150{
151 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000152 install(&make<_VSTD::collate<char> >(1u));
153 install(&make<_VSTD::collate<wchar_t> >(1u));
154 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
155 install(&make<_VSTD::ctype<wchar_t> >(1u));
156 install(&make<codecvt<char, char, mbstate_t> >(1u));
157 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
158 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
159 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
160 install(&make<numpunct<char> >(1u));
161 install(&make<numpunct<wchar_t> >(1u));
162 install(&make<num_get<char> >(1u));
163 install(&make<num_get<wchar_t> >(1u));
164 install(&make<num_put<char> >(1u));
165 install(&make<num_put<wchar_t> >(1u));
166 install(&make<moneypunct<char, false> >(1u));
167 install(&make<moneypunct<char, true> >(1u));
168 install(&make<moneypunct<wchar_t, false> >(1u));
169 install(&make<moneypunct<wchar_t, true> >(1u));
170 install(&make<money_get<char> >(1u));
171 install(&make<money_get<wchar_t> >(1u));
172 install(&make<money_put<char> >(1u));
173 install(&make<money_put<wchar_t> >(1u));
174 install(&make<time_get<char> >(1u));
175 install(&make<time_get<wchar_t> >(1u));
176 install(&make<time_put<char> >(1u));
177 install(&make<time_put<wchar_t> >(1u));
178 install(&make<_VSTD::messages<char> >(1u));
179 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000180}
181
182locale::__imp::__imp(const string& name, size_t refs)
183 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000184 facets_(N),
185 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000186{
Howard Hinnantd4444702010-08-11 17:04:31 +0000187#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000188 try
189 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000190#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000191 facets_ = locale::classic().__locale_->facets_;
192 for (unsigned i = 0; i < facets_.size(); ++i)
193 if (facets_[i])
194 facets_[i]->__add_shared();
195 install(new collate_byname<char>(name_));
196 install(new collate_byname<wchar_t>(name_));
197 install(new ctype_byname<char>(name_));
198 install(new ctype_byname<wchar_t>(name_));
199 install(new codecvt_byname<char, char, mbstate_t>(name_));
200 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
201 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
202 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
203 install(new numpunct_byname<char>(name_));
204 install(new numpunct_byname<wchar_t>(name_));
205 install(new moneypunct_byname<char, false>(name_));
206 install(new moneypunct_byname<char, true>(name_));
207 install(new moneypunct_byname<wchar_t, false>(name_));
208 install(new moneypunct_byname<wchar_t, true>(name_));
209 install(new time_get_byname<char>(name_));
210 install(new time_get_byname<wchar_t>(name_));
211 install(new time_put_byname<char>(name_));
212 install(new time_put_byname<wchar_t>(name_));
213 install(new messages_byname<char>(name_));
214 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000215#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000216 }
217 catch (...)
218 {
219 for (unsigned i = 0; i < facets_.size(); ++i)
220 if (facets_[i])
221 facets_[i]->__release_shared();
222 throw;
223 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000224#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000225}
226
Howard Hinnant21772ec2012-12-28 18:15:01 +0000227// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000228// copy constructor` warning emitted by GCC
Howard Hinnant5f767b72012-12-27 23:24:31 +0000229#pragma GCC diagnostic push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000230#pragma GCC diagnostic ignored "-Wextra"
Howard Hinnant5f767b72012-12-27 23:24:31 +0000231
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000232locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000233 : facets_(max<size_t>(N, other.facets_.size())),
234 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000235{
236 facets_ = other.facets_;
237 for (unsigned i = 0; i < facets_.size(); ++i)
238 if (facets_[i])
239 facets_[i]->__add_shared();
240}
241
Howard Hinnant5f767b72012-12-27 23:24:31 +0000242#pragma GCC diagnostic pop
243
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000244locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000245 : facets_(N),
246 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000247{
248 facets_ = other.facets_;
249 for (unsigned i = 0; i < facets_.size(); ++i)
250 if (facets_[i])
251 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000252#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000253 try
254 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000255#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000256 if (c & locale::collate)
257 {
258 install(new collate_byname<char>(name));
259 install(new collate_byname<wchar_t>(name));
260 }
261 if (c & locale::ctype)
262 {
263 install(new ctype_byname<char>(name));
264 install(new ctype_byname<wchar_t>(name));
265 install(new codecvt_byname<char, char, mbstate_t>(name));
266 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
267 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
268 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
269 }
270 if (c & locale::monetary)
271 {
272 install(new moneypunct_byname<char, false>(name));
273 install(new moneypunct_byname<char, true>(name));
274 install(new moneypunct_byname<wchar_t, false>(name));
275 install(new moneypunct_byname<wchar_t, true>(name));
276 }
277 if (c & locale::numeric)
278 {
279 install(new numpunct_byname<char>(name));
280 install(new numpunct_byname<wchar_t>(name));
281 }
282 if (c & locale::time)
283 {
284 install(new time_get_byname<char>(name));
285 install(new time_get_byname<wchar_t>(name));
286 install(new time_put_byname<char>(name));
287 install(new time_put_byname<wchar_t>(name));
288 }
289 if (c & locale::messages)
290 {
291 install(new messages_byname<char>(name));
292 install(new messages_byname<wchar_t>(name));
293 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000294#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000295 }
296 catch (...)
297 {
298 for (unsigned i = 0; i < facets_.size(); ++i)
299 if (facets_[i])
300 facets_[i]->__release_shared();
301 throw;
302 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000303#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000304}
305
306template<class F>
307inline
308void
309locale::__imp::install_from(const locale::__imp& one)
310{
311 long id = F::id.__get();
312 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
313}
314
315locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000316 : facets_(N),
317 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000318{
319 facets_ = other.facets_;
320 for (unsigned i = 0; i < facets_.size(); ++i)
321 if (facets_[i])
322 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000323#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000324 try
325 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000326#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000327 if (c & locale::collate)
328 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000329 install_from<_VSTD::collate<char> >(one);
330 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000331 }
332 if (c & locale::ctype)
333 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000334 install_from<_VSTD::ctype<char> >(one);
335 install_from<_VSTD::ctype<wchar_t> >(one);
336 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
337 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
338 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
339 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000340 }
341 if (c & locale::monetary)
342 {
343 install_from<moneypunct<char, false> >(one);
344 install_from<moneypunct<char, true> >(one);
345 install_from<moneypunct<wchar_t, false> >(one);
346 install_from<moneypunct<wchar_t, true> >(one);
347 install_from<money_get<char> >(one);
348 install_from<money_get<wchar_t> >(one);
349 install_from<money_put<char> >(one);
350 install_from<money_put<wchar_t> >(one);
351 }
352 if (c & locale::numeric)
353 {
354 install_from<numpunct<char> >(one);
355 install_from<numpunct<wchar_t> >(one);
356 install_from<num_get<char> >(one);
357 install_from<num_get<wchar_t> >(one);
358 install_from<num_put<char> >(one);
359 install_from<num_put<wchar_t> >(one);
360 }
361 if (c & locale::time)
362 {
363 install_from<time_get<char> >(one);
364 install_from<time_get<wchar_t> >(one);
365 install_from<time_put<char> >(one);
366 install_from<time_put<wchar_t> >(one);
367 }
368 if (c & locale::messages)
369 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000370 install_from<_VSTD::messages<char> >(one);
371 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000372 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000373#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000374 }
375 catch (...)
376 {
377 for (unsigned i = 0; i < facets_.size(); ++i)
378 if (facets_[i])
379 facets_[i]->__release_shared();
380 throw;
381 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000382#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000383}
384
385locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000386 : facets_(max<size_t>(N, other.facets_.size()+1)),
387 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000388{
389 f->__add_shared();
390 unique_ptr<facet, release> hold(f);
391 facets_ = other.facets_;
392 for (unsigned i = 0; i < other.facets_.size(); ++i)
393 if (facets_[i])
394 facets_[i]->__add_shared();
395 install(hold.get(), id);
396}
397
398locale::__imp::~__imp()
399{
400 for (unsigned i = 0; i < facets_.size(); ++i)
401 if (facets_[i])
402 facets_[i]->__release_shared();
403}
404
405void
406locale::__imp::install(facet* f, long id)
407{
408 f->__add_shared();
409 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000410 if (static_cast<size_t>(id) >= facets_.size())
411 facets_.resize(static_cast<size_t>(id+1));
412 if (facets_[static_cast<size_t>(id)])
413 facets_[static_cast<size_t>(id)]->__release_shared();
414 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000415}
416
417const locale::facet*
418locale::__imp::use_facet(long id) const
419{
Howard Hinnantd4444702010-08-11 17:04:31 +0000420#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000421 if (!has_facet(id))
422 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000423#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000424 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000425}
426
427// locale
428
429const locale&
430locale::__imp::make_classic()
431{
432 // only one thread can get in here and it only gets in once
433 static aligned_storage<sizeof(locale)>::type buf;
434 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000435 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000436 return *c;
437}
438
439const locale&
440locale::classic()
441{
442 static const locale& c = __imp::make_classic();
443 return c;
444}
445
446locale&
447locale::__imp::make_global()
448{
449 // only one thread can get in here and it only gets in once
450 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000451 ::new (&buf) locale(locale::classic());
452 return *(locale*)&buf;
453}
454
455locale&
456locale::__global()
457{
458 static locale& g = __imp::make_global();
459 return g;
460}
461
Howard Hinnantc9834542011-05-31 15:34:58 +0000462locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000463 : __locale_(__global().__locale_)
464{
465 __locale_->__add_shared();
466}
467
Howard Hinnantc9834542011-05-31 15:34:58 +0000468locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000469 : __locale_(l.__locale_)
470{
471 __locale_->__add_shared();
472}
473
Howard Hinnantc9834542011-05-31 15:34:58 +0000474locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000475{
476 __locale_->__release_shared();
477}
478
479const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000480locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000481{
482 other.__locale_->__add_shared();
483 __locale_->__release_shared();
484 __locale_ = other.__locale_;
485 return *this;
486}
487
488locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000489#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000490 : __locale_(name ? new __imp(name)
491 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000492#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000493 : __locale_(new __imp(name))
494#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000495{
496 __locale_->__add_shared();
497}
498
499locale::locale(const string& name)
500 : __locale_(new __imp(name))
501{
502 __locale_->__add_shared();
503}
504
505locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000506#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000507 : __locale_(name ? new __imp(*other.__locale_, name, c)
508 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000509#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000510 : __locale_(new __imp(*other.__locale_, name, c))
511#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000512{
513 __locale_->__add_shared();
514}
515
516locale::locale(const locale& other, const string& name, category c)
517 : __locale_(new __imp(*other.__locale_, name, c))
518{
519 __locale_->__add_shared();
520}
521
522locale::locale(const locale& other, const locale& one, category c)
523 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
524{
525 __locale_->__add_shared();
526}
527
528string
529locale::name() const
530{
531 return __locale_->name();
532}
533
534void
535locale::__install_ctor(const locale& other, facet* f, long id)
536{
537 if (f)
538 __locale_ = new __imp(*other.__locale_, f, id);
539 else
540 __locale_ = other.__locale_;
541 __locale_->__add_shared();
542}
543
544locale
545locale::global(const locale& loc)
546{
547 locale& g = __global();
548 locale r = g;
549 g = loc;
550 if (g.name() != "*")
551 setlocale(LC_ALL, g.name().c_str());
552 return r;
553}
554
555bool
556locale::has_facet(id& x) const
557{
558 return __locale_->has_facet(x.__get());
559}
560
561const locale::facet*
562locale::use_facet(id& x) const
563{
564 return __locale_->use_facet(x.__get());
565}
566
567bool
568locale::operator==(const locale& y) const
569{
570 return (__locale_ == y.__locale_)
571 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
572}
573
574// locale::facet
575
576locale::facet::~facet()
577{
578}
579
580void
Howard Hinnant1694d232011-05-28 14:41:13 +0000581locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000582{
583 delete this;
584}
585
586// locale::id
587
588int32_t locale::id::__next_id = 0;
589
590namespace
591{
592
593class __fake_bind
594{
595 locale::id* id_;
596 void (locale::id::* pmf_)();
597public:
598 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
599 : id_(id), pmf_(pmf) {}
600
601 void operator()() const
602 {
603 (id_->*pmf_)();
604 }
605};
606
607}
608
609long
610locale::id::__get()
611{
612 call_once(__flag_, __fake_bind(&locale::id::__init, this));
613 return __id_ - 1;
614}
615
616void
617locale::id::__init()
618{
Howard Hinnantadff4892010-05-24 17:49:41 +0000619 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000620}
621
622// template <> class collate_byname<char>
623
624collate_byname<char>::collate_byname(const char* n, size_t refs)
625 : collate<char>(refs),
626 __l(newlocale(LC_ALL_MASK, n, 0))
627{
Howard Hinnantd4444702010-08-11 17:04:31 +0000628#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000629 if (__l == 0)
630 throw runtime_error("collate_byname<char>::collate_byname"
631 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000632#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000633}
634
635collate_byname<char>::collate_byname(const string& name, size_t refs)
636 : collate<char>(refs),
637 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
638{
Howard Hinnantd4444702010-08-11 17:04:31 +0000639#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000640 if (__l == 0)
641 throw runtime_error("collate_byname<char>::collate_byname"
642 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000643#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000644}
645
646collate_byname<char>::~collate_byname()
647{
648 freelocale(__l);
649}
650
651int
652collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
653 const char_type* __lo2, const char_type* __hi2) const
654{
655 string_type lhs(__lo1, __hi1);
656 string_type rhs(__lo2, __hi2);
657 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
658 if (r < 0)
659 return -1;
660 if (r > 0)
661 return 1;
662 return r;
663}
664
665collate_byname<char>::string_type
666collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
667{
668 const string_type in(lo, hi);
669 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
670 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
671 return out;
672}
673
674// template <> class collate_byname<wchar_t>
675
676collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
677 : collate<wchar_t>(refs),
678 __l(newlocale(LC_ALL_MASK, n, 0))
679{
Howard Hinnantd4444702010-08-11 17:04:31 +0000680#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000681 if (__l == 0)
682 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
683 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000684#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000685}
686
687collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
688 : collate<wchar_t>(refs),
689 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
690{
Howard Hinnantd4444702010-08-11 17:04:31 +0000691#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000692 if (__l == 0)
693 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
694 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000695#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000696}
697
698collate_byname<wchar_t>::~collate_byname()
699{
700 freelocale(__l);
701}
702
703int
704collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
705 const char_type* __lo2, const char_type* __hi2) const
706{
707 string_type lhs(__lo1, __hi1);
708 string_type rhs(__lo2, __hi2);
709 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
710 if (r < 0)
711 return -1;
712 if (r > 0)
713 return 1;
714 return r;
715}
716
717collate_byname<wchar_t>::string_type
718collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
719{
720 const string_type in(lo, hi);
721 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
722 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
723 return out;
724}
725
726// template <> class ctype<wchar_t>;
727
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000728const ctype_base::mask ctype_base::space;
729const ctype_base::mask ctype_base::print;
730const ctype_base::mask ctype_base::cntrl;
731const ctype_base::mask ctype_base::upper;
732const ctype_base::mask ctype_base::lower;
733const ctype_base::mask ctype_base::alpha;
734const ctype_base::mask ctype_base::digit;
735const ctype_base::mask ctype_base::punct;
736const ctype_base::mask ctype_base::xdigit;
737const ctype_base::mask ctype_base::blank;
738const ctype_base::mask ctype_base::alnum;
739const ctype_base::mask ctype_base::graph;
740
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000741locale::id ctype<wchar_t>::id;
742
743ctype<wchar_t>::~ctype()
744{
745}
746
747bool
748ctype<wchar_t>::do_is(mask m, char_type c) const
749{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000750 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000751}
752
753const wchar_t*
754ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
755{
756 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000757 *vec = static_cast<mask>(isascii(*low) ?
758 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000759 return low;
760}
761
762const wchar_t*
763ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
764{
765 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000766 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000767 break;
768 return low;
769}
770
771const wchar_t*
772ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
773{
774 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000775 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000776 break;
777 return low;
778}
779
780wchar_t
781ctype<wchar_t>::do_toupper(char_type c) const
782{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000783#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
784 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
785#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000786 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000787#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000788 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000789#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000790}
791
792const wchar_t*
793ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
794{
795 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000796#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
797 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
798#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000799 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
800 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000801#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000802 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000803#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000804 return low;
805}
806
807wchar_t
808ctype<wchar_t>::do_tolower(char_type c) const
809{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000810#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
811 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
812#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000813 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000814#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000815 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000816#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000817}
818
819const wchar_t*
820ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
821{
822 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000823#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
824 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
825#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000826 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
827 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000828#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000829 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000830#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000831 return low;
832}
833
834wchar_t
835ctype<wchar_t>::do_widen(char c) const
836{
837 return c;
838}
839
840const char*
841ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
842{
843 for (; low != high; ++low, ++dest)
844 *dest = *low;
845 return low;
846}
847
848char
849ctype<wchar_t>::do_narrow(char_type c, char dfault) const
850{
851 if (isascii(c))
852 return static_cast<char>(c);
853 return dfault;
854}
855
856const wchar_t*
857ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
858{
859 for (; low != high; ++low, ++dest)
860 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000861 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000862 else
863 *dest = dfault;
864 return low;
865}
866
867// template <> class ctype<char>;
868
869locale::id ctype<char>::id;
870
871ctype<char>::ctype(const mask* tab, bool del, size_t refs)
872 : locale::facet(refs),
873 __tab_(tab),
874 __del_(del)
875{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000876 if (__tab_ == 0)
877 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000878}
879
880ctype<char>::~ctype()
881{
882 if (__tab_ && __del_)
883 delete [] __tab_;
884}
885
886char
887ctype<char>::do_toupper(char_type c) const
888{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000889#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000890 return isascii(c) ?
891 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000892#elif defined(__GLIBC__)
Marshall Clow88c31902013-02-07 14:22:51 +0000893 return isascii(c) ?
894 static_cast<char>(__classic_upper_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000895#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000896 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000897#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000898}
899
900const char*
901ctype<char>::do_toupper(char_type* low, const char_type* high) const
902{
903 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000904#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000905 *low = isascii(*low) ?
906 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000907#elif defined(__GLIBC__)
Marshall Clow88c31902013-02-07 14:22:51 +0000908 *low = isascii(*low) ?
909 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000910#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000911 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000912#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000913 return low;
914}
915
916char
917ctype<char>::do_tolower(char_type c) const
918{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000919#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000920 return isascii(c) ?
921 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000922#elif defined(__GLIBC__)
Marshall Clow88c31902013-02-07 14:22:51 +0000923 return isascii(c) ?
924 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000925#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000926 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000927#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000928}
929
930const char*
931ctype<char>::do_tolower(char_type* low, const char_type* high) const
932{
933 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000934#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000935 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000936#elif defined(__GLIBC__)
Marshall Clow88c31902013-02-07 14:22:51 +0000937 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000938#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000939 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000940#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000941 return low;
942}
943
944char
945ctype<char>::do_widen(char c) const
946{
947 return c;
948}
949
950const char*
951ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
952{
953 for (; low != high; ++low, ++dest)
954 *dest = *low;
955 return low;
956}
957
958char
959ctype<char>::do_narrow(char_type c, char dfault) const
960{
961 if (isascii(c))
962 return static_cast<char>(c);
963 return dfault;
964}
965
966const char*
967ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
968{
969 for (; low != high; ++low, ++dest)
970 if (isascii(*low))
971 *dest = *low;
972 else
973 *dest = dfault;
974 return low;
975}
976
977const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000978ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000979{
David Chisnallc512df12011-09-21 08:39:44 +0000980#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000981 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000982#elif defined(__GLIBC__)
983 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +0000984#elif __sun__
985 return __ctype_mask;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000986#elif _WIN32
987 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +0000988// This is assumed to be safe, which is a nonsense assumption because we're
989// going to end up dereferencing it later...
Sean Hunt62a6ac32011-07-09 00:56:23 +0000990#else
David Chisnall997e4542012-02-29 13:05:08 +0000991 // Platform not supported: abort so the person doing the port knows what to
992 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +0000993# warning ctype<char>::classic_table() is not implemented
David Chisnall997e4542012-02-29 13:05:08 +0000994 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +0000995 return NULL;
996#endif
997}
998
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000999#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001000const int*
1001ctype<char>::__classic_lower_table() _NOEXCEPT
1002{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001003 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001004}
1005
1006const int*
1007ctype<char>::__classic_upper_table() _NOEXCEPT
1008{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001009 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001010}
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001011#endif // __GLIBC__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001012
1013// template <> class ctype_byname<char>
1014
1015ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1016 : ctype<char>(0, false, refs),
1017 __l(newlocale(LC_ALL_MASK, name, 0))
1018{
Howard Hinnantd4444702010-08-11 17:04:31 +00001019#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001020 if (__l == 0)
1021 throw runtime_error("ctype_byname<char>::ctype_byname"
1022 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001023#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001024}
1025
1026ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1027 : ctype<char>(0, false, refs),
1028 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1029{
Howard Hinnantd4444702010-08-11 17:04:31 +00001030#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001031 if (__l == 0)
1032 throw runtime_error("ctype_byname<char>::ctype_byname"
1033 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001034#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001035}
1036
1037ctype_byname<char>::~ctype_byname()
1038{
1039 freelocale(__l);
1040}
1041
1042char
1043ctype_byname<char>::do_toupper(char_type c) const
1044{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001045 return static_cast<char>(toupper_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001046}
1047
1048const char*
1049ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1050{
1051 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001052 *low = static_cast<char>(toupper_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001053 return low;
1054}
1055
1056char
1057ctype_byname<char>::do_tolower(char_type c) const
1058{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001059 return static_cast<char>(tolower_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001060}
1061
1062const char*
1063ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1064{
1065 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001066 *low = static_cast<char>(tolower_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001067 return low;
1068}
1069
1070// template <> class ctype_byname<wchar_t>
1071
1072ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1073 : ctype<wchar_t>(refs),
1074 __l(newlocale(LC_ALL_MASK, name, 0))
1075{
Howard Hinnantd4444702010-08-11 17:04:31 +00001076#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001077 if (__l == 0)
1078 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1079 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001080#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001081}
1082
1083ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1084 : ctype<wchar_t>(refs),
1085 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1086{
Howard Hinnantd4444702010-08-11 17:04:31 +00001087#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001088 if (__l == 0)
1089 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1090 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001091#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001092}
1093
1094ctype_byname<wchar_t>::~ctype_byname()
1095{
1096 freelocale(__l);
1097}
1098
1099bool
1100ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1101{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001102#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001103 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001104#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001105 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001106 wint_t ch = static_cast<wint_t>(c);
1107 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1108 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1109 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1110 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1111 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1112 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1113 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1114 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1115 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1116 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001117 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001118#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001119}
1120
1121const wchar_t*
1122ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1123{
1124 for (; low != high; ++low, ++vec)
1125 {
1126 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001127 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001128 else
1129 {
1130 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001131 wint_t ch = static_cast<wint_t>(*low);
1132 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001133 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001134 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001135 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001136 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001137 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001138 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001139 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001140 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001141 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001142 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001143 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001144 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001145 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001146 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001147 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001148 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001149 *vec |= xdigit;
1150 }
1151 }
1152 return low;
1153}
1154
1155const wchar_t*
1156ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1157{
1158 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001159 {
1160#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001161 if (iswctype_l(*low, m, __l))
1162 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001163#else
Marshall Clow88c31902013-02-07 14:22:51 +00001164 wint_t ch = static_cast<wint_t>(*low);
1165 if (m & space && iswspace_l(ch, __l)) break;
1166 if (m & print && iswprint_l(ch, __l)) break;
1167 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1168 if (m & upper && iswupper_l(ch, __l)) break;
1169 if (m & lower && iswlower_l(ch, __l)) break;
1170 if (m & alpha && iswalpha_l(ch, __l)) break;
1171 if (m & digit && iswdigit_l(ch, __l)) break;
1172 if (m & punct && iswpunct_l(ch, __l)) break;
1173 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1174 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001175#endif
1176 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001177 return low;
1178}
1179
1180const wchar_t*
1181ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1182{
1183 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001184 {
1185#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001186 if (!iswctype_l(*low, m, __l))
1187 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001188#else
Marshall Clow88c31902013-02-07 14:22:51 +00001189 wint_t ch = static_cast<wint_t>(*low);
1190 if (m & space && iswspace_l(ch, __l)) continue;
1191 if (m & print && iswprint_l(ch, __l)) continue;
1192 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1193 if (m & upper && iswupper_l(ch, __l)) continue;
1194 if (m & lower && iswlower_l(ch, __l)) continue;
1195 if (m & alpha && iswalpha_l(ch, __l)) continue;
1196 if (m & digit && iswdigit_l(ch, __l)) continue;
1197 if (m & punct && iswpunct_l(ch, __l)) continue;
1198 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1199 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001200 break;
1201#endif
1202 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001203 return low;
1204}
1205
1206wchar_t
1207ctype_byname<wchar_t>::do_toupper(char_type c) const
1208{
1209 return towupper_l(c, __l);
1210}
1211
1212const wchar_t*
1213ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1214{
1215 for (; low != high; ++low)
1216 *low = towupper_l(*low, __l);
1217 return low;
1218}
1219
1220wchar_t
1221ctype_byname<wchar_t>::do_tolower(char_type c) const
1222{
1223 return towlower_l(c, __l);
1224}
1225
1226const wchar_t*
1227ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1228{
1229 for (; low != high; ++low)
1230 *low = towlower_l(*low, __l);
1231 return low;
1232}
1233
1234wchar_t
1235ctype_byname<wchar_t>::do_widen(char c) const
1236{
Howard Hinnant866569b2011-09-28 23:39:33 +00001237#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001238 return btowc_l(c, __l);
1239#else
1240 return __btowc_l(c, __l);
1241#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001242}
1243
1244const char*
1245ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1246{
1247 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001248#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001249 *dest = btowc_l(*low, __l);
1250#else
1251 *dest = __btowc_l(*low, __l);
1252#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001253 return low;
1254}
1255
1256char
1257ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1258{
Howard Hinnant866569b2011-09-28 23:39:33 +00001259#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001260 int r = wctob_l(c, __l);
1261#else
1262 int r = __wctob_l(c, __l);
1263#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001264 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001265}
1266
1267const wchar_t*
1268ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1269{
1270 for (; low != high; ++low, ++dest)
1271 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001272#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001273 int r = wctob_l(*low, __l);
1274#else
1275 int r = __wctob_l(*low, __l);
1276#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001277 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001278 }
1279 return low;
1280}
1281
1282// template <> class codecvt<char, char, mbstate_t>
1283
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001284locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001285
1286codecvt<char, char, mbstate_t>::~codecvt()
1287{
1288}
1289
1290codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001291codecvt<char, char, mbstate_t>::do_out(state_type&,
1292 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001293 extern_type* to, extern_type*, extern_type*& to_nxt) const
1294{
1295 frm_nxt = frm;
1296 to_nxt = to;
1297 return noconv;
1298}
1299
1300codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001301codecvt<char, char, mbstate_t>::do_in(state_type&,
1302 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001303 intern_type* to, intern_type*, intern_type*& to_nxt) const
1304{
1305 frm_nxt = frm;
1306 to_nxt = to;
1307 return noconv;
1308}
1309
1310codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001311codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001312 extern_type* to, extern_type*, extern_type*& to_nxt) const
1313{
1314 to_nxt = to;
1315 return noconv;
1316}
1317
1318int
Howard Hinnantc9834542011-05-31 15:34:58 +00001319codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001320{
1321 return 1;
1322}
1323
1324bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001325codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001326{
1327 return true;
1328}
1329
1330int
1331codecvt<char, char, mbstate_t>::do_length(state_type&,
1332 const extern_type* frm, const extern_type* end, size_t mx) const
1333{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001334 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001335}
1336
1337int
Howard Hinnantc9834542011-05-31 15:34:58 +00001338codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001339{
1340 return 1;
1341}
1342
1343// template <> class codecvt<wchar_t, char, mbstate_t>
1344
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001345locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001346
1347codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1348 : locale::facet(refs),
1349 __l(0)
1350{
1351}
1352
1353codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1354 : locale::facet(refs),
1355 __l(newlocale(LC_ALL_MASK, nm, 0))
1356{
Howard Hinnantd4444702010-08-11 17:04:31 +00001357#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001358 if (__l == 0)
1359 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1360 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001361#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001362}
1363
1364codecvt<wchar_t, char, mbstate_t>::~codecvt()
1365{
1366 if (__l != 0)
1367 freelocale(__l);
1368}
1369
1370codecvt<wchar_t, char, mbstate_t>::result
1371codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001372 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001373 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1374{
1375 // look for first internal null in frm
1376 const intern_type* fend = frm;
1377 for (; fend != frm_end; ++fend)
1378 if (*fend == 0)
1379 break;
1380 // loop over all null-terminated sequences in frm
1381 to_nxt = to;
1382 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1383 {
1384 // save state in case needed to reover to_nxt on error
1385 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001386#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001387 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1388 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001389#else
1390 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1391#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001392 if (n == size_t(-1))
1393 {
1394 // need to recover to_nxt
1395 for (to_nxt = to; frm != frm_nxt; ++frm)
1396 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001397#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001398 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1399#else
1400 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1401#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001402 if (n == size_t(-1))
1403 break;
1404 to_nxt += n;
1405 }
1406 frm_nxt = frm;
1407 return error;
1408 }
1409 if (n == 0)
1410 return partial;
1411 to_nxt += n;
1412 if (to_nxt == to_end)
1413 break;
1414 if (fend != frm_end) // set up next null terminated sequence
1415 {
1416 // Try to write the terminating null
1417 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001418#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001419 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1420#else
1421 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1422#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001423 if (n == size_t(-1)) // on error
1424 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001425 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001426 return partial;
1427 for (extern_type* p = tmp; n; --n) // write it
1428 *to_nxt++ = *p++;
1429 ++frm_nxt;
1430 // look for next null in frm
1431 for (fend = frm_nxt; fend != frm_end; ++fend)
1432 if (*fend == 0)
1433 break;
1434 }
1435 }
1436 return frm_nxt == frm_end ? ok : partial;
1437}
1438
1439codecvt<wchar_t, char, mbstate_t>::result
1440codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001441 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001442 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1443{
1444 // look for first internal null in frm
1445 const extern_type* fend = frm;
1446 for (; fend != frm_end; ++fend)
1447 if (*fend == 0)
1448 break;
1449 // loop over all null-terminated sequences in frm
1450 to_nxt = to;
1451 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1452 {
1453 // save state in case needed to reover to_nxt on error
1454 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001455#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001456 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1457 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001458#else
1459 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1460#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001461 if (n == size_t(-1))
1462 {
1463 // need to recover to_nxt
1464 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1465 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001466#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001467 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1468 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001469#else
1470 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1471#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001472 switch (n)
1473 {
1474 case 0:
1475 ++frm;
1476 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001477 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001478 frm_nxt = frm;
1479 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001480 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001481 frm_nxt = frm;
1482 return partial;
1483 default:
1484 frm += n;
1485 break;
1486 }
1487 }
1488 frm_nxt = frm;
1489 return frm_nxt == frm_end ? ok : partial;
1490 }
1491 if (n == 0)
1492 return error;
1493 to_nxt += n;
1494 if (to_nxt == to_end)
1495 break;
1496 if (fend != frm_end) // set up next null terminated sequence
1497 {
1498 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001499#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001500 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1501#else
1502 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1503#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001504 if (n != 0) // on error
1505 return error;
1506 ++to_nxt;
1507 ++frm_nxt;
1508 // look for next null in frm
1509 for (fend = frm_nxt; fend != frm_end; ++fend)
1510 if (*fend == 0)
1511 break;
1512 }
1513 }
1514 return frm_nxt == frm_end ? ok : partial;
1515}
1516
1517codecvt<wchar_t, char, mbstate_t>::result
1518codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1519 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1520{
1521 to_nxt = to;
1522 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001523#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001524 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1525#else
1526 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1527#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001528 if (n == size_t(-1) || n == 0) // on error
1529 return error;
1530 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001531 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001532 return partial;
1533 for (extern_type* p = tmp; n; --n) // write it
1534 *to_nxt++ = *p++;
1535 return ok;
1536}
1537
1538int
Howard Hinnantc9834542011-05-31 15:34:58 +00001539codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001540{
Howard Hinnant866569b2011-09-28 23:39:33 +00001541#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001542 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1543#else
1544 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1545#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001546 {
1547 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001548#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001549 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1550#else
1551 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1552#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001553 return 1; // which take more than 1 char to form a wchar_t
1554 return 0;
1555 }
1556 return -1;
1557}
1558
1559bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001560codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001561{
1562 return false;
1563}
1564
1565int
1566codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1567 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1568{
1569 int nbytes = 0;
1570 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1571 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001572#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001573 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001574#else
1575 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1576#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001577 switch (n)
1578 {
1579 case 0:
1580 ++nbytes;
1581 ++frm;
1582 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001583 case size_t(-1):
1584 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001585 return nbytes;
1586 default:
1587 nbytes += n;
1588 frm += n;
1589 break;
1590 }
1591 }
1592 return nbytes;
1593}
1594
1595int
Howard Hinnantc9834542011-05-31 15:34:58 +00001596codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001597{
Howard Hinnant866569b2011-09-28 23:39:33 +00001598#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001599 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1600#else
1601 return __l == 0 ? 1 : __mb_cur_max_l(__l);
1602#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001603}
1604
1605// Valid UTF ranges
1606// UTF-32 UTF-16 UTF-8 # of code points
1607// first second first second third fourth
1608// 000000 - 00007F 0000 - 007F 00 - 7F 127
1609// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1610// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1611// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1612// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1613// 00D800 - 00DFFF invalid
1614// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1615// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1616// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1617// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1618
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001619static
1620codecvt_base::result
1621utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1622 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1623 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1624{
1625 frm_nxt = frm;
1626 to_nxt = to;
1627 if (mode & generate_header)
1628 {
1629 if (to_end-to_nxt < 3)
1630 return codecvt_base::partial;
1631 *to_nxt++ = static_cast<uint8_t>(0xEF);
1632 *to_nxt++ = static_cast<uint8_t>(0xBB);
1633 *to_nxt++ = static_cast<uint8_t>(0xBF);
1634 }
1635 for (; frm_nxt < frm_end; ++frm_nxt)
1636 {
1637 uint16_t wc1 = *frm_nxt;
1638 if (wc1 > Maxcode)
1639 return codecvt_base::error;
1640 if (wc1 < 0x0080)
1641 {
1642 if (to_end-to_nxt < 1)
1643 return codecvt_base::partial;
1644 *to_nxt++ = static_cast<uint8_t>(wc1);
1645 }
1646 else if (wc1 < 0x0800)
1647 {
1648 if (to_end-to_nxt < 2)
1649 return codecvt_base::partial;
1650 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1651 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1652 }
1653 else if (wc1 < 0xD800)
1654 {
1655 if (to_end-to_nxt < 3)
1656 return codecvt_base::partial;
1657 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1658 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1659 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1660 }
1661 else if (wc1 < 0xDC00)
1662 {
1663 if (frm_end-frm_nxt < 2)
1664 return codecvt_base::partial;
1665 uint16_t wc2 = frm_nxt[1];
1666 if ((wc2 & 0xFC00) != 0xDC00)
1667 return codecvt_base::error;
1668 if (to_end-to_nxt < 4)
1669 return codecvt_base::partial;
1670 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1671 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1672 return codecvt_base::error;
1673 ++frm_nxt;
1674 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1675 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1676 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1677 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1678 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1679 }
1680 else if (wc1 < 0xE000)
1681 {
1682 return codecvt_base::error;
1683 }
1684 else
1685 {
1686 if (to_end-to_nxt < 3)
1687 return codecvt_base::partial;
1688 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1689 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1690 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1691 }
1692 }
1693 return codecvt_base::ok;
1694}
1695
1696static
1697codecvt_base::result
1698utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1699 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1700 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1701{
1702 frm_nxt = frm;
1703 to_nxt = to;
1704 if (mode & generate_header)
1705 {
1706 if (to_end-to_nxt < 3)
1707 return codecvt_base::partial;
1708 *to_nxt++ = static_cast<uint8_t>(0xEF);
1709 *to_nxt++ = static_cast<uint8_t>(0xBB);
1710 *to_nxt++ = static_cast<uint8_t>(0xBF);
1711 }
1712 for (; frm_nxt < frm_end; ++frm_nxt)
1713 {
1714 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1715 if (wc1 > Maxcode)
1716 return codecvt_base::error;
1717 if (wc1 < 0x0080)
1718 {
1719 if (to_end-to_nxt < 1)
1720 return codecvt_base::partial;
1721 *to_nxt++ = static_cast<uint8_t>(wc1);
1722 }
1723 else if (wc1 < 0x0800)
1724 {
1725 if (to_end-to_nxt < 2)
1726 return codecvt_base::partial;
1727 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1728 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1729 }
1730 else if (wc1 < 0xD800)
1731 {
1732 if (to_end-to_nxt < 3)
1733 return codecvt_base::partial;
1734 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1735 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1736 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1737 }
1738 else if (wc1 < 0xDC00)
1739 {
1740 if (frm_end-frm_nxt < 2)
1741 return codecvt_base::partial;
1742 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1743 if ((wc2 & 0xFC00) != 0xDC00)
1744 return codecvt_base::error;
1745 if (to_end-to_nxt < 4)
1746 return codecvt_base::partial;
1747 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1748 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1749 return codecvt_base::error;
1750 ++frm_nxt;
1751 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1752 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1753 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1754 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1755 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1756 }
1757 else if (wc1 < 0xE000)
1758 {
1759 return codecvt_base::error;
1760 }
1761 else
1762 {
1763 if (to_end-to_nxt < 3)
1764 return codecvt_base::partial;
1765 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1766 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1767 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1768 }
1769 }
1770 return codecvt_base::ok;
1771}
1772
1773static
1774codecvt_base::result
1775utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1776 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1777 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1778{
1779 frm_nxt = frm;
1780 to_nxt = to;
1781 if (mode & consume_header)
1782 {
1783 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1784 frm_nxt[2] == 0xBF)
1785 frm_nxt += 3;
1786 }
1787 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1788 {
1789 uint8_t c1 = *frm_nxt;
1790 if (c1 > Maxcode)
1791 return codecvt_base::error;
1792 if (c1 < 0x80)
1793 {
1794 *to_nxt = static_cast<uint16_t>(c1);
1795 ++frm_nxt;
1796 }
1797 else if (c1 < 0xC2)
1798 {
1799 return codecvt_base::error;
1800 }
1801 else if (c1 < 0xE0)
1802 {
1803 if (frm_end-frm_nxt < 2)
1804 return codecvt_base::partial;
1805 uint8_t c2 = frm_nxt[1];
1806 if ((c2 & 0xC0) != 0x80)
1807 return codecvt_base::error;
1808 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1809 if (t > Maxcode)
1810 return codecvt_base::error;
1811 *to_nxt = t;
1812 frm_nxt += 2;
1813 }
1814 else if (c1 < 0xF0)
1815 {
1816 if (frm_end-frm_nxt < 3)
1817 return codecvt_base::partial;
1818 uint8_t c2 = frm_nxt[1];
1819 uint8_t c3 = frm_nxt[2];
1820 switch (c1)
1821 {
1822 case 0xE0:
1823 if ((c2 & 0xE0) != 0xA0)
1824 return codecvt_base::error;
1825 break;
1826 case 0xED:
1827 if ((c2 & 0xE0) != 0x80)
1828 return codecvt_base::error;
1829 break;
1830 default:
1831 if ((c2 & 0xC0) != 0x80)
1832 return codecvt_base::error;
1833 break;
1834 }
1835 if ((c3 & 0xC0) != 0x80)
1836 return codecvt_base::error;
1837 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1838 | ((c2 & 0x3F) << 6)
1839 | (c3 & 0x3F));
1840 if (t > Maxcode)
1841 return codecvt_base::error;
1842 *to_nxt = t;
1843 frm_nxt += 3;
1844 }
1845 else if (c1 < 0xF5)
1846 {
1847 if (frm_end-frm_nxt < 4)
1848 return codecvt_base::partial;
1849 uint8_t c2 = frm_nxt[1];
1850 uint8_t c3 = frm_nxt[2];
1851 uint8_t c4 = frm_nxt[3];
1852 switch (c1)
1853 {
1854 case 0xF0:
1855 if (!(0x90 <= c2 && c2 <= 0xBF))
1856 return codecvt_base::error;
1857 break;
1858 case 0xF4:
1859 if ((c2 & 0xF0) != 0x80)
1860 return codecvt_base::error;
1861 break;
1862 default:
1863 if ((c2 & 0xC0) != 0x80)
1864 return codecvt_base::error;
1865 break;
1866 }
1867 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1868 return codecvt_base::error;
1869 if (to_end-to_nxt < 2)
1870 return codecvt_base::partial;
1871 if (((((unsigned long)c1 & 7) << 18) +
1872 (((unsigned long)c2 & 0x3F) << 12) +
1873 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1874 return codecvt_base::error;
1875 *to_nxt = static_cast<uint16_t>(
1876 0xD800
1877 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1878 | ((c2 & 0x0F) << 2)
1879 | ((c3 & 0x30) >> 4));
1880 *++to_nxt = static_cast<uint16_t>(
1881 0xDC00
1882 | ((c3 & 0x0F) << 6)
1883 | (c4 & 0x3F));
1884 frm_nxt += 4;
1885 }
1886 else
1887 {
1888 return codecvt_base::error;
1889 }
1890 }
1891 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1892}
1893
1894static
1895codecvt_base::result
1896utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1897 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1898 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1899{
1900 frm_nxt = frm;
1901 to_nxt = to;
1902 if (mode & consume_header)
1903 {
1904 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1905 frm_nxt[2] == 0xBF)
1906 frm_nxt += 3;
1907 }
1908 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1909 {
1910 uint8_t c1 = *frm_nxt;
1911 if (c1 > Maxcode)
1912 return codecvt_base::error;
1913 if (c1 < 0x80)
1914 {
1915 *to_nxt = static_cast<uint32_t>(c1);
1916 ++frm_nxt;
1917 }
1918 else if (c1 < 0xC2)
1919 {
1920 return codecvt_base::error;
1921 }
1922 else if (c1 < 0xE0)
1923 {
1924 if (frm_end-frm_nxt < 2)
1925 return codecvt_base::partial;
1926 uint8_t c2 = frm_nxt[1];
1927 if ((c2 & 0xC0) != 0x80)
1928 return codecvt_base::error;
1929 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1930 if (t > Maxcode)
1931 return codecvt_base::error;
1932 *to_nxt = static_cast<uint32_t>(t);
1933 frm_nxt += 2;
1934 }
1935 else if (c1 < 0xF0)
1936 {
1937 if (frm_end-frm_nxt < 3)
1938 return codecvt_base::partial;
1939 uint8_t c2 = frm_nxt[1];
1940 uint8_t c3 = frm_nxt[2];
1941 switch (c1)
1942 {
1943 case 0xE0:
1944 if ((c2 & 0xE0) != 0xA0)
1945 return codecvt_base::error;
1946 break;
1947 case 0xED:
1948 if ((c2 & 0xE0) != 0x80)
1949 return codecvt_base::error;
1950 break;
1951 default:
1952 if ((c2 & 0xC0) != 0x80)
1953 return codecvt_base::error;
1954 break;
1955 }
1956 if ((c3 & 0xC0) != 0x80)
1957 return codecvt_base::error;
1958 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1959 | ((c2 & 0x3F) << 6)
1960 | (c3 & 0x3F));
1961 if (t > Maxcode)
1962 return codecvt_base::error;
1963 *to_nxt = static_cast<uint32_t>(t);
1964 frm_nxt += 3;
1965 }
1966 else if (c1 < 0xF5)
1967 {
1968 if (frm_end-frm_nxt < 4)
1969 return codecvt_base::partial;
1970 uint8_t c2 = frm_nxt[1];
1971 uint8_t c3 = frm_nxt[2];
1972 uint8_t c4 = frm_nxt[3];
1973 switch (c1)
1974 {
1975 case 0xF0:
1976 if (!(0x90 <= c2 && c2 <= 0xBF))
1977 return codecvt_base::error;
1978 break;
1979 case 0xF4:
1980 if ((c2 & 0xF0) != 0x80)
1981 return codecvt_base::error;
1982 break;
1983 default:
1984 if ((c2 & 0xC0) != 0x80)
1985 return codecvt_base::error;
1986 break;
1987 }
1988 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1989 return codecvt_base::error;
1990 if (to_end-to_nxt < 2)
1991 return codecvt_base::partial;
1992 if (((((unsigned long)c1 & 7) << 18) +
1993 (((unsigned long)c2 & 0x3F) << 12) +
1994 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1995 return codecvt_base::error;
1996 *to_nxt = static_cast<uint32_t>(
1997 0xD800
1998 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1999 | ((c2 & 0x0F) << 2)
2000 | ((c3 & 0x30) >> 4));
2001 *++to_nxt = static_cast<uint32_t>(
2002 0xDC00
2003 | ((c3 & 0x0F) << 6)
2004 | (c4 & 0x3F));
2005 frm_nxt += 4;
2006 }
2007 else
2008 {
2009 return codecvt_base::error;
2010 }
2011 }
2012 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2013}
2014
2015static
2016int
2017utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2018 size_t mx, unsigned long Maxcode = 0x10FFFF,
2019 codecvt_mode mode = codecvt_mode(0))
2020{
2021 const uint8_t* frm_nxt = frm;
2022 if (mode & consume_header)
2023 {
2024 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2025 frm_nxt[2] == 0xBF)
2026 frm_nxt += 3;
2027 }
2028 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2029 {
2030 uint8_t c1 = *frm_nxt;
2031 if (c1 > Maxcode)
2032 break;
2033 if (c1 < 0x80)
2034 {
2035 ++frm_nxt;
2036 }
2037 else if (c1 < 0xC2)
2038 {
2039 break;
2040 }
2041 else if (c1 < 0xE0)
2042 {
2043 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2044 break;
2045 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2046 if (t > Maxcode)
2047 break;
2048 frm_nxt += 2;
2049 }
2050 else if (c1 < 0xF0)
2051 {
2052 if (frm_end-frm_nxt < 3)
2053 break;
2054 uint8_t c2 = frm_nxt[1];
2055 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002056 switch (c1)
2057 {
2058 case 0xE0:
2059 if ((c2 & 0xE0) != 0xA0)
2060 return static_cast<int>(frm_nxt - frm);
2061 break;
2062 case 0xED:
2063 if ((c2 & 0xE0) != 0x80)
2064 return static_cast<int>(frm_nxt - frm);
2065 break;
2066 default:
2067 if ((c2 & 0xC0) != 0x80)
2068 return static_cast<int>(frm_nxt - frm);
2069 break;
2070 }
2071 if ((c3 & 0xC0) != 0x80)
2072 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002073 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002074 break;
2075 frm_nxt += 3;
2076 }
2077 else if (c1 < 0xF5)
2078 {
2079 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2080 break;
2081 uint8_t c2 = frm_nxt[1];
2082 uint8_t c3 = frm_nxt[2];
2083 uint8_t c4 = frm_nxt[3];
2084 switch (c1)
2085 {
2086 case 0xF0:
2087 if (!(0x90 <= c2 && c2 <= 0xBF))
2088 return static_cast<int>(frm_nxt - frm);
2089 break;
2090 case 0xF4:
2091 if ((c2 & 0xF0) != 0x80)
2092 return static_cast<int>(frm_nxt - frm);
2093 break;
2094 default:
2095 if ((c2 & 0xC0) != 0x80)
2096 return static_cast<int>(frm_nxt - frm);
2097 break;
2098 }
2099 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2100 break;
2101 if (((((unsigned long)c1 & 7) << 18) +
2102 (((unsigned long)c2 & 0x3F) << 12) +
2103 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2104 break;
2105 ++nchar16_t;
2106 frm_nxt += 4;
2107 }
2108 else
2109 {
2110 break;
2111 }
2112 }
2113 return static_cast<int>(frm_nxt - frm);
2114}
2115
2116static
2117codecvt_base::result
2118ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2119 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2120 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2121{
2122 frm_nxt = frm;
2123 to_nxt = to;
2124 if (mode & generate_header)
2125 {
2126 if (to_end-to_nxt < 3)
2127 return codecvt_base::partial;
2128 *to_nxt++ = static_cast<uint8_t>(0xEF);
2129 *to_nxt++ = static_cast<uint8_t>(0xBB);
2130 *to_nxt++ = static_cast<uint8_t>(0xBF);
2131 }
2132 for (; frm_nxt < frm_end; ++frm_nxt)
2133 {
2134 uint32_t wc = *frm_nxt;
2135 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2136 return codecvt_base::error;
2137 if (wc < 0x000080)
2138 {
2139 if (to_end-to_nxt < 1)
2140 return codecvt_base::partial;
2141 *to_nxt++ = static_cast<uint8_t>(wc);
2142 }
2143 else if (wc < 0x000800)
2144 {
2145 if (to_end-to_nxt < 2)
2146 return codecvt_base::partial;
2147 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2148 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2149 }
2150 else if (wc < 0x010000)
2151 {
2152 if (to_end-to_nxt < 3)
2153 return codecvt_base::partial;
2154 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2155 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2156 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2157 }
2158 else // if (wc < 0x110000)
2159 {
2160 if (to_end-to_nxt < 4)
2161 return codecvt_base::partial;
2162 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2163 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2164 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2165 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2166 }
2167 }
2168 return codecvt_base::ok;
2169}
2170
2171static
2172codecvt_base::result
2173utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2174 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2175 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2176{
2177 frm_nxt = frm;
2178 to_nxt = to;
2179 if (mode & consume_header)
2180 {
2181 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2182 frm_nxt[2] == 0xBF)
2183 frm_nxt += 3;
2184 }
2185 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2186 {
2187 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2188 if (c1 < 0x80)
2189 {
2190 if (c1 > Maxcode)
2191 return codecvt_base::error;
2192 *to_nxt = static_cast<uint32_t>(c1);
2193 ++frm_nxt;
2194 }
2195 else if (c1 < 0xC2)
2196 {
2197 return codecvt_base::error;
2198 }
2199 else if (c1 < 0xE0)
2200 {
2201 if (frm_end-frm_nxt < 2)
2202 return codecvt_base::partial;
2203 uint8_t c2 = frm_nxt[1];
2204 if ((c2 & 0xC0) != 0x80)
2205 return codecvt_base::error;
2206 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2207 | (c2 & 0x3F));
2208 if (t > Maxcode)
2209 return codecvt_base::error;
2210 *to_nxt = t;
2211 frm_nxt += 2;
2212 }
2213 else if (c1 < 0xF0)
2214 {
2215 if (frm_end-frm_nxt < 3)
2216 return codecvt_base::partial;
2217 uint8_t c2 = frm_nxt[1];
2218 uint8_t c3 = frm_nxt[2];
2219 switch (c1)
2220 {
2221 case 0xE0:
2222 if ((c2 & 0xE0) != 0xA0)
2223 return codecvt_base::error;
2224 break;
2225 case 0xED:
2226 if ((c2 & 0xE0) != 0x80)
2227 return codecvt_base::error;
2228 break;
2229 default:
2230 if ((c2 & 0xC0) != 0x80)
2231 return codecvt_base::error;
2232 break;
2233 }
2234 if ((c3 & 0xC0) != 0x80)
2235 return codecvt_base::error;
2236 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2237 | ((c2 & 0x3F) << 6)
2238 | (c3 & 0x3F));
2239 if (t > Maxcode)
2240 return codecvt_base::error;
2241 *to_nxt = t;
2242 frm_nxt += 3;
2243 }
2244 else if (c1 < 0xF5)
2245 {
2246 if (frm_end-frm_nxt < 4)
2247 return codecvt_base::partial;
2248 uint8_t c2 = frm_nxt[1];
2249 uint8_t c3 = frm_nxt[2];
2250 uint8_t c4 = frm_nxt[3];
2251 switch (c1)
2252 {
2253 case 0xF0:
2254 if (!(0x90 <= c2 && c2 <= 0xBF))
2255 return codecvt_base::error;
2256 break;
2257 case 0xF4:
2258 if ((c2 & 0xF0) != 0x80)
2259 return codecvt_base::error;
2260 break;
2261 default:
2262 if ((c2 & 0xC0) != 0x80)
2263 return codecvt_base::error;
2264 break;
2265 }
2266 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2267 return codecvt_base::error;
2268 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2269 | ((c2 & 0x3F) << 12)
2270 | ((c3 & 0x3F) << 6)
2271 | (c4 & 0x3F));
2272 if (t > Maxcode)
2273 return codecvt_base::error;
2274 *to_nxt = t;
2275 frm_nxt += 4;
2276 }
2277 else
2278 {
2279 return codecvt_base::error;
2280 }
2281 }
2282 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2283}
2284
2285static
2286int
2287utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2288 size_t mx, unsigned long Maxcode = 0x10FFFF,
2289 codecvt_mode mode = codecvt_mode(0))
2290{
2291 const uint8_t* frm_nxt = frm;
2292 if (mode & consume_header)
2293 {
2294 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2295 frm_nxt[2] == 0xBF)
2296 frm_nxt += 3;
2297 }
2298 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2299 {
2300 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2301 if (c1 < 0x80)
2302 {
2303 if (c1 > Maxcode)
2304 break;
2305 ++frm_nxt;
2306 }
2307 else if (c1 < 0xC2)
2308 {
2309 break;
2310 }
2311 else if (c1 < 0xE0)
2312 {
2313 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2314 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002315 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002316 break;
2317 frm_nxt += 2;
2318 }
2319 else if (c1 < 0xF0)
2320 {
2321 if (frm_end-frm_nxt < 3)
2322 break;
2323 uint8_t c2 = frm_nxt[1];
2324 uint8_t c3 = frm_nxt[2];
2325 switch (c1)
2326 {
2327 case 0xE0:
2328 if ((c2 & 0xE0) != 0xA0)
2329 return static_cast<int>(frm_nxt - frm);
2330 break;
2331 case 0xED:
2332 if ((c2 & 0xE0) != 0x80)
2333 return static_cast<int>(frm_nxt - frm);
2334 break;
2335 default:
2336 if ((c2 & 0xC0) != 0x80)
2337 return static_cast<int>(frm_nxt - frm);
2338 break;
2339 }
2340 if ((c3 & 0xC0) != 0x80)
2341 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002342 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002343 break;
2344 frm_nxt += 3;
2345 }
2346 else if (c1 < 0xF5)
2347 {
2348 if (frm_end-frm_nxt < 4)
2349 break;
2350 uint8_t c2 = frm_nxt[1];
2351 uint8_t c3 = frm_nxt[2];
2352 uint8_t c4 = frm_nxt[3];
2353 switch (c1)
2354 {
2355 case 0xF0:
2356 if (!(0x90 <= c2 && c2 <= 0xBF))
2357 return static_cast<int>(frm_nxt - frm);
2358 break;
2359 case 0xF4:
2360 if ((c2 & 0xF0) != 0x80)
2361 return static_cast<int>(frm_nxt - frm);
2362 break;
2363 default:
2364 if ((c2 & 0xC0) != 0x80)
2365 return static_cast<int>(frm_nxt - frm);
2366 break;
2367 }
2368 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2369 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002370 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2371 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002372 break;
2373 frm_nxt += 4;
2374 }
2375 else
2376 {
2377 break;
2378 }
2379 }
2380 return static_cast<int>(frm_nxt - frm);
2381}
2382
2383static
2384codecvt_base::result
2385ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2386 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2387 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2388{
2389 frm_nxt = frm;
2390 to_nxt = to;
2391 if (mode & generate_header)
2392 {
2393 if (to_end-to_nxt < 3)
2394 return codecvt_base::partial;
2395 *to_nxt++ = static_cast<uint8_t>(0xEF);
2396 *to_nxt++ = static_cast<uint8_t>(0xBB);
2397 *to_nxt++ = static_cast<uint8_t>(0xBF);
2398 }
2399 for (; frm_nxt < frm_end; ++frm_nxt)
2400 {
2401 uint16_t wc = *frm_nxt;
2402 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2403 return codecvt_base::error;
2404 if (wc < 0x0080)
2405 {
2406 if (to_end-to_nxt < 1)
2407 return codecvt_base::partial;
2408 *to_nxt++ = static_cast<uint8_t>(wc);
2409 }
2410 else if (wc < 0x0800)
2411 {
2412 if (to_end-to_nxt < 2)
2413 return codecvt_base::partial;
2414 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2415 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2416 }
2417 else // if (wc <= 0xFFFF)
2418 {
2419 if (to_end-to_nxt < 3)
2420 return codecvt_base::partial;
2421 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2422 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2423 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2424 }
2425 }
2426 return codecvt_base::ok;
2427}
2428
2429static
2430codecvt_base::result
2431utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2432 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2433 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2434{
2435 frm_nxt = frm;
2436 to_nxt = to;
2437 if (mode & consume_header)
2438 {
2439 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2440 frm_nxt[2] == 0xBF)
2441 frm_nxt += 3;
2442 }
2443 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2444 {
2445 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2446 if (c1 < 0x80)
2447 {
2448 if (c1 > Maxcode)
2449 return codecvt_base::error;
2450 *to_nxt = static_cast<uint16_t>(c1);
2451 ++frm_nxt;
2452 }
2453 else if (c1 < 0xC2)
2454 {
2455 return codecvt_base::error;
2456 }
2457 else if (c1 < 0xE0)
2458 {
2459 if (frm_end-frm_nxt < 2)
2460 return codecvt_base::partial;
2461 uint8_t c2 = frm_nxt[1];
2462 if ((c2 & 0xC0) != 0x80)
2463 return codecvt_base::error;
2464 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2465 | (c2 & 0x3F));
2466 if (t > Maxcode)
2467 return codecvt_base::error;
2468 *to_nxt = t;
2469 frm_nxt += 2;
2470 }
2471 else if (c1 < 0xF0)
2472 {
2473 if (frm_end-frm_nxt < 3)
2474 return codecvt_base::partial;
2475 uint8_t c2 = frm_nxt[1];
2476 uint8_t c3 = frm_nxt[2];
2477 switch (c1)
2478 {
2479 case 0xE0:
2480 if ((c2 & 0xE0) != 0xA0)
2481 return codecvt_base::error;
2482 break;
2483 case 0xED:
2484 if ((c2 & 0xE0) != 0x80)
2485 return codecvt_base::error;
2486 break;
2487 default:
2488 if ((c2 & 0xC0) != 0x80)
2489 return codecvt_base::error;
2490 break;
2491 }
2492 if ((c3 & 0xC0) != 0x80)
2493 return codecvt_base::error;
2494 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2495 | ((c2 & 0x3F) << 6)
2496 | (c3 & 0x3F));
2497 if (t > Maxcode)
2498 return codecvt_base::error;
2499 *to_nxt = t;
2500 frm_nxt += 3;
2501 }
2502 else
2503 {
2504 return codecvt_base::error;
2505 }
2506 }
2507 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2508}
2509
2510static
2511int
2512utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2513 size_t mx, unsigned long Maxcode = 0x10FFFF,
2514 codecvt_mode mode = codecvt_mode(0))
2515{
2516 const uint8_t* frm_nxt = frm;
2517 if (mode & consume_header)
2518 {
2519 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2520 frm_nxt[2] == 0xBF)
2521 frm_nxt += 3;
2522 }
2523 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2524 {
2525 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2526 if (c1 < 0x80)
2527 {
2528 if (c1 > Maxcode)
2529 break;
2530 ++frm_nxt;
2531 }
2532 else if (c1 < 0xC2)
2533 {
2534 break;
2535 }
2536 else if (c1 < 0xE0)
2537 {
2538 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2539 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002540 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002541 break;
2542 frm_nxt += 2;
2543 }
2544 else if (c1 < 0xF0)
2545 {
2546 if (frm_end-frm_nxt < 3)
2547 break;
2548 uint8_t c2 = frm_nxt[1];
2549 uint8_t c3 = frm_nxt[2];
2550 switch (c1)
2551 {
2552 case 0xE0:
2553 if ((c2 & 0xE0) != 0xA0)
2554 return static_cast<int>(frm_nxt - frm);
2555 break;
2556 case 0xED:
2557 if ((c2 & 0xE0) != 0x80)
2558 return static_cast<int>(frm_nxt - frm);
2559 break;
2560 default:
2561 if ((c2 & 0xC0) != 0x80)
2562 return static_cast<int>(frm_nxt - frm);
2563 break;
2564 }
2565 if ((c3 & 0xC0) != 0x80)
2566 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002567 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002568 break;
2569 frm_nxt += 3;
2570 }
2571 else
2572 {
2573 break;
2574 }
2575 }
2576 return static_cast<int>(frm_nxt - frm);
2577}
2578
2579static
2580codecvt_base::result
2581ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2582 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2583 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2584{
2585 frm_nxt = frm;
2586 to_nxt = to;
2587 if (mode & generate_header)
2588 {
2589 if (to_end-to_nxt < 2)
2590 return codecvt_base::partial;
2591 *to_nxt++ = static_cast<uint8_t>(0xFE);
2592 *to_nxt++ = static_cast<uint8_t>(0xFF);
2593 }
2594 for (; frm_nxt < frm_end; ++frm_nxt)
2595 {
2596 uint32_t wc = *frm_nxt;
2597 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2598 return codecvt_base::error;
2599 if (wc < 0x010000)
2600 {
2601 if (to_end-to_nxt < 2)
2602 return codecvt_base::partial;
2603 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2604 *to_nxt++ = static_cast<uint8_t>(wc);
2605 }
2606 else
2607 {
2608 if (to_end-to_nxt < 4)
2609 return codecvt_base::partial;
2610 uint16_t t = static_cast<uint16_t>(
2611 0xD800
2612 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2613 | ((wc & 0x00FC00) >> 10));
2614 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2615 *to_nxt++ = static_cast<uint8_t>(t);
2616 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2617 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2618 *to_nxt++ = static_cast<uint8_t>(t);
2619 }
2620 }
2621 return codecvt_base::ok;
2622}
2623
2624static
2625codecvt_base::result
2626utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2627 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2628 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2629{
2630 frm_nxt = frm;
2631 to_nxt = to;
2632 if (mode & consume_header)
2633 {
2634 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2635 frm_nxt += 2;
2636 }
2637 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2638 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002639 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002640 if ((c1 & 0xFC00) == 0xDC00)
2641 return codecvt_base::error;
2642 if ((c1 & 0xFC00) != 0xD800)
2643 {
2644 if (c1 > Maxcode)
2645 return codecvt_base::error;
2646 *to_nxt = static_cast<uint32_t>(c1);
2647 frm_nxt += 2;
2648 }
2649 else
2650 {
2651 if (frm_end-frm_nxt < 4)
2652 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002653 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002654 if ((c2 & 0xFC00) != 0xDC00)
2655 return codecvt_base::error;
2656 uint32_t t = static_cast<uint32_t>(
2657 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2658 | ((c1 & 0x003F) << 10)
2659 | (c2 & 0x03FF));
2660 if (t > Maxcode)
2661 return codecvt_base::error;
2662 *to_nxt = t;
2663 frm_nxt += 4;
2664 }
2665 }
2666 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2667}
2668
2669static
2670int
2671utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2672 size_t mx, unsigned long Maxcode = 0x10FFFF,
2673 codecvt_mode mode = codecvt_mode(0))
2674{
2675 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002676 if (mode & consume_header)
2677 {
2678 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2679 frm_nxt += 2;
2680 }
2681 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2682 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002683 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002684 if ((c1 & 0xFC00) == 0xDC00)
2685 break;
2686 if ((c1 & 0xFC00) != 0xD800)
2687 {
2688 if (c1 > Maxcode)
2689 break;
2690 frm_nxt += 2;
2691 }
2692 else
2693 {
2694 if (frm_end-frm_nxt < 4)
2695 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002696 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002697 if ((c2 & 0xFC00) != 0xDC00)
2698 break;
2699 uint32_t t = static_cast<uint32_t>(
2700 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2701 | ((c1 & 0x003F) << 10)
2702 | (c2 & 0x03FF));
2703 if (t > Maxcode)
2704 break;
2705 frm_nxt += 4;
2706 }
2707 }
2708 return static_cast<int>(frm_nxt - frm);
2709}
2710
2711static
2712codecvt_base::result
2713ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2714 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2715 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2716{
2717 frm_nxt = frm;
2718 to_nxt = to;
2719 if (mode & generate_header)
2720 {
2721 if (to_end-to_nxt < 2)
2722 return codecvt_base::partial;
2723 *to_nxt++ = static_cast<uint8_t>(0xFF);
2724 *to_nxt++ = static_cast<uint8_t>(0xFE);
2725 }
2726 for (; frm_nxt < frm_end; ++frm_nxt)
2727 {
2728 uint32_t wc = *frm_nxt;
2729 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2730 return codecvt_base::error;
2731 if (wc < 0x010000)
2732 {
2733 if (to_end-to_nxt < 2)
2734 return codecvt_base::partial;
2735 *to_nxt++ = static_cast<uint8_t>(wc);
2736 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2737 }
2738 else
2739 {
2740 if (to_end-to_nxt < 4)
2741 return codecvt_base::partial;
2742 uint16_t t = static_cast<uint16_t>(
2743 0xD800
2744 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2745 | ((wc & 0x00FC00) >> 10));
2746 *to_nxt++ = static_cast<uint8_t>(t);
2747 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2748 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2749 *to_nxt++ = static_cast<uint8_t>(t);
2750 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2751 }
2752 }
2753 return codecvt_base::ok;
2754}
2755
2756static
2757codecvt_base::result
2758utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2759 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2760 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2761{
2762 frm_nxt = frm;
2763 to_nxt = to;
2764 if (mode & consume_header)
2765 {
2766 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2767 frm_nxt += 2;
2768 }
2769 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2770 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002771 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002772 if ((c1 & 0xFC00) == 0xDC00)
2773 return codecvt_base::error;
2774 if ((c1 & 0xFC00) != 0xD800)
2775 {
2776 if (c1 > Maxcode)
2777 return codecvt_base::error;
2778 *to_nxt = static_cast<uint32_t>(c1);
2779 frm_nxt += 2;
2780 }
2781 else
2782 {
2783 if (frm_end-frm_nxt < 4)
2784 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002785 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002786 if ((c2 & 0xFC00) != 0xDC00)
2787 return codecvt_base::error;
2788 uint32_t t = static_cast<uint32_t>(
2789 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2790 | ((c1 & 0x003F) << 10)
2791 | (c2 & 0x03FF));
2792 if (t > Maxcode)
2793 return codecvt_base::error;
2794 *to_nxt = t;
2795 frm_nxt += 4;
2796 }
2797 }
2798 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2799}
2800
2801static
2802int
2803utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2804 size_t mx, unsigned long Maxcode = 0x10FFFF,
2805 codecvt_mode mode = codecvt_mode(0))
2806{
2807 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002808 if (mode & consume_header)
2809 {
2810 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2811 frm_nxt += 2;
2812 }
2813 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2814 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002815 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002816 if ((c1 & 0xFC00) == 0xDC00)
2817 break;
2818 if ((c1 & 0xFC00) != 0xD800)
2819 {
2820 if (c1 > Maxcode)
2821 break;
2822 frm_nxt += 2;
2823 }
2824 else
2825 {
2826 if (frm_end-frm_nxt < 4)
2827 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002828 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002829 if ((c2 & 0xFC00) != 0xDC00)
2830 break;
2831 uint32_t t = static_cast<uint32_t>(
2832 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2833 | ((c1 & 0x003F) << 10)
2834 | (c2 & 0x03FF));
2835 if (t > Maxcode)
2836 break;
2837 frm_nxt += 4;
2838 }
2839 }
2840 return static_cast<int>(frm_nxt - frm);
2841}
2842
2843static
2844codecvt_base::result
2845ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2846 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2847 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2848{
2849 frm_nxt = frm;
2850 to_nxt = to;
2851 if (mode & generate_header)
2852 {
2853 if (to_end-to_nxt < 2)
2854 return codecvt_base::partial;
2855 *to_nxt++ = static_cast<uint8_t>(0xFE);
2856 *to_nxt++ = static_cast<uint8_t>(0xFF);
2857 }
2858 for (; frm_nxt < frm_end; ++frm_nxt)
2859 {
2860 uint16_t wc = *frm_nxt;
2861 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2862 return codecvt_base::error;
2863 if (to_end-to_nxt < 2)
2864 return codecvt_base::partial;
2865 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2866 *to_nxt++ = static_cast<uint8_t>(wc);
2867 }
2868 return codecvt_base::ok;
2869}
2870
2871static
2872codecvt_base::result
2873utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2874 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2875 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2876{
2877 frm_nxt = frm;
2878 to_nxt = to;
2879 if (mode & consume_header)
2880 {
2881 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2882 frm_nxt += 2;
2883 }
2884 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2885 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002886 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002887 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2888 return codecvt_base::error;
2889 *to_nxt = c1;
2890 frm_nxt += 2;
2891 }
2892 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2893}
2894
2895static
2896int
2897utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2898 size_t mx, unsigned long Maxcode = 0x10FFFF,
2899 codecvt_mode mode = codecvt_mode(0))
2900{
2901 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002902 if (mode & consume_header)
2903 {
2904 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2905 frm_nxt += 2;
2906 }
2907 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2908 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002909 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002910 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2911 break;
2912 frm_nxt += 2;
2913 }
2914 return static_cast<int>(frm_nxt - frm);
2915}
2916
2917static
2918codecvt_base::result
2919ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2920 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2921 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2922{
2923 frm_nxt = frm;
2924 to_nxt = to;
2925 if (mode & generate_header)
2926 {
2927 if (to_end-to_nxt < 2)
2928 return codecvt_base::partial;
2929 *to_nxt++ = static_cast<uint8_t>(0xFF);
2930 *to_nxt++ = static_cast<uint8_t>(0xFE);
2931 }
2932 for (; frm_nxt < frm_end; ++frm_nxt)
2933 {
2934 uint16_t wc = *frm_nxt;
2935 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2936 return codecvt_base::error;
2937 if (to_end-to_nxt < 2)
2938 return codecvt_base::partial;
2939 *to_nxt++ = static_cast<uint8_t>(wc);
2940 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2941 }
2942 return codecvt_base::ok;
2943}
2944
2945static
2946codecvt_base::result
2947utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2948 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2949 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2950{
2951 frm_nxt = frm;
2952 to_nxt = to;
2953 if (mode & consume_header)
2954 {
2955 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2956 frm_nxt += 2;
2957 }
2958 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2959 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002960 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002961 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2962 return codecvt_base::error;
2963 *to_nxt = c1;
2964 frm_nxt += 2;
2965 }
2966 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2967}
2968
2969static
2970int
2971utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2972 size_t mx, unsigned long Maxcode = 0x10FFFF,
2973 codecvt_mode mode = codecvt_mode(0))
2974{
2975 const uint8_t* frm_nxt = frm;
2976 frm_nxt = frm;
2977 if (mode & consume_header)
2978 {
2979 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2980 frm_nxt += 2;
2981 }
2982 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2983 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002984 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002985 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2986 break;
2987 frm_nxt += 2;
2988 }
2989 return static_cast<int>(frm_nxt - frm);
2990}
2991
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002992// template <> class codecvt<char16_t, char, mbstate_t>
2993
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002994locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002995
2996codecvt<char16_t, char, mbstate_t>::~codecvt()
2997{
2998}
2999
3000codecvt<char16_t, char, mbstate_t>::result
3001codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003002 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003003 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3004{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003005 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3006 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3007 const uint16_t* _frm_nxt = _frm;
3008 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3009 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3010 uint8_t* _to_nxt = _to;
3011 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3012 frm_nxt = frm + (_frm_nxt - _frm);
3013 to_nxt = to + (_to_nxt - _to);
3014 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003015}
3016
3017codecvt<char16_t, char, mbstate_t>::result
3018codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003019 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003020 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3021{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003022 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3023 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3024 const uint8_t* _frm_nxt = _frm;
3025 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3026 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3027 uint16_t* _to_nxt = _to;
3028 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3029 frm_nxt = frm + (_frm_nxt - _frm);
3030 to_nxt = to + (_to_nxt - _to);
3031 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003032}
3033
3034codecvt<char16_t, char, mbstate_t>::result
3035codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3036 extern_type* to, extern_type*, extern_type*& to_nxt) const
3037{
3038 to_nxt = to;
3039 return noconv;
3040}
3041
3042int
Howard Hinnantc9834542011-05-31 15:34:58 +00003043codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003044{
3045 return 0;
3046}
3047
3048bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003049codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003050{
3051 return false;
3052}
3053
3054int
3055codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3056 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3057{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003058 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3059 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3060 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003061}
3062
3063int
Howard Hinnantc9834542011-05-31 15:34:58 +00003064codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003065{
3066 return 4;
3067}
3068
3069// template <> class codecvt<char32_t, char, mbstate_t>
3070
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003071locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003072
3073codecvt<char32_t, char, mbstate_t>::~codecvt()
3074{
3075}
3076
3077codecvt<char32_t, char, mbstate_t>::result
3078codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003079 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003080 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3081{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003082 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3083 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3084 const uint32_t* _frm_nxt = _frm;
3085 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3086 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3087 uint8_t* _to_nxt = _to;
3088 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3089 frm_nxt = frm + (_frm_nxt - _frm);
3090 to_nxt = to + (_to_nxt - _to);
3091 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003092}
3093
3094codecvt<char32_t, char, mbstate_t>::result
3095codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003096 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003097 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3098{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003099 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3100 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3101 const uint8_t* _frm_nxt = _frm;
3102 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3103 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3104 uint32_t* _to_nxt = _to;
3105 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3106 frm_nxt = frm + (_frm_nxt - _frm);
3107 to_nxt = to + (_to_nxt - _to);
3108 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003109}
3110
3111codecvt<char32_t, char, mbstate_t>::result
3112codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3113 extern_type* to, extern_type*, extern_type*& to_nxt) const
3114{
3115 to_nxt = to;
3116 return noconv;
3117}
3118
3119int
Howard Hinnantc9834542011-05-31 15:34:58 +00003120codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003121{
3122 return 0;
3123}
3124
3125bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003126codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003127{
3128 return false;
3129}
3130
3131int
3132codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3133 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3134{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003135 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3136 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3137 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003138}
3139
3140int
Howard Hinnantc9834542011-05-31 15:34:58 +00003141codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003142{
3143 return 4;
3144}
3145
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003146// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003147
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003148__codecvt_utf8<wchar_t>::result
3149__codecvt_utf8<wchar_t>::do_out(state_type&,
3150 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003151 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3152{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003153 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3154 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3155 const uint32_t* _frm_nxt = _frm;
3156 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3157 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3158 uint8_t* _to_nxt = _to;
3159 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3160 _Maxcode_, _Mode_);
3161 frm_nxt = frm + (_frm_nxt - _frm);
3162 to_nxt = to + (_to_nxt - _to);
3163 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003164}
3165
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003166__codecvt_utf8<wchar_t>::result
3167__codecvt_utf8<wchar_t>::do_in(state_type&,
3168 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003169 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3170{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003171 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3172 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3173 const uint8_t* _frm_nxt = _frm;
3174 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3175 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3176 uint32_t* _to_nxt = _to;
3177 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3178 _Maxcode_, _Mode_);
3179 frm_nxt = frm + (_frm_nxt - _frm);
3180 to_nxt = to + (_to_nxt - _to);
3181 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003182}
3183
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003184__codecvt_utf8<wchar_t>::result
3185__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003186 extern_type* to, extern_type*, extern_type*& to_nxt) const
3187{
3188 to_nxt = to;
3189 return noconv;
3190}
3191
3192int
Howard Hinnantc9834542011-05-31 15:34:58 +00003193__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003194{
3195 return 0;
3196}
3197
3198bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003199__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003200{
3201 return false;
3202}
3203
3204int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003205__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003206 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3207{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003208 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3209 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3210 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003211}
3212
3213int
Howard Hinnantc9834542011-05-31 15:34:58 +00003214__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003215{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003216 if (_Mode_ & consume_header)
3217 return 7;
3218 return 4;
3219}
3220
3221// __codecvt_utf8<char16_t>
3222
3223__codecvt_utf8<char16_t>::result
3224__codecvt_utf8<char16_t>::do_out(state_type&,
3225 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3226 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3227{
3228 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3229 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3230 const uint16_t* _frm_nxt = _frm;
3231 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3232 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3233 uint8_t* _to_nxt = _to;
3234 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3235 _Maxcode_, _Mode_);
3236 frm_nxt = frm + (_frm_nxt - _frm);
3237 to_nxt = to + (_to_nxt - _to);
3238 return r;
3239}
3240
3241__codecvt_utf8<char16_t>::result
3242__codecvt_utf8<char16_t>::do_in(state_type&,
3243 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3244 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3245{
3246 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3247 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3248 const uint8_t* _frm_nxt = _frm;
3249 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3250 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3251 uint16_t* _to_nxt = _to;
3252 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3253 _Maxcode_, _Mode_);
3254 frm_nxt = frm + (_frm_nxt - _frm);
3255 to_nxt = to + (_to_nxt - _to);
3256 return r;
3257}
3258
3259__codecvt_utf8<char16_t>::result
3260__codecvt_utf8<char16_t>::do_unshift(state_type&,
3261 extern_type* to, extern_type*, extern_type*& to_nxt) const
3262{
3263 to_nxt = to;
3264 return noconv;
3265}
3266
3267int
Howard Hinnantc9834542011-05-31 15:34:58 +00003268__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003269{
3270 return 0;
3271}
3272
3273bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003274__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003275{
3276 return false;
3277}
3278
3279int
3280__codecvt_utf8<char16_t>::do_length(state_type&,
3281 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3282{
3283 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3284 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3285 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3286}
3287
3288int
Howard Hinnantc9834542011-05-31 15:34:58 +00003289__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003290{
3291 if (_Mode_ & consume_header)
3292 return 6;
3293 return 3;
3294}
3295
3296// __codecvt_utf8<char32_t>
3297
3298__codecvt_utf8<char32_t>::result
3299__codecvt_utf8<char32_t>::do_out(state_type&,
3300 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3301 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3302{
3303 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3304 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3305 const uint32_t* _frm_nxt = _frm;
3306 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3307 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3308 uint8_t* _to_nxt = _to;
3309 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3310 _Maxcode_, _Mode_);
3311 frm_nxt = frm + (_frm_nxt - _frm);
3312 to_nxt = to + (_to_nxt - _to);
3313 return r;
3314}
3315
3316__codecvt_utf8<char32_t>::result
3317__codecvt_utf8<char32_t>::do_in(state_type&,
3318 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3319 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3320{
3321 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3322 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3323 const uint8_t* _frm_nxt = _frm;
3324 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3325 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3326 uint32_t* _to_nxt = _to;
3327 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3328 _Maxcode_, _Mode_);
3329 frm_nxt = frm + (_frm_nxt - _frm);
3330 to_nxt = to + (_to_nxt - _to);
3331 return r;
3332}
3333
3334__codecvt_utf8<char32_t>::result
3335__codecvt_utf8<char32_t>::do_unshift(state_type&,
3336 extern_type* to, extern_type*, extern_type*& to_nxt) const
3337{
3338 to_nxt = to;
3339 return noconv;
3340}
3341
3342int
Howard Hinnantc9834542011-05-31 15:34:58 +00003343__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003344{
3345 return 0;
3346}
3347
3348bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003349__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003350{
3351 return false;
3352}
3353
3354int
3355__codecvt_utf8<char32_t>::do_length(state_type&,
3356 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3357{
3358 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3359 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3360 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3361}
3362
3363int
Howard Hinnantc9834542011-05-31 15:34:58 +00003364__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003365{
3366 if (_Mode_ & consume_header)
3367 return 7;
3368 return 4;
3369}
3370
3371// __codecvt_utf16<wchar_t, false>
3372
3373__codecvt_utf16<wchar_t, false>::result
3374__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3375 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3376 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3377{
3378 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3379 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3380 const uint32_t* _frm_nxt = _frm;
3381 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3382 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3383 uint8_t* _to_nxt = _to;
3384 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3385 _Maxcode_, _Mode_);
3386 frm_nxt = frm + (_frm_nxt - _frm);
3387 to_nxt = to + (_to_nxt - _to);
3388 return r;
3389}
3390
3391__codecvt_utf16<wchar_t, false>::result
3392__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3393 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3394 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3395{
3396 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3397 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3398 const uint8_t* _frm_nxt = _frm;
3399 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3400 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3401 uint32_t* _to_nxt = _to;
3402 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3403 _Maxcode_, _Mode_);
3404 frm_nxt = frm + (_frm_nxt - _frm);
3405 to_nxt = to + (_to_nxt - _to);
3406 return r;
3407}
3408
3409__codecvt_utf16<wchar_t, false>::result
3410__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3411 extern_type* to, extern_type*, extern_type*& to_nxt) const
3412{
3413 to_nxt = to;
3414 return noconv;
3415}
3416
3417int
Howard Hinnantc9834542011-05-31 15:34:58 +00003418__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003419{
3420 return 0;
3421}
3422
3423bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003424__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003425{
3426 return false;
3427}
3428
3429int
3430__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3431 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3432{
3433 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3434 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3435 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3436}
3437
3438int
Howard Hinnantc9834542011-05-31 15:34:58 +00003439__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003440{
3441 if (_Mode_ & consume_header)
3442 return 6;
3443 return 4;
3444}
3445
3446// __codecvt_utf16<wchar_t, true>
3447
3448__codecvt_utf16<wchar_t, true>::result
3449__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3450 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3451 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3452{
3453 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3454 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3455 const uint32_t* _frm_nxt = _frm;
3456 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3457 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3458 uint8_t* _to_nxt = _to;
3459 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3460 _Maxcode_, _Mode_);
3461 frm_nxt = frm + (_frm_nxt - _frm);
3462 to_nxt = to + (_to_nxt - _to);
3463 return r;
3464}
3465
3466__codecvt_utf16<wchar_t, true>::result
3467__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3468 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3469 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3470{
3471 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3472 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3473 const uint8_t* _frm_nxt = _frm;
3474 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3475 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3476 uint32_t* _to_nxt = _to;
3477 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3478 _Maxcode_, _Mode_);
3479 frm_nxt = frm + (_frm_nxt - _frm);
3480 to_nxt = to + (_to_nxt - _to);
3481 return r;
3482}
3483
3484__codecvt_utf16<wchar_t, true>::result
3485__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3486 extern_type* to, extern_type*, extern_type*& to_nxt) const
3487{
3488 to_nxt = to;
3489 return noconv;
3490}
3491
3492int
Howard Hinnantc9834542011-05-31 15:34:58 +00003493__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003494{
3495 return 0;
3496}
3497
3498bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003499__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003500{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003501 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003502}
3503
3504int
3505__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3506 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3507{
3508 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3509 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3510 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3511}
3512
3513int
Howard Hinnantc9834542011-05-31 15:34:58 +00003514__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003515{
3516 if (_Mode_ & consume_header)
3517 return 6;
3518 return 4;
3519}
3520
3521// __codecvt_utf16<char16_t, false>
3522
3523__codecvt_utf16<char16_t, false>::result
3524__codecvt_utf16<char16_t, false>::do_out(state_type&,
3525 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3526 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3527{
3528 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3529 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3530 const uint16_t* _frm_nxt = _frm;
3531 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3532 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3533 uint8_t* _to_nxt = _to;
3534 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3535 _Maxcode_, _Mode_);
3536 frm_nxt = frm + (_frm_nxt - _frm);
3537 to_nxt = to + (_to_nxt - _to);
3538 return r;
3539}
3540
3541__codecvt_utf16<char16_t, false>::result
3542__codecvt_utf16<char16_t, false>::do_in(state_type&,
3543 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3544 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3545{
3546 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3547 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3548 const uint8_t* _frm_nxt = _frm;
3549 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3550 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3551 uint16_t* _to_nxt = _to;
3552 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3553 _Maxcode_, _Mode_);
3554 frm_nxt = frm + (_frm_nxt - _frm);
3555 to_nxt = to + (_to_nxt - _to);
3556 return r;
3557}
3558
3559__codecvt_utf16<char16_t, false>::result
3560__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3561 extern_type* to, extern_type*, extern_type*& to_nxt) const
3562{
3563 to_nxt = to;
3564 return noconv;
3565}
3566
3567int
Howard Hinnantc9834542011-05-31 15:34:58 +00003568__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003569{
3570 return 0;
3571}
3572
3573bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003574__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003575{
3576 return false;
3577}
3578
3579int
3580__codecvt_utf16<char16_t, false>::do_length(state_type&,
3581 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3582{
3583 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3584 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3585 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3586}
3587
3588int
Howard Hinnantc9834542011-05-31 15:34:58 +00003589__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003590{
3591 if (_Mode_ & consume_header)
3592 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003593 return 2;
3594}
3595
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003596// __codecvt_utf16<char16_t, true>
3597
3598__codecvt_utf16<char16_t, true>::result
3599__codecvt_utf16<char16_t, true>::do_out(state_type&,
3600 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3601 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3602{
3603 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3604 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3605 const uint16_t* _frm_nxt = _frm;
3606 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3607 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3608 uint8_t* _to_nxt = _to;
3609 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3610 _Maxcode_, _Mode_);
3611 frm_nxt = frm + (_frm_nxt - _frm);
3612 to_nxt = to + (_to_nxt - _to);
3613 return r;
3614}
3615
3616__codecvt_utf16<char16_t, true>::result
3617__codecvt_utf16<char16_t, true>::do_in(state_type&,
3618 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3619 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3620{
3621 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3622 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3623 const uint8_t* _frm_nxt = _frm;
3624 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3625 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3626 uint16_t* _to_nxt = _to;
3627 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3628 _Maxcode_, _Mode_);
3629 frm_nxt = frm + (_frm_nxt - _frm);
3630 to_nxt = to + (_to_nxt - _to);
3631 return r;
3632}
3633
3634__codecvt_utf16<char16_t, true>::result
3635__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3636 extern_type* to, extern_type*, extern_type*& to_nxt) const
3637{
3638 to_nxt = to;
3639 return noconv;
3640}
3641
3642int
Howard Hinnantc9834542011-05-31 15:34:58 +00003643__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003644{
3645 return 0;
3646}
3647
3648bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003649__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003650{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003651 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003652}
3653
3654int
3655__codecvt_utf16<char16_t, true>::do_length(state_type&,
3656 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3657{
3658 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3659 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3660 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3661}
3662
3663int
Howard Hinnantc9834542011-05-31 15:34:58 +00003664__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003665{
3666 if (_Mode_ & consume_header)
3667 return 4;
3668 return 2;
3669}
3670
3671// __codecvt_utf16<char32_t, false>
3672
3673__codecvt_utf16<char32_t, false>::result
3674__codecvt_utf16<char32_t, false>::do_out(state_type&,
3675 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3676 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3677{
3678 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3679 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3680 const uint32_t* _frm_nxt = _frm;
3681 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3682 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3683 uint8_t* _to_nxt = _to;
3684 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3685 _Maxcode_, _Mode_);
3686 frm_nxt = frm + (_frm_nxt - _frm);
3687 to_nxt = to + (_to_nxt - _to);
3688 return r;
3689}
3690
3691__codecvt_utf16<char32_t, false>::result
3692__codecvt_utf16<char32_t, false>::do_in(state_type&,
3693 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3694 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3695{
3696 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3697 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3698 const uint8_t* _frm_nxt = _frm;
3699 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3700 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3701 uint32_t* _to_nxt = _to;
3702 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3703 _Maxcode_, _Mode_);
3704 frm_nxt = frm + (_frm_nxt - _frm);
3705 to_nxt = to + (_to_nxt - _to);
3706 return r;
3707}
3708
3709__codecvt_utf16<char32_t, false>::result
3710__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3711 extern_type* to, extern_type*, extern_type*& to_nxt) const
3712{
3713 to_nxt = to;
3714 return noconv;
3715}
3716
3717int
Howard Hinnantc9834542011-05-31 15:34:58 +00003718__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003719{
3720 return 0;
3721}
3722
3723bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003724__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003725{
3726 return false;
3727}
3728
3729int
3730__codecvt_utf16<char32_t, false>::do_length(state_type&,
3731 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3732{
3733 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3734 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3735 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3736}
3737
3738int
Howard Hinnantc9834542011-05-31 15:34:58 +00003739__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003740{
3741 if (_Mode_ & consume_header)
3742 return 6;
3743 return 4;
3744}
3745
3746// __codecvt_utf16<char32_t, true>
3747
3748__codecvt_utf16<char32_t, true>::result
3749__codecvt_utf16<char32_t, true>::do_out(state_type&,
3750 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3751 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3752{
3753 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3754 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3755 const uint32_t* _frm_nxt = _frm;
3756 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3757 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3758 uint8_t* _to_nxt = _to;
3759 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3760 _Maxcode_, _Mode_);
3761 frm_nxt = frm + (_frm_nxt - _frm);
3762 to_nxt = to + (_to_nxt - _to);
3763 return r;
3764}
3765
3766__codecvt_utf16<char32_t, true>::result
3767__codecvt_utf16<char32_t, true>::do_in(state_type&,
3768 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3769 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3770{
3771 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3772 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3773 const uint8_t* _frm_nxt = _frm;
3774 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3775 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3776 uint32_t* _to_nxt = _to;
3777 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3778 _Maxcode_, _Mode_);
3779 frm_nxt = frm + (_frm_nxt - _frm);
3780 to_nxt = to + (_to_nxt - _to);
3781 return r;
3782}
3783
3784__codecvt_utf16<char32_t, true>::result
3785__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3786 extern_type* to, extern_type*, extern_type*& to_nxt) const
3787{
3788 to_nxt = to;
3789 return noconv;
3790}
3791
3792int
Howard Hinnantc9834542011-05-31 15:34:58 +00003793__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003794{
3795 return 0;
3796}
3797
3798bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003799__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003800{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003801 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003802}
3803
3804int
3805__codecvt_utf16<char32_t, true>::do_length(state_type&,
3806 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3807{
3808 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3809 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3810 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3811}
3812
3813int
Howard Hinnantc9834542011-05-31 15:34:58 +00003814__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003815{
3816 if (_Mode_ & consume_header)
3817 return 6;
3818 return 4;
3819}
3820
3821// __codecvt_utf8_utf16<wchar_t>
3822
3823__codecvt_utf8_utf16<wchar_t>::result
3824__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3825 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3826 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3827{
3828 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3829 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3830 const uint32_t* _frm_nxt = _frm;
3831 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3832 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3833 uint8_t* _to_nxt = _to;
3834 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3835 _Maxcode_, _Mode_);
3836 frm_nxt = frm + (_frm_nxt - _frm);
3837 to_nxt = to + (_to_nxt - _to);
3838 return r;
3839}
3840
3841__codecvt_utf8_utf16<wchar_t>::result
3842__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3843 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3844 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3845{
3846 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3847 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3848 const uint8_t* _frm_nxt = _frm;
3849 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3850 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3851 uint32_t* _to_nxt = _to;
3852 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3853 _Maxcode_, _Mode_);
3854 frm_nxt = frm + (_frm_nxt - _frm);
3855 to_nxt = to + (_to_nxt - _to);
3856 return r;
3857}
3858
3859__codecvt_utf8_utf16<wchar_t>::result
3860__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3861 extern_type* to, extern_type*, extern_type*& to_nxt) const
3862{
3863 to_nxt = to;
3864 return noconv;
3865}
3866
3867int
Howard Hinnantc9834542011-05-31 15:34:58 +00003868__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003869{
3870 return 0;
3871}
3872
3873bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003874__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003875{
3876 return false;
3877}
3878
3879int
3880__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3881 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3882{
3883 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3884 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3885 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3886}
3887
3888int
Howard Hinnantc9834542011-05-31 15:34:58 +00003889__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003890{
3891 if (_Mode_ & consume_header)
3892 return 7;
3893 return 4;
3894}
3895
3896// __codecvt_utf8_utf16<char16_t>
3897
3898__codecvt_utf8_utf16<char16_t>::result
3899__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3900 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3901 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3902{
3903 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3904 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3905 const uint16_t* _frm_nxt = _frm;
3906 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3907 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3908 uint8_t* _to_nxt = _to;
3909 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3910 _Maxcode_, _Mode_);
3911 frm_nxt = frm + (_frm_nxt - _frm);
3912 to_nxt = to + (_to_nxt - _to);
3913 return r;
3914}
3915
3916__codecvt_utf8_utf16<char16_t>::result
3917__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3918 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3919 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3920{
3921 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3922 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3923 const uint8_t* _frm_nxt = _frm;
3924 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3925 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3926 uint16_t* _to_nxt = _to;
3927 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3928 _Maxcode_, _Mode_);
3929 frm_nxt = frm + (_frm_nxt - _frm);
3930 to_nxt = to + (_to_nxt - _to);
3931 return r;
3932}
3933
3934__codecvt_utf8_utf16<char16_t>::result
3935__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3936 extern_type* to, extern_type*, extern_type*& to_nxt) const
3937{
3938 to_nxt = to;
3939 return noconv;
3940}
3941
3942int
Howard Hinnantc9834542011-05-31 15:34:58 +00003943__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003944{
3945 return 0;
3946}
3947
3948bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003949__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003950{
3951 return false;
3952}
3953
3954int
3955__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3956 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3957{
3958 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3959 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3960 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3961}
3962
3963int
Howard Hinnantc9834542011-05-31 15:34:58 +00003964__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003965{
3966 if (_Mode_ & consume_header)
3967 return 7;
3968 return 4;
3969}
3970
3971// __codecvt_utf8_utf16<char32_t>
3972
3973__codecvt_utf8_utf16<char32_t>::result
3974__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3975 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3976 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3977{
3978 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3979 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3980 const uint32_t* _frm_nxt = _frm;
3981 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3982 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3983 uint8_t* _to_nxt = _to;
3984 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3985 _Maxcode_, _Mode_);
3986 frm_nxt = frm + (_frm_nxt - _frm);
3987 to_nxt = to + (_to_nxt - _to);
3988 return r;
3989}
3990
3991__codecvt_utf8_utf16<char32_t>::result
3992__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3993 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3994 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3995{
3996 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3997 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3998 const uint8_t* _frm_nxt = _frm;
3999 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4000 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4001 uint32_t* _to_nxt = _to;
4002 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4003 _Maxcode_, _Mode_);
4004 frm_nxt = frm + (_frm_nxt - _frm);
4005 to_nxt = to + (_to_nxt - _to);
4006 return r;
4007}
4008
4009__codecvt_utf8_utf16<char32_t>::result
4010__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4011 extern_type* to, extern_type*, extern_type*& to_nxt) const
4012{
4013 to_nxt = to;
4014 return noconv;
4015}
4016
4017int
Howard Hinnantc9834542011-05-31 15:34:58 +00004018__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004019{
4020 return 0;
4021}
4022
4023bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004024__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004025{
4026 return false;
4027}
4028
4029int
4030__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4031 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4032{
4033 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4034 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4035 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4036}
4037
4038int
Howard Hinnantc9834542011-05-31 15:34:58 +00004039__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004040{
4041 if (_Mode_ & consume_header)
4042 return 7;
4043 return 4;
4044}
4045
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004046// __narrow_to_utf8<16>
4047
4048__narrow_to_utf8<16>::~__narrow_to_utf8()
4049{
4050}
4051
4052// __narrow_to_utf8<32>
4053
4054__narrow_to_utf8<32>::~__narrow_to_utf8()
4055{
4056}
4057
4058// __widen_from_utf8<16>
4059
4060__widen_from_utf8<16>::~__widen_from_utf8()
4061{
4062}
4063
4064// __widen_from_utf8<32>
4065
4066__widen_from_utf8<32>::~__widen_from_utf8()
4067{
4068}
4069
4070// numpunct<char> && numpunct<wchar_t>
4071
4072locale::id numpunct< char >::id;
4073locale::id numpunct<wchar_t>::id;
4074
4075numpunct<char>::numpunct(size_t refs)
4076 : locale::facet(refs),
4077 __decimal_point_('.'),
4078 __thousands_sep_(',')
4079{
4080}
4081
4082numpunct<wchar_t>::numpunct(size_t refs)
4083 : locale::facet(refs),
4084 __decimal_point_(L'.'),
4085 __thousands_sep_(L',')
4086{
4087}
4088
4089numpunct<char>::~numpunct()
4090{
4091}
4092
4093numpunct<wchar_t>::~numpunct()
4094{
4095}
4096
4097 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4098wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4099
4100 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4101wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4102
4103string numpunct< char >::do_grouping() const {return __grouping_;}
4104string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4105
4106 string numpunct< char >::do_truename() const {return "true";}
4107wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4108
4109 string numpunct< char >::do_falsename() const {return "false";}
4110wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4111
4112// numpunct_byname<char>
4113
4114numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4115 : numpunct<char>(refs)
4116{
4117 __init(nm);
4118}
4119
4120numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4121 : numpunct<char>(refs)
4122{
4123 __init(nm.c_str());
4124}
4125
4126numpunct_byname<char>::~numpunct_byname()
4127{
4128}
4129
4130void
4131numpunct_byname<char>::__init(const char* nm)
4132{
4133 if (strcmp(nm, "C") != 0)
4134 {
Sean Huntf3907e62011-07-15 05:40:33 +00004135 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004136#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004137 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004138 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4139 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004140#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004141#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004142 lconv* lc = localeconv_l(loc.get());
4143#else
4144 lconv* lc = __localeconv_l(loc.get());
4145#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004146 if (*lc->decimal_point)
4147 __decimal_point_ = *lc->decimal_point;
4148 if (*lc->thousands_sep)
4149 __thousands_sep_ = *lc->thousands_sep;
4150 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004151 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004152 }
4153}
4154
4155// numpunct_byname<wchar_t>
4156
4157numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4158 : numpunct<wchar_t>(refs)
4159{
4160 __init(nm);
4161}
4162
4163numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4164 : numpunct<wchar_t>(refs)
4165{
4166 __init(nm.c_str());
4167}
4168
4169numpunct_byname<wchar_t>::~numpunct_byname()
4170{
4171}
4172
4173void
4174numpunct_byname<wchar_t>::__init(const char* nm)
4175{
4176 if (strcmp(nm, "C") != 0)
4177 {
Sean Huntf3907e62011-07-15 05:40:33 +00004178 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004179#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004180 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004181 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4182 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004183#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004184#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004185 lconv* lc = localeconv_l(loc.get());
4186#else
4187 lconv* lc = __localeconv_l(loc.get());
4188#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004189 if (*lc->decimal_point)
4190 __decimal_point_ = *lc->decimal_point;
4191 if (*lc->thousands_sep)
4192 __thousands_sep_ = *lc->thousands_sep;
4193 __grouping_ = lc->grouping;
4194 // locallization for truename and falsename is not available
4195 }
4196}
4197
4198// num_get helpers
4199
4200int
4201__num_get_base::__get_base(ios_base& iob)
4202{
4203 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4204 if (__basefield == ios_base::oct)
4205 return 8;
4206 else if (__basefield == ios_base::hex)
4207 return 16;
4208 else if (__basefield == 0)
4209 return 0;
4210 return 10;
4211}
4212
4213const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4214
4215void
4216__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4217 ios_base::iostate& __err)
4218{
4219 if (__grouping.size() != 0)
4220 {
4221 reverse(__g, __g_end);
4222 const char* __ig = __grouping.data();
4223 const char* __eg = __ig + __grouping.size();
4224 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4225 {
4226 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4227 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004228 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004229 {
4230 __err = ios_base::failbit;
4231 return;
4232 }
4233 }
4234 if (__eg - __ig > 1)
4235 ++__ig;
4236 }
4237 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4238 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004239 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004240 __err = ios_base::failbit;
4241 }
4242 }
4243}
4244
4245void
4246__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4247 ios_base::fmtflags __flags)
4248{
4249 if (__flags & ios_base::showpos)
4250 *__fmtp++ = '+';
4251 if (__flags & ios_base::showbase)
4252 *__fmtp++ = '#';
4253 while(*__len)
4254 *__fmtp++ = *__len++;
4255 if ((__flags & ios_base::basefield) == ios_base::oct)
4256 *__fmtp = 'o';
4257 else if ((__flags & ios_base::basefield) == ios_base::hex)
4258 {
4259 if (__flags & ios_base::uppercase)
4260 *__fmtp = 'X';
4261 else
4262 *__fmtp = 'x';
4263 }
4264 else if (__signd)
4265 *__fmtp = 'd';
4266 else
4267 *__fmtp = 'u';
4268}
4269
4270bool
4271__num_put_base::__format_float(char* __fmtp, const char* __len,
4272 ios_base::fmtflags __flags)
4273{
4274 bool specify_precision = true;
4275 if (__flags & ios_base::showpos)
4276 *__fmtp++ = '+';
4277 if (__flags & ios_base::showpoint)
4278 *__fmtp++ = '#';
4279 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4280 bool uppercase = __flags & ios_base::uppercase;
4281 if (floatfield == (ios_base::fixed | ios_base::scientific))
4282 specify_precision = false;
4283 else
4284 {
4285 *__fmtp++ = '.';
4286 *__fmtp++ = '*';
4287 }
4288 while(*__len)
4289 *__fmtp++ = *__len++;
4290 if (floatfield == ios_base::fixed)
4291 {
4292 if (uppercase)
4293 *__fmtp = 'F';
4294 else
4295 *__fmtp = 'f';
4296 }
4297 else if (floatfield == ios_base::scientific)
4298 {
4299 if (uppercase)
4300 *__fmtp = 'E';
4301 else
4302 *__fmtp = 'e';
4303 }
4304 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4305 {
4306 if (uppercase)
4307 *__fmtp = 'A';
4308 else
4309 *__fmtp = 'a';
4310 }
4311 else
4312 {
4313 if (uppercase)
4314 *__fmtp = 'G';
4315 else
4316 *__fmtp = 'g';
4317 }
4318 return specify_precision;
4319}
4320
4321char*
4322__num_put_base::__identify_padding(char* __nb, char* __ne,
4323 const ios_base& __iob)
4324{
4325 switch (__iob.flags() & ios_base::adjustfield)
4326 {
4327 case ios_base::internal:
4328 if (__nb[0] == '-' || __nb[0] == '+')
4329 return __nb+1;
4330 if (__ne - __nb >= 2 && __nb[0] == '0'
4331 && (__nb[1] == 'x' || __nb[1] == 'X'))
4332 return __nb+2;
4333 break;
4334 case ios_base::left:
4335 return __ne;
4336 case ios_base::right:
4337 default:
4338 break;
4339 }
4340 return __nb;
4341}
4342
4343// time_get
4344
4345static
4346string*
4347init_weeks()
4348{
4349 static string weeks[14];
4350 weeks[0] = "Sunday";
4351 weeks[1] = "Monday";
4352 weeks[2] = "Tuesday";
4353 weeks[3] = "Wednesday";
4354 weeks[4] = "Thursday";
4355 weeks[5] = "Friday";
4356 weeks[6] = "Saturday";
4357 weeks[7] = "Sun";
4358 weeks[8] = "Mon";
4359 weeks[9] = "Tue";
4360 weeks[10] = "Wed";
4361 weeks[11] = "Thu";
4362 weeks[12] = "Fri";
4363 weeks[13] = "Sat";
4364 return weeks;
4365}
4366
4367static
4368wstring*
4369init_wweeks()
4370{
4371 static wstring weeks[14];
4372 weeks[0] = L"Sunday";
4373 weeks[1] = L"Monday";
4374 weeks[2] = L"Tuesday";
4375 weeks[3] = L"Wednesday";
4376 weeks[4] = L"Thursday";
4377 weeks[5] = L"Friday";
4378 weeks[6] = L"Saturday";
4379 weeks[7] = L"Sun";
4380 weeks[8] = L"Mon";
4381 weeks[9] = L"Tue";
4382 weeks[10] = L"Wed";
4383 weeks[11] = L"Thu";
4384 weeks[12] = L"Fri";
4385 weeks[13] = L"Sat";
4386 return weeks;
4387}
4388
4389template <>
4390const string*
4391__time_get_c_storage<char>::__weeks() const
4392{
4393 static const string* weeks = init_weeks();
4394 return weeks;
4395}
4396
4397template <>
4398const wstring*
4399__time_get_c_storage<wchar_t>::__weeks() const
4400{
4401 static const wstring* weeks = init_wweeks();
4402 return weeks;
4403}
4404
4405static
4406string*
4407init_months()
4408{
4409 static string months[24];
4410 months[0] = "January";
4411 months[1] = "February";
4412 months[2] = "March";
4413 months[3] = "April";
4414 months[4] = "May";
4415 months[5] = "June";
4416 months[6] = "July";
4417 months[7] = "August";
4418 months[8] = "September";
4419 months[9] = "October";
4420 months[10] = "November";
4421 months[11] = "December";
4422 months[12] = "Jan";
4423 months[13] = "Feb";
4424 months[14] = "Mar";
4425 months[15] = "Apr";
4426 months[16] = "May";
4427 months[17] = "Jun";
4428 months[18] = "Jul";
4429 months[19] = "Aug";
4430 months[20] = "Sep";
4431 months[21] = "Oct";
4432 months[22] = "Nov";
4433 months[23] = "Dec";
4434 return months;
4435}
4436
4437static
4438wstring*
4439init_wmonths()
4440{
4441 static wstring months[24];
4442 months[0] = L"January";
4443 months[1] = L"February";
4444 months[2] = L"March";
4445 months[3] = L"April";
4446 months[4] = L"May";
4447 months[5] = L"June";
4448 months[6] = L"July";
4449 months[7] = L"August";
4450 months[8] = L"September";
4451 months[9] = L"October";
4452 months[10] = L"November";
4453 months[11] = L"December";
4454 months[12] = L"Jan";
4455 months[13] = L"Feb";
4456 months[14] = L"Mar";
4457 months[15] = L"Apr";
4458 months[16] = L"May";
4459 months[17] = L"Jun";
4460 months[18] = L"Jul";
4461 months[19] = L"Aug";
4462 months[20] = L"Sep";
4463 months[21] = L"Oct";
4464 months[22] = L"Nov";
4465 months[23] = L"Dec";
4466 return months;
4467}
4468
4469template <>
4470const string*
4471__time_get_c_storage<char>::__months() const
4472{
4473 static const string* months = init_months();
4474 return months;
4475}
4476
4477template <>
4478const wstring*
4479__time_get_c_storage<wchar_t>::__months() const
4480{
4481 static const wstring* months = init_wmonths();
4482 return months;
4483}
4484
4485static
4486string*
4487init_am_pm()
4488{
4489 static string am_pm[24];
4490 am_pm[0] = "AM";
4491 am_pm[1] = "PM";
4492 return am_pm;
4493}
4494
4495static
4496wstring*
4497init_wam_pm()
4498{
4499 static wstring am_pm[24];
4500 am_pm[0] = L"AM";
4501 am_pm[1] = L"PM";
4502 return am_pm;
4503}
4504
4505template <>
4506const string*
4507__time_get_c_storage<char>::__am_pm() const
4508{
4509 static const string* am_pm = init_am_pm();
4510 return am_pm;
4511}
4512
4513template <>
4514const wstring*
4515__time_get_c_storage<wchar_t>::__am_pm() const
4516{
4517 static const wstring* am_pm = init_wam_pm();
4518 return am_pm;
4519}
4520
4521template <>
4522const string&
4523__time_get_c_storage<char>::__x() const
4524{
4525 static string s("%m/%d/%y");
4526 return s;
4527}
4528
4529template <>
4530const wstring&
4531__time_get_c_storage<wchar_t>::__x() const
4532{
4533 static wstring s(L"%m/%d/%y");
4534 return s;
4535}
4536
4537template <>
4538const string&
4539__time_get_c_storage<char>::__X() const
4540{
4541 static string s("%H:%M:%S");
4542 return s;
4543}
4544
4545template <>
4546const wstring&
4547__time_get_c_storage<wchar_t>::__X() const
4548{
4549 static wstring s(L"%H:%M:%S");
4550 return s;
4551}
4552
4553template <>
4554const string&
4555__time_get_c_storage<char>::__c() const
4556{
4557 static string s("%a %b %d %H:%M:%S %Y");
4558 return s;
4559}
4560
4561template <>
4562const wstring&
4563__time_get_c_storage<wchar_t>::__c() const
4564{
4565 static wstring s(L"%a %b %d %H:%M:%S %Y");
4566 return s;
4567}
4568
4569template <>
4570const string&
4571__time_get_c_storage<char>::__r() const
4572{
4573 static string s("%I:%M:%S %p");
4574 return s;
4575}
4576
4577template <>
4578const wstring&
4579__time_get_c_storage<wchar_t>::__r() const
4580{
4581 static wstring s(L"%I:%M:%S %p");
4582 return s;
4583}
4584
4585// time_get_byname
4586
4587__time_get::__time_get(const char* nm)
4588 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4589{
Howard Hinnantd4444702010-08-11 17:04:31 +00004590#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004591 if (__loc_ == 0)
4592 throw runtime_error("time_get_byname"
4593 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004594#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004595}
4596
4597__time_get::__time_get(const string& nm)
4598 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4599{
Howard Hinnantd4444702010-08-11 17:04:31 +00004600#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004601 if (__loc_ == 0)
4602 throw runtime_error("time_get_byname"
4603 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004604#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004605}
4606
4607__time_get::~__time_get()
4608{
4609 freelocale(__loc_);
4610}
4611
Howard Hinnant335b1512012-02-20 16:51:43 +00004612#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant21772ec2012-12-28 18:15:01 +00004613#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant335b1512012-02-20 16:51:43 +00004614
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004615template <>
4616string
4617__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4618{
Howard Hinnant3074a052012-02-19 14:55:32 +00004619 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004620 t.tm_sec = 59;
4621 t.tm_min = 55;
4622 t.tm_hour = 23;
4623 t.tm_mday = 31;
4624 t.tm_mon = 11;
4625 t.tm_year = 161;
4626 t.tm_wday = 6;
4627 t.tm_yday = 364;
4628 t.tm_isdst = -1;
4629 char buf[100];
4630 char f[3] = {0};
4631 f[0] = '%';
4632 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004633 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004634 char* bb = buf;
4635 char* be = buf + n;
4636 string result;
4637 while (bb != be)
4638 {
4639 if (ct.is(ctype_base::space, *bb))
4640 {
4641 result.push_back(' ');
4642 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4643 ;
4644 continue;
4645 }
4646 char* w = bb;
4647 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004648 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004649 ct, err, false)
4650 - this->__weeks_;
4651 if (i < 14)
4652 {
4653 result.push_back('%');
4654 if (i < 7)
4655 result.push_back('A');
4656 else
4657 result.push_back('a');
4658 bb = w;
4659 continue;
4660 }
4661 w = bb;
4662 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4663 ct, err, false)
4664 - this->__months_;
4665 if (i < 24)
4666 {
4667 result.push_back('%');
4668 if (i < 12)
4669 result.push_back('B');
4670 else
4671 result.push_back('b');
4672 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4673 result.back() = 'm';
4674 bb = w;
4675 continue;
4676 }
4677 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4678 {
4679 w = bb;
4680 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4681 ct, err, false) - this->__am_pm_;
4682 if (i < 2)
4683 {
4684 result.push_back('%');
4685 result.push_back('p');
4686 bb = w;
4687 continue;
4688 }
4689 }
4690 w = bb;
4691 if (ct.is(ctype_base::digit, *bb))
4692 {
4693 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4694 {
4695 case 6:
4696 result.push_back('%');
4697 result.push_back('w');
4698 break;
4699 case 7:
4700 result.push_back('%');
4701 result.push_back('u');
4702 break;
4703 case 11:
4704 result.push_back('%');
4705 result.push_back('I');
4706 break;
4707 case 12:
4708 result.push_back('%');
4709 result.push_back('m');
4710 break;
4711 case 23:
4712 result.push_back('%');
4713 result.push_back('H');
4714 break;
4715 case 31:
4716 result.push_back('%');
4717 result.push_back('d');
4718 break;
4719 case 55:
4720 result.push_back('%');
4721 result.push_back('M');
4722 break;
4723 case 59:
4724 result.push_back('%');
4725 result.push_back('S');
4726 break;
4727 case 61:
4728 result.push_back('%');
4729 result.push_back('y');
4730 break;
4731 case 364:
4732 result.push_back('%');
4733 result.push_back('j');
4734 break;
4735 case 2061:
4736 result.push_back('%');
4737 result.push_back('Y');
4738 break;
4739 default:
4740 for (; w != bb; ++w)
4741 result.push_back(*w);
4742 break;
4743 }
4744 continue;
4745 }
4746 if (*bb == '%')
4747 {
4748 result.push_back('%');
4749 result.push_back('%');
4750 ++bb;
4751 continue;
4752 }
4753 result.push_back(*bb);
4754 ++bb;
4755 }
4756 return result;
4757}
4758
Howard Hinnantec3773c2011-12-01 20:21:04 +00004759#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004760
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004761template <>
4762wstring
4763__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4764{
Howard Hinnant3074a052012-02-19 14:55:32 +00004765 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004766 t.tm_sec = 59;
4767 t.tm_min = 55;
4768 t.tm_hour = 23;
4769 t.tm_mday = 31;
4770 t.tm_mon = 11;
4771 t.tm_year = 161;
4772 t.tm_wday = 6;
4773 t.tm_yday = 364;
4774 t.tm_isdst = -1;
4775 char buf[100];
4776 char f[3] = {0};
4777 f[0] = '%';
4778 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004779 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004780 wchar_t wbuf[100];
4781 wchar_t* wbb = wbuf;
4782 mbstate_t mb = {0};
4783 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004784#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004785 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004786#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004787 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004788#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004789 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004790 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004791 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004792 wstring result;
4793 while (wbb != wbe)
4794 {
4795 if (ct.is(ctype_base::space, *wbb))
4796 {
4797 result.push_back(L' ');
4798 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4799 ;
4800 continue;
4801 }
4802 wchar_t* w = wbb;
4803 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004804 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004805 ct, err, false)
4806 - this->__weeks_;
4807 if (i < 14)
4808 {
4809 result.push_back(L'%');
4810 if (i < 7)
4811 result.push_back(L'A');
4812 else
4813 result.push_back(L'a');
4814 wbb = w;
4815 continue;
4816 }
4817 w = wbb;
4818 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4819 ct, err, false)
4820 - this->__months_;
4821 if (i < 24)
4822 {
4823 result.push_back(L'%');
4824 if (i < 12)
4825 result.push_back(L'B');
4826 else
4827 result.push_back(L'b');
4828 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4829 result.back() = L'm';
4830 wbb = w;
4831 continue;
4832 }
4833 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4834 {
4835 w = wbb;
4836 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4837 ct, err, false) - this->__am_pm_;
4838 if (i < 2)
4839 {
4840 result.push_back(L'%');
4841 result.push_back(L'p');
4842 wbb = w;
4843 continue;
4844 }
4845 }
4846 w = wbb;
4847 if (ct.is(ctype_base::digit, *wbb))
4848 {
4849 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4850 {
4851 case 6:
4852 result.push_back(L'%');
4853 result.push_back(L'w');
4854 break;
4855 case 7:
4856 result.push_back(L'%');
4857 result.push_back(L'u');
4858 break;
4859 case 11:
4860 result.push_back(L'%');
4861 result.push_back(L'I');
4862 break;
4863 case 12:
4864 result.push_back(L'%');
4865 result.push_back(L'm');
4866 break;
4867 case 23:
4868 result.push_back(L'%');
4869 result.push_back(L'H');
4870 break;
4871 case 31:
4872 result.push_back(L'%');
4873 result.push_back(L'd');
4874 break;
4875 case 55:
4876 result.push_back(L'%');
4877 result.push_back(L'M');
4878 break;
4879 case 59:
4880 result.push_back(L'%');
4881 result.push_back(L'S');
4882 break;
4883 case 61:
4884 result.push_back(L'%');
4885 result.push_back(L'y');
4886 break;
4887 case 364:
4888 result.push_back(L'%');
4889 result.push_back(L'j');
4890 break;
4891 case 2061:
4892 result.push_back(L'%');
4893 result.push_back(L'Y');
4894 break;
4895 default:
4896 for (; w != wbb; ++w)
4897 result.push_back(*w);
4898 break;
4899 }
4900 continue;
4901 }
4902 if (ct.narrow(*wbb, 0) == '%')
4903 {
4904 result.push_back(L'%');
4905 result.push_back(L'%');
4906 ++wbb;
4907 continue;
4908 }
4909 result.push_back(*wbb);
4910 ++wbb;
4911 }
4912 return result;
4913}
4914
4915template <>
4916void
4917__time_get_storage<char>::init(const ctype<char>& ct)
4918{
Howard Hinnantcd992362012-08-02 18:44:17 +00004919 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004920 char buf[100];
4921 // __weeks_
4922 for (int i = 0; i < 7; ++i)
4923 {
4924 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004925 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004926 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004927 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004928 __weeks_[i+7] = buf;
4929 }
4930 // __months_
4931 for (int i = 0; i < 12; ++i)
4932 {
4933 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004934 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004935 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004936 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004937 __months_[i+12] = buf;
4938 }
4939 // __am_pm_
4940 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004941 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004942 __am_pm_[0] = buf;
4943 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004944 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004945 __am_pm_[1] = buf;
4946 __c_ = __analyze('c', ct);
4947 __r_ = __analyze('r', ct);
4948 __x_ = __analyze('x', ct);
4949 __X_ = __analyze('X', ct);
4950}
4951
4952template <>
4953void
4954__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4955{
4956 tm t = {0};
4957 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004958 wchar_t wbuf[100];
4959 wchar_t* wbe;
4960 mbstate_t mb = {0};
4961 // __weeks_
4962 for (int i = 0; i < 7; ++i)
4963 {
4964 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004965 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004966 mb = mbstate_t();
4967 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004968#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004969 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004970#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004971 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004972#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004973 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004974 __throw_runtime_error("locale not supported");
4975 wbe = wbuf + j;
4976 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004977 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004978 mb = mbstate_t();
4979 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004980#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004981 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004982#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004983 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004984#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004985 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004986 __throw_runtime_error("locale not supported");
4987 wbe = wbuf + j;
4988 __weeks_[i+7].assign(wbuf, wbe);
4989 }
4990 // __months_
4991 for (int i = 0; i < 12; ++i)
4992 {
4993 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004994 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004995 mb = mbstate_t();
4996 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004997#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004998 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004999#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005000 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005001#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005002 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005003 __throw_runtime_error("locale not supported");
5004 wbe = wbuf + j;
5005 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005006 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005007 mb = mbstate_t();
5008 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005009#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005010 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005011#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005012 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005013#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005014 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005015 __throw_runtime_error("locale not supported");
5016 wbe = wbuf + j;
5017 __months_[i+12].assign(wbuf, wbe);
5018 }
5019 // __am_pm_
5020 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005021 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005022 mb = mbstate_t();
5023 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005024#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005025 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005026#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005027 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005028#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005029 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005030 __throw_runtime_error("locale not supported");
5031 wbe = wbuf + j;
5032 __am_pm_[0].assign(wbuf, wbe);
5033 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005034 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005035 mb = mbstate_t();
5036 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005037#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005038 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005039#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005040 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005041#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005042 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005043 __throw_runtime_error("locale not supported");
5044 wbe = wbuf + j;
5045 __am_pm_[1].assign(wbuf, wbe);
5046 __c_ = __analyze('c', ct);
5047 __r_ = __analyze('r', ct);
5048 __x_ = __analyze('x', ct);
5049 __X_ = __analyze('X', ct);
5050}
5051
5052template <class CharT>
5053struct _LIBCPP_HIDDEN __time_get_temp
5054 : public ctype_byname<CharT>
5055{
5056 explicit __time_get_temp(const char* nm)
5057 : ctype_byname<CharT>(nm, 1) {}
5058 explicit __time_get_temp(const string& nm)
5059 : ctype_byname<CharT>(nm, 1) {}
5060};
5061
5062template <>
5063__time_get_storage<char>::__time_get_storage(const char* __nm)
5064 : __time_get(__nm)
5065{
5066 const __time_get_temp<char> ct(__nm);
5067 init(ct);
5068}
5069
5070template <>
5071__time_get_storage<char>::__time_get_storage(const string& __nm)
5072 : __time_get(__nm)
5073{
5074 const __time_get_temp<char> ct(__nm);
5075 init(ct);
5076}
5077
5078template <>
5079__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5080 : __time_get(__nm)
5081{
5082 const __time_get_temp<wchar_t> ct(__nm);
5083 init(ct);
5084}
5085
5086template <>
5087__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5088 : __time_get(__nm)
5089{
5090 const __time_get_temp<wchar_t> ct(__nm);
5091 init(ct);
5092}
5093
5094template <>
5095time_base::dateorder
5096__time_get_storage<char>::__do_date_order() const
5097{
5098 unsigned i;
5099 for (i = 0; i < __x_.size(); ++i)
5100 if (__x_[i] == '%')
5101 break;
5102 ++i;
5103 switch (__x_[i])
5104 {
5105 case 'y':
5106 case 'Y':
5107 for (++i; i < __x_.size(); ++i)
5108 if (__x_[i] == '%')
5109 break;
5110 if (i == __x_.size())
5111 break;
5112 ++i;
5113 switch (__x_[i])
5114 {
5115 case 'm':
5116 for (++i; i < __x_.size(); ++i)
5117 if (__x_[i] == '%')
5118 break;
5119 if (i == __x_.size())
5120 break;
5121 ++i;
5122 if (__x_[i] == 'd')
5123 return time_base::ymd;
5124 break;
5125 case 'd':
5126 for (++i; i < __x_.size(); ++i)
5127 if (__x_[i] == '%')
5128 break;
5129 if (i == __x_.size())
5130 break;
5131 ++i;
5132 if (__x_[i] == 'm')
5133 return time_base::ydm;
5134 break;
5135 }
5136 break;
5137 case 'm':
5138 for (++i; i < __x_.size(); ++i)
5139 if (__x_[i] == '%')
5140 break;
5141 if (i == __x_.size())
5142 break;
5143 ++i;
5144 if (__x_[i] == 'd')
5145 {
5146 for (++i; i < __x_.size(); ++i)
5147 if (__x_[i] == '%')
5148 break;
5149 if (i == __x_.size())
5150 break;
5151 ++i;
5152 if (__x_[i] == 'y' || __x_[i] == 'Y')
5153 return time_base::mdy;
5154 break;
5155 }
5156 break;
5157 case 'd':
5158 for (++i; i < __x_.size(); ++i)
5159 if (__x_[i] == '%')
5160 break;
5161 if (i == __x_.size())
5162 break;
5163 ++i;
5164 if (__x_[i] == 'm')
5165 {
5166 for (++i; i < __x_.size(); ++i)
5167 if (__x_[i] == '%')
5168 break;
5169 if (i == __x_.size())
5170 break;
5171 ++i;
5172 if (__x_[i] == 'y' || __x_[i] == 'Y')
5173 return time_base::dmy;
5174 break;
5175 }
5176 break;
5177 }
5178 return time_base::no_order;
5179}
5180
5181template <>
5182time_base::dateorder
5183__time_get_storage<wchar_t>::__do_date_order() const
5184{
5185 unsigned i;
5186 for (i = 0; i < __x_.size(); ++i)
5187 if (__x_[i] == L'%')
5188 break;
5189 ++i;
5190 switch (__x_[i])
5191 {
5192 case L'y':
5193 case L'Y':
5194 for (++i; i < __x_.size(); ++i)
5195 if (__x_[i] == L'%')
5196 break;
5197 if (i == __x_.size())
5198 break;
5199 ++i;
5200 switch (__x_[i])
5201 {
5202 case L'm':
5203 for (++i; i < __x_.size(); ++i)
5204 if (__x_[i] == L'%')
5205 break;
5206 if (i == __x_.size())
5207 break;
5208 ++i;
5209 if (__x_[i] == L'd')
5210 return time_base::ymd;
5211 break;
5212 case L'd':
5213 for (++i; i < __x_.size(); ++i)
5214 if (__x_[i] == L'%')
5215 break;
5216 if (i == __x_.size())
5217 break;
5218 ++i;
5219 if (__x_[i] == L'm')
5220 return time_base::ydm;
5221 break;
5222 }
5223 break;
5224 case L'm':
5225 for (++i; i < __x_.size(); ++i)
5226 if (__x_[i] == L'%')
5227 break;
5228 if (i == __x_.size())
5229 break;
5230 ++i;
5231 if (__x_[i] == L'd')
5232 {
5233 for (++i; i < __x_.size(); ++i)
5234 if (__x_[i] == L'%')
5235 break;
5236 if (i == __x_.size())
5237 break;
5238 ++i;
5239 if (__x_[i] == L'y' || __x_[i] == L'Y')
5240 return time_base::mdy;
5241 break;
5242 }
5243 break;
5244 case L'd':
5245 for (++i; i < __x_.size(); ++i)
5246 if (__x_[i] == L'%')
5247 break;
5248 if (i == __x_.size())
5249 break;
5250 ++i;
5251 if (__x_[i] == L'm')
5252 {
5253 for (++i; i < __x_.size(); ++i)
5254 if (__x_[i] == L'%')
5255 break;
5256 if (i == __x_.size())
5257 break;
5258 ++i;
5259 if (__x_[i] == L'y' || __x_[i] == L'Y')
5260 return time_base::dmy;
5261 break;
5262 }
5263 break;
5264 }
5265 return time_base::no_order;
5266}
5267
5268// time_put
5269
5270__time_put::__time_put(const char* nm)
5271 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5272{
Howard Hinnantd4444702010-08-11 17:04:31 +00005273#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005274 if (__loc_ == 0)
5275 throw runtime_error("time_put_byname"
5276 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005277#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005278}
5279
5280__time_put::__time_put(const string& nm)
5281 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5282{
Howard Hinnantd4444702010-08-11 17:04:31 +00005283#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005284 if (__loc_ == 0)
5285 throw runtime_error("time_put_byname"
5286 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005287#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005288}
5289
5290__time_put::~__time_put()
5291{
5292 if (__loc_)
5293 freelocale(__loc_);
5294}
5295
5296void
5297__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5298 char __fmt, char __mod) const
5299{
5300 char fmt[] = {'%', __fmt, __mod, 0};
5301 if (__mod != 0)
5302 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005303 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005304 __ne = __nb + n;
5305}
5306
5307void
5308__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5309 char __fmt, char __mod) const
5310{
5311 char __nar[100];
5312 char* __ne = __nar + 100;
5313 __do_put(__nar, __ne, __tm, __fmt, __mod);
5314 mbstate_t mb = {0};
5315 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005316#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005317 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005318#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005319 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005320#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005321 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005322 __throw_runtime_error("locale not supported");
5323 __we = __wb + j;
5324}
5325
5326// moneypunct_byname
5327
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005328template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005329static
5330void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005331__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5332 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5333 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005334{
5335 const char sign = static_cast<char>(money_base::sign);
5336 const char space = static_cast<char>(money_base::space);
5337 const char none = static_cast<char>(money_base::none);
5338 const char symbol = static_cast<char>(money_base::symbol);
5339 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005340 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5341
5342 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5343 // function'. "Space between sign and symbol or value" means that
5344 // if the sign is adjacent to the symbol, there's a space between
5345 // them, and otherwise there's a space between the sign and value.
5346 //
5347 // C11's localeconv specifies that the fourth character of an
5348 // international curr_symbol is used to separate the sign and
5349 // value when sep_by_space says to do so. C++ can't represent
5350 // that, so we just use a space. When sep_by_space says to
5351 // separate the symbol and value-or-sign with a space, we rearrange the
5352 // curr_symbol to put its spacing character on the correct side of
5353 // the symbol.
5354 //
5355 // We also need to avoid adding an extra space between the sign
5356 // and value when the currency symbol is suppressed (by not
5357 // setting showbase). We match glibc's strfmon by interpreting
5358 // sep_by_space==1 as "omit the space when the currency symbol is
5359 // absent".
5360 //
5361 // Users who want to get this right should use ICU instead.
5362
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005363 switch (cs_precedes)
5364 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005365 case 0: // value before curr_symbol
5366 if (symbol_contains_sep) {
5367 // Move the separator to before the symbol, to place it
5368 // between the value and symbol.
5369 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5370 __curr_symbol_.end());
5371 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005372 switch (sign_posn)
5373 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005374 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005375 pat.field[0] = sign;
5376 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005377 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005378 pat.field[3] = symbol;
5379 switch (sep_by_space)
5380 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005381 case 0: // No space separates the currency symbol and value.
5382 // This case may have changed between C99 and C11;
5383 // assume the currency symbol matches the intention.
5384 case 2: // Space between sign and currency or value.
5385 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005386 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005387 case 1: // Space between currency-and-sign or currency and value.
5388 if (!symbol_contains_sep) {
5389 // We insert the space into the symbol instead of
5390 // setting pat.field[2]=space so that when
5391 // showbase is not set, the space goes away too.
5392 __curr_symbol_.insert(0, 1, space_char);
5393 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005394 return;
5395 default:
5396 break;
5397 }
5398 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005399 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005400 pat.field[0] = sign;
5401 pat.field[3] = symbol;
5402 switch (sep_by_space)
5403 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005404 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005405 pat.field[1] = value;
5406 pat.field[2] = none;
5407 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005408 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005409 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005410 pat.field[2] = none;
5411 if (!symbol_contains_sep) {
5412 // We insert the space into the symbol instead of
5413 // setting pat.field[2]=space so that when
5414 // showbase is not set, the space goes away too.
5415 __curr_symbol_.insert(0, 1, space_char);
5416 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005417 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005418 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005419 pat.field[1] = space;
5420 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005421 if (symbol_contains_sep) {
5422 // Remove the separator from the symbol, since it
5423 // has already appeared after the sign.
5424 __curr_symbol_.erase(__curr_symbol_.begin());
5425 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005426 return;
5427 default:
5428 break;
5429 }
5430 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005431 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005432 pat.field[0] = value;
5433 pat.field[3] = sign;
5434 switch (sep_by_space)
5435 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005436 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005437 pat.field[1] = none;
5438 pat.field[2] = symbol;
5439 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005440 case 1: // Space between currency-and-sign or currency and value.
5441 if (!symbol_contains_sep) {
5442 // We insert the space into the symbol instead of
5443 // setting pat.field[1]=space so that when
5444 // showbase is not set, the space goes away too.
5445 __curr_symbol_.insert(0, 1, space_char);
5446 }
5447 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005448 pat.field[2] = symbol;
5449 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005450 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005451 pat.field[1] = symbol;
5452 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005453 if (symbol_contains_sep) {
5454 // Remove the separator from the symbol, since it
5455 // should not be removed if showbase is absent.
5456 __curr_symbol_.erase(__curr_symbol_.begin());
5457 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005458 return;
5459 default:
5460 break;
5461 }
5462 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005463 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005464 pat.field[0] = value;
5465 pat.field[3] = symbol;
5466 switch (sep_by_space)
5467 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005468 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005469 pat.field[1] = none;
5470 pat.field[2] = sign;
5471 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005472 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005473 pat.field[1] = space;
5474 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005475 if (symbol_contains_sep) {
5476 // Remove the separator from the symbol, since it
5477 // has already appeared before the sign.
5478 __curr_symbol_.erase(__curr_symbol_.begin());
5479 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005480 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005481 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005482 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005483 pat.field[2] = none;
5484 if (!symbol_contains_sep) {
5485 // We insert the space into the symbol instead of
5486 // setting pat.field[2]=space so that when
5487 // showbase is not set, the space goes away too.
5488 __curr_symbol_.insert(0, 1, space_char);
5489 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005490 return;
5491 default:
5492 break;
5493 }
5494 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005495 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005496 pat.field[0] = value;
5497 pat.field[3] = sign;
5498 switch (sep_by_space)
5499 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005500 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005501 pat.field[1] = none;
5502 pat.field[2] = symbol;
5503 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005504 case 1: // Space between currency-and-sign or currency and value.
5505 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005506 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005507 if (!symbol_contains_sep) {
5508 // We insert the space into the symbol instead of
5509 // setting pat.field[1]=space so that when
5510 // showbase is not set, the space goes away too.
5511 __curr_symbol_.insert(0, 1, space_char);
5512 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005513 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005514 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005515 pat.field[1] = symbol;
5516 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005517 if (symbol_contains_sep) {
5518 // Remove the separator from the symbol, since it
5519 // should not disappear when showbase is absent.
5520 __curr_symbol_.erase(__curr_symbol_.begin());
5521 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005522 return;
5523 default:
5524 break;
5525 }
5526 break;
5527 default:
5528 break;
5529 }
5530 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005531 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005532 switch (sign_posn)
5533 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005534 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005535 pat.field[0] = sign;
5536 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005537 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005538 pat.field[3] = value;
5539 switch (sep_by_space)
5540 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005541 case 0: // No space separates the currency symbol and value.
5542 // This case may have changed between C99 and C11;
5543 // assume the currency symbol matches the intention.
5544 case 2: // Space between sign and currency or value.
5545 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005546 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005547 case 1: // Space between currency-and-sign or currency and value.
5548 if (!symbol_contains_sep) {
5549 // We insert the space into the symbol instead of
5550 // setting pat.field[2]=space so that when
5551 // showbase is not set, the space goes away too.
5552 __curr_symbol_.insert(0, 1, space_char);
5553 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005554 return;
5555 default:
5556 break;
5557 }
5558 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005559 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005560 pat.field[0] = sign;
5561 pat.field[3] = value;
5562 switch (sep_by_space)
5563 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005564 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005565 pat.field[1] = symbol;
5566 pat.field[2] = none;
5567 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005568 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005569 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005570 pat.field[2] = none;
5571 if (!symbol_contains_sep) {
5572 // We insert the space into the symbol instead of
5573 // setting pat.field[2]=space so that when
5574 // showbase is not set, the space goes away too.
5575 __curr_symbol_.push_back(space_char);
5576 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005577 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005578 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005579 pat.field[1] = space;
5580 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005581 if (symbol_contains_sep) {
5582 // Remove the separator from the symbol, since it
5583 // has already appeared after the sign.
5584 __curr_symbol_.pop_back();
5585 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005586 return;
5587 default:
5588 break;
5589 }
5590 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005591 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005592 pat.field[0] = symbol;
5593 pat.field[3] = sign;
5594 switch (sep_by_space)
5595 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005596 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005597 pat.field[1] = none;
5598 pat.field[2] = value;
5599 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005600 case 1: // Space between currency-and-sign or currency and value.
5601 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005602 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005603 if (!symbol_contains_sep) {
5604 // We insert the space into the symbol instead of
5605 // setting pat.field[1]=space so that when
5606 // showbase is not set, the space goes away too.
5607 __curr_symbol_.push_back(space_char);
5608 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005609 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005610 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005611 pat.field[1] = value;
5612 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005613 if (symbol_contains_sep) {
5614 // Remove the separator from the symbol, since it
5615 // will appear before the sign.
5616 __curr_symbol_.pop_back();
5617 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005618 return;
5619 default:
5620 break;
5621 }
5622 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005623 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005624 pat.field[0] = sign;
5625 pat.field[3] = value;
5626 switch (sep_by_space)
5627 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005628 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005629 pat.field[1] = symbol;
5630 pat.field[2] = none;
5631 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005632 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005633 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005634 pat.field[2] = none;
5635 if (!symbol_contains_sep) {
5636 // We insert the space into the symbol instead of
5637 // setting pat.field[2]=space so that when
5638 // showbase is not set, the space goes away too.
5639 __curr_symbol_.push_back(space_char);
5640 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005641 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005642 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005643 pat.field[1] = space;
5644 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005645 if (symbol_contains_sep) {
5646 // Remove the separator from the symbol, since it
5647 // has already appeared after the sign.
5648 __curr_symbol_.pop_back();
5649 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005650 return;
5651 default:
5652 break;
5653 }
5654 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005655 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005656 pat.field[0] = symbol;
5657 pat.field[3] = value;
5658 switch (sep_by_space)
5659 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005660 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005661 pat.field[1] = sign;
5662 pat.field[2] = none;
5663 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005664 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005665 pat.field[1] = sign;
5666 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005667 if (symbol_contains_sep) {
5668 // Remove the separator from the symbol, since it
5669 // should not disappear when showbase is absent.
5670 __curr_symbol_.pop_back();
5671 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005672 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005673 case 2: // Space between sign and currency or value.
5674 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005675 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005676 if (!symbol_contains_sep) {
5677 // We insert the space into the symbol instead of
5678 // setting pat.field[1]=space so that when
5679 // showbase is not set, the space goes away too.
5680 __curr_symbol_.push_back(space_char);
5681 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005682 return;
5683 default:
5684 break;
5685 }
5686 break;
5687 default:
5688 break;
5689 }
5690 break;
5691 default:
5692 break;
5693 }
5694 pat.field[0] = symbol;
5695 pat.field[1] = sign;
5696 pat.field[2] = none;
5697 pat.field[3] = value;
5698}
5699
5700template<>
5701void
5702moneypunct_byname<char, false>::init(const char* nm)
5703{
5704 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005705 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005706#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005707 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005708 throw runtime_error("moneypunct_byname"
5709 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005710#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005711#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005712 lconv* lc = localeconv_l(loc.get());
5713#else
5714 lconv* lc = __localeconv_l(loc.get());
5715#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005716 if (*lc->mon_decimal_point)
5717 __decimal_point_ = *lc->mon_decimal_point;
5718 else
5719 __decimal_point_ = base::do_decimal_point();
5720 if (*lc->mon_thousands_sep)
5721 __thousands_sep_ = *lc->mon_thousands_sep;
5722 else
5723 __thousands_sep_ = base::do_thousands_sep();
5724 __grouping_ = lc->mon_grouping;
5725 __curr_symbol_ = lc->currency_symbol;
5726 if (lc->frac_digits != CHAR_MAX)
5727 __frac_digits_ = lc->frac_digits;
5728 else
5729 __frac_digits_ = base::do_frac_digits();
5730 if (lc->p_sign_posn == 0)
5731 __positive_sign_ = "()";
5732 else
5733 __positive_sign_ = lc->positive_sign;
5734 if (lc->n_sign_posn == 0)
5735 __negative_sign_ = "()";
5736 else
5737 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005738 // Assume the positive and negative formats will want spaces in
5739 // the same places in curr_symbol since there's no way to
5740 // represent anything else.
5741 string_type __dummy_curr_symbol = __curr_symbol_;
5742 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5743 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5744 __init_pat(__neg_format_, __curr_symbol_, false,
5745 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005746}
5747
5748template<>
5749void
5750moneypunct_byname<char, true>::init(const char* nm)
5751{
5752 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005753 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005754#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005755 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005756 throw runtime_error("moneypunct_byname"
5757 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005758#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005759#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005760 lconv* lc = localeconv_l(loc.get());
5761#else
5762 lconv* lc = __localeconv_l(loc.get());
5763#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005764 if (*lc->mon_decimal_point)
5765 __decimal_point_ = *lc->mon_decimal_point;
5766 else
5767 __decimal_point_ = base::do_decimal_point();
5768 if (*lc->mon_thousands_sep)
5769 __thousands_sep_ = *lc->mon_thousands_sep;
5770 else
5771 __thousands_sep_ = base::do_thousands_sep();
5772 __grouping_ = lc->mon_grouping;
5773 __curr_symbol_ = lc->int_curr_symbol;
5774 if (lc->int_frac_digits != CHAR_MAX)
5775 __frac_digits_ = lc->int_frac_digits;
5776 else
5777 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005778#if _WIN32
5779 if (lc->p_sign_posn == 0)
5780#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005781 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005782#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005783 __positive_sign_ = "()";
5784 else
5785 __positive_sign_ = lc->positive_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005786#if _WIN32
5787 if(lc->n_sign_posn == 0)
5788#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005789 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005790#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005791 __negative_sign_ = "()";
5792 else
5793 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005794 // Assume the positive and negative formats will want spaces in
5795 // the same places in curr_symbol since there's no way to
5796 // represent anything else.
5797 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005798#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005799 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5800 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5801 __init_pat(__neg_format_, __curr_symbol_, true,
5802 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005803#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005804 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5805 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5806 lc->int_p_sign_posn, ' ');
5807 __init_pat(__neg_format_, __curr_symbol_, true,
5808 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5809 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005810#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005811}
5812
5813template<>
5814void
5815moneypunct_byname<wchar_t, false>::init(const char* nm)
5816{
5817 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005818 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005819#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005820 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005821 throw runtime_error("moneypunct_byname"
5822 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005823#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005824#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005825 lconv* lc = localeconv_l(loc.get());
5826#else
5827 lconv* lc = __localeconv_l(loc.get());
5828#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005829 if (*lc->mon_decimal_point)
5830 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5831 else
5832 __decimal_point_ = base::do_decimal_point();
5833 if (*lc->mon_thousands_sep)
5834 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5835 else
5836 __thousands_sep_ = base::do_thousands_sep();
5837 __grouping_ = lc->mon_grouping;
5838 wchar_t wbuf[100];
5839 mbstate_t mb = {0};
5840 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005841#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005842 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005843#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005844 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005845#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005846 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005847 __throw_runtime_error("locale not supported");
5848 wchar_t* wbe = wbuf + j;
5849 __curr_symbol_.assign(wbuf, wbe);
5850 if (lc->frac_digits != CHAR_MAX)
5851 __frac_digits_ = lc->frac_digits;
5852 else
5853 __frac_digits_ = base::do_frac_digits();
5854 if (lc->p_sign_posn == 0)
5855 __positive_sign_ = L"()";
5856 else
5857 {
5858 mb = mbstate_t();
5859 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005860#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005861 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005862#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005863 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005864#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005865 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005866 __throw_runtime_error("locale not supported");
5867 wbe = wbuf + j;
5868 __positive_sign_.assign(wbuf, wbe);
5869 }
5870 if (lc->n_sign_posn == 0)
5871 __negative_sign_ = L"()";
5872 else
5873 {
5874 mb = mbstate_t();
5875 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005876#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005877 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005878#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005879 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005880#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005881 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005882 __throw_runtime_error("locale not supported");
5883 wbe = wbuf + j;
5884 __negative_sign_.assign(wbuf, wbe);
5885 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005886 // Assume the positive and negative formats will want spaces in
5887 // the same places in curr_symbol since there's no way to
5888 // represent anything else.
5889 string_type __dummy_curr_symbol = __curr_symbol_;
5890 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5891 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5892 __init_pat(__neg_format_, __curr_symbol_, false,
5893 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005894}
5895
5896template<>
5897void
5898moneypunct_byname<wchar_t, true>::init(const char* nm)
5899{
5900 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005901 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005902#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005903 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005904 throw runtime_error("moneypunct_byname"
5905 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005906#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005907#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005908 lconv* lc = localeconv_l(loc.get());
5909#else
5910 lconv* lc = __localeconv_l(loc.get());
5911#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005912 if (*lc->mon_decimal_point)
5913 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5914 else
5915 __decimal_point_ = base::do_decimal_point();
5916 if (*lc->mon_thousands_sep)
5917 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5918 else
5919 __thousands_sep_ = base::do_thousands_sep();
5920 __grouping_ = lc->mon_grouping;
5921 wchar_t wbuf[100];
5922 mbstate_t mb = {0};
5923 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005924#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005925 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005926#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005927 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005928#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005929 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005930 __throw_runtime_error("locale not supported");
5931 wchar_t* wbe = wbuf + j;
5932 __curr_symbol_.assign(wbuf, wbe);
5933 if (lc->int_frac_digits != CHAR_MAX)
5934 __frac_digits_ = lc->int_frac_digits;
5935 else
5936 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005937#if _WIN32
5938 if (lc->p_sign_posn == 0)
5939#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005940 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005941#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005942 __positive_sign_ = L"()";
5943 else
5944 {
5945 mb = mbstate_t();
5946 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005947#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005948 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005949#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005950 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005951#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005952 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005953 __throw_runtime_error("locale not supported");
5954 wbe = wbuf + j;
5955 __positive_sign_.assign(wbuf, wbe);
5956 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005957#if _WIN32
5958 if (lc->n_sign_posn == 0)
5959#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005960 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005961#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005962 __negative_sign_ = L"()";
5963 else
5964 {
5965 mb = mbstate_t();
5966 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005967#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005968 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005969#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005970 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005971#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005972 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005973 __throw_runtime_error("locale not supported");
5974 wbe = wbuf + j;
5975 __negative_sign_.assign(wbuf, wbe);
5976 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005977 // Assume the positive and negative formats will want spaces in
5978 // the same places in curr_symbol since there's no way to
5979 // represent anything else.
5980 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005981#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005982 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5983 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5984 __init_pat(__neg_format_, __curr_symbol_, true,
5985 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005986#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005987 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5988 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5989 lc->int_p_sign_posn, L' ');
5990 __init_pat(__neg_format_, __curr_symbol_, true,
5991 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5992 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005993#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005994}
5995
5996void __do_nothing(void*) {}
5997
5998void __throw_runtime_error(const char* msg)
5999{
Howard Hinnantd4444702010-08-11 17:04:31 +00006000#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006001 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00006002#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006003}
6004
6005template class collate<char>;
6006template class collate<wchar_t>;
6007
6008template class num_get<char>;
6009template class num_get<wchar_t>;
6010
Howard Hinnantec3773c2011-12-01 20:21:04 +00006011template struct __num_get<char>;
6012template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006013
6014template class num_put<char>;
6015template class num_put<wchar_t>;
6016
Howard Hinnantec3773c2011-12-01 20:21:04 +00006017template struct __num_put<char>;
6018template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006019
6020template class time_get<char>;
6021template class time_get<wchar_t>;
6022
6023template class time_get_byname<char>;
6024template class time_get_byname<wchar_t>;
6025
6026template class time_put<char>;
6027template class time_put<wchar_t>;
6028
6029template class time_put_byname<char>;
6030template class time_put_byname<wchar_t>;
6031
6032template class moneypunct<char, false>;
6033template class moneypunct<char, true>;
6034template class moneypunct<wchar_t, false>;
6035template class moneypunct<wchar_t, true>;
6036
6037template class moneypunct_byname<char, false>;
6038template class moneypunct_byname<char, true>;
6039template class moneypunct_byname<wchar_t, false>;
6040template class moneypunct_byname<wchar_t, true>;
6041
6042template class money_get<char>;
6043template class money_get<wchar_t>;
6044
6045template class __money_get<char>;
6046template class __money_get<wchar_t>;
6047
6048template class money_put<char>;
6049template class money_put<wchar_t>;
6050
6051template class __money_put<char>;
6052template class __money_put<wchar_t>;
6053
6054template class messages<char>;
6055template class messages<wchar_t>;
6056
6057template class messages_byname<char>;
6058template class messages_byname<wchar_t>;
6059
6060template class codecvt_byname<char, char, mbstate_t>;
6061template class codecvt_byname<wchar_t, char, mbstate_t>;
6062template class codecvt_byname<char16_t, char, mbstate_t>;
6063template class codecvt_byname<char32_t, char, mbstate_t>;
6064
6065template class __vector_base_common<true>;
6066
6067_LIBCPP_END_NAMESPACE_STD