blob: faceb4e840fcd279b749c5d4400c5c42340cfe89 [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>
85_LIBCPP_ALWAYS_INLINE
86_LIBCPP_CONSTEXPR
87size_t
88countof(const T (&)[N])
89{
90 return N;
91}
92
93template <typename T>
94_LIBCPP_ALWAYS_INLINE
95_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 Hinnant5f767b72012-12-27 23:24:31 +0000227// NOTE(saleem) avoid the `base class should be explicitly initialized in the
228// copy constructor` warning emitted by GCC
229#pragma GCC diagnostic ignored "-Wextra"
230#pragma GCC diagnostic push
231
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__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000893 return isascii(c) ? __classic_upper_table()[static_cast<size_t>(c)] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000894#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000895 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000896#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000897}
898
899const char*
900ctype<char>::do_toupper(char_type* low, const char_type* high) const
901{
902 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000903#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000904 *low = isascii(*low) ?
905 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000906#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000907 *low = isascii(*low) ? __classic_upper_table()[static_cast<size_t>(*low)] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000908#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000909 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000910#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000911 return low;
912}
913
914char
915ctype<char>::do_tolower(char_type c) const
916{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000917#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000918 return isascii(c) ?
919 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000920#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000921 return isascii(c) ? __classic_lower_table()[static_cast<size_t>(c)] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000922#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000923 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000924#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000925}
926
927const char*
928ctype<char>::do_tolower(char_type* low, const char_type* high) const
929{
930 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000931#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000932 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000933#elif defined(__GLIBC__)
Howard Hinnantc6e54b92012-12-27 18:46:00 +0000934 *low = isascii(*low) ? __classic_lower_table()[static_cast<size_t>(*low)] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000935#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000936 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000937#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000938 return low;
939}
940
941char
942ctype<char>::do_widen(char c) const
943{
944 return c;
945}
946
947const char*
948ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
949{
950 for (; low != high; ++low, ++dest)
951 *dest = *low;
952 return low;
953}
954
955char
956ctype<char>::do_narrow(char_type c, char dfault) const
957{
958 if (isascii(c))
959 return static_cast<char>(c);
960 return dfault;
961}
962
963const char*
964ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
965{
966 for (; low != high; ++low, ++dest)
967 if (isascii(*low))
968 *dest = *low;
969 else
970 *dest = dfault;
971 return low;
972}
973
974const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000975ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000976{
David Chisnallc512df12011-09-21 08:39:44 +0000977#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000978 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000979#elif defined(__GLIBC__)
980 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +0000981#elif __sun__
982 return __ctype_mask;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000983#elif _WIN32
984 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +0000985// This is assumed to be safe, which is a nonsense assumption because we're
986// going to end up dereferencing it later...
Sean Hunt62a6ac32011-07-09 00:56:23 +0000987#else
David Chisnall997e4542012-02-29 13:05:08 +0000988 // Platform not supported: abort so the person doing the port knows what to
989 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +0000990# warning ctype<char>::classic_table() is not implemented
David Chisnall997e4542012-02-29 13:05:08 +0000991 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +0000992 return NULL;
993#endif
994}
995
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000996#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000997const int*
998ctype<char>::__classic_lower_table() _NOEXCEPT
999{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001000 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001001}
1002
1003const int*
1004ctype<char>::__classic_upper_table() _NOEXCEPT
1005{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001006 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001007}
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001008#endif // __GLIBC__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001009
1010// template <> class ctype_byname<char>
1011
1012ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1013 : ctype<char>(0, false, refs),
1014 __l(newlocale(LC_ALL_MASK, name, 0))
1015{
Howard Hinnantd4444702010-08-11 17:04:31 +00001016#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001017 if (__l == 0)
1018 throw runtime_error("ctype_byname<char>::ctype_byname"
1019 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001020#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001021}
1022
1023ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1024 : ctype<char>(0, false, refs),
1025 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1026{
Howard Hinnantd4444702010-08-11 17:04:31 +00001027#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001028 if (__l == 0)
1029 throw runtime_error("ctype_byname<char>::ctype_byname"
1030 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001031#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001032}
1033
1034ctype_byname<char>::~ctype_byname()
1035{
1036 freelocale(__l);
1037}
1038
1039char
1040ctype_byname<char>::do_toupper(char_type c) const
1041{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001042 return static_cast<char>(toupper_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001043}
1044
1045const char*
1046ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1047{
1048 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001049 *low = static_cast<char>(toupper_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001050 return low;
1051}
1052
1053char
1054ctype_byname<char>::do_tolower(char_type c) const
1055{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001056 return static_cast<char>(tolower_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001057}
1058
1059const char*
1060ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1061{
1062 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001063 *low = static_cast<char>(tolower_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001064 return low;
1065}
1066
1067// template <> class ctype_byname<wchar_t>
1068
1069ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1070 : ctype<wchar_t>(refs),
1071 __l(newlocale(LC_ALL_MASK, name, 0))
1072{
Howard Hinnantd4444702010-08-11 17:04:31 +00001073#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001074 if (__l == 0)
1075 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1076 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001077#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001078}
1079
1080ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1081 : ctype<wchar_t>(refs),
1082 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1083{
Howard Hinnantd4444702010-08-11 17:04:31 +00001084#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001085 if (__l == 0)
1086 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1087 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001088#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001089}
1090
1091ctype_byname<wchar_t>::~ctype_byname()
1092{
1093 freelocale(__l);
1094}
1095
1096bool
1097ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1098{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001099#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001100 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001101#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001102 bool result = false;
1103 if (m & space) result |= (iswspace_l(c, __l) != 0);
1104 if (m & print) result |= (iswprint_l(c, __l) != 0);
1105 if (m & cntrl) result |= (iswcntrl_l(c, __l) != 0);
1106 if (m & upper) result |= (iswupper_l(c, __l) != 0);
1107 if (m & lower) result |= (iswlower_l(c, __l) != 0);
1108 if (m & alpha) result |= (iswalpha_l(c, __l) != 0);
1109 if (m & digit) result |= (iswdigit_l(c, __l) != 0);
1110 if (m & punct) result |= (iswpunct_l(c, __l) != 0);
1111 if (m & xdigit) result |= (iswxdigit_l(c, __l) != 0);
1112 if (m & blank) result |= (iswblank_l(c, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001113 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001114#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001115}
1116
1117const wchar_t*
1118ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1119{
1120 for (; low != high; ++low, ++vec)
1121 {
1122 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001123 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001124 else
1125 {
1126 *vec = 0;
1127 if (iswspace_l(*low, __l))
1128 *vec |= space;
1129 if (iswprint_l(*low, __l))
1130 *vec |= print;
1131 if (iswcntrl_l(*low, __l))
1132 *vec |= cntrl;
1133 if (iswupper_l(*low, __l))
1134 *vec |= upper;
1135 if (iswlower_l(*low, __l))
1136 *vec |= lower;
1137 if (iswalpha_l(*low, __l))
1138 *vec |= alpha;
1139 if (iswdigit_l(*low, __l))
1140 *vec |= digit;
1141 if (iswpunct_l(*low, __l))
1142 *vec |= punct;
1143 if (iswxdigit_l(*low, __l))
1144 *vec |= xdigit;
1145 }
1146 }
1147 return low;
1148}
1149
1150const wchar_t*
1151ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1152{
1153 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001154 {
1155#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001156 if (iswctype_l(*low, m, __l))
1157 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001158#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001159 if (m & space && iswspace_l(*low, __l)) break;
1160 if (m & print && iswprint_l(*low, __l)) break;
1161 if (m & cntrl && iswcntrl_l(*low, __l)) break;
1162 if (m & upper && iswupper_l(*low, __l)) break;
1163 if (m & lower && iswlower_l(*low, __l)) break;
1164 if (m & alpha && iswalpha_l(*low, __l)) break;
1165 if (m & digit && iswdigit_l(*low, __l)) break;
1166 if (m & punct && iswpunct_l(*low, __l)) break;
1167 if (m & xdigit && iswxdigit_l(*low, __l)) break;
1168 if (m & blank && iswblank_l(*low, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001169#endif
1170 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001171 return low;
1172}
1173
1174const wchar_t*
1175ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1176{
1177 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001178 {
1179#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001180 if (!iswctype_l(*low, m, __l))
1181 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001182#else
1183 if (m & space && iswspace_l(*low, __l)) continue;
1184 if (m & print && iswprint_l(*low, __l)) continue;
1185 if (m & cntrl && iswcntrl_l(*low, __l)) continue;
1186 if (m & upper && iswupper_l(*low, __l)) continue;
1187 if (m & lower && iswlower_l(*low, __l)) continue;
1188 if (m & alpha && iswalpha_l(*low, __l)) continue;
1189 if (m & digit && iswdigit_l(*low, __l)) continue;
1190 if (m & punct && iswpunct_l(*low, __l)) continue;
1191 if (m & xdigit && iswxdigit_l(*low, __l)) continue;
1192 if (m & blank && iswblank_l(*low, __l)) continue;
1193 break;
1194#endif
1195 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001196 return low;
1197}
1198
1199wchar_t
1200ctype_byname<wchar_t>::do_toupper(char_type c) const
1201{
1202 return towupper_l(c, __l);
1203}
1204
1205const wchar_t*
1206ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1207{
1208 for (; low != high; ++low)
1209 *low = towupper_l(*low, __l);
1210 return low;
1211}
1212
1213wchar_t
1214ctype_byname<wchar_t>::do_tolower(char_type c) const
1215{
1216 return towlower_l(c, __l);
1217}
1218
1219const wchar_t*
1220ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1221{
1222 for (; low != high; ++low)
1223 *low = towlower_l(*low, __l);
1224 return low;
1225}
1226
1227wchar_t
1228ctype_byname<wchar_t>::do_widen(char c) const
1229{
Howard Hinnant866569b2011-09-28 23:39:33 +00001230#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001231 return btowc_l(c, __l);
1232#else
1233 return __btowc_l(c, __l);
1234#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001235}
1236
1237const char*
1238ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1239{
1240 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001241#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001242 *dest = btowc_l(*low, __l);
1243#else
1244 *dest = __btowc_l(*low, __l);
1245#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001246 return low;
1247}
1248
1249char
1250ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1251{
Howard Hinnant866569b2011-09-28 23:39:33 +00001252#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001253 int r = wctob_l(c, __l);
1254#else
1255 int r = __wctob_l(c, __l);
1256#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001257 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001258}
1259
1260const wchar_t*
1261ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1262{
1263 for (; low != high; ++low, ++dest)
1264 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001265#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001266 int r = wctob_l(*low, __l);
1267#else
1268 int r = __wctob_l(*low, __l);
1269#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001270 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001271 }
1272 return low;
1273}
1274
1275// template <> class codecvt<char, char, mbstate_t>
1276
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001277locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001278
1279codecvt<char, char, mbstate_t>::~codecvt()
1280{
1281}
1282
1283codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001284codecvt<char, char, mbstate_t>::do_out(state_type&,
1285 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001286 extern_type* to, extern_type*, extern_type*& to_nxt) const
1287{
1288 frm_nxt = frm;
1289 to_nxt = to;
1290 return noconv;
1291}
1292
1293codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001294codecvt<char, char, mbstate_t>::do_in(state_type&,
1295 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001296 intern_type* to, intern_type*, intern_type*& to_nxt) const
1297{
1298 frm_nxt = frm;
1299 to_nxt = to;
1300 return noconv;
1301}
1302
1303codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001304codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001305 extern_type* to, extern_type*, extern_type*& to_nxt) const
1306{
1307 to_nxt = to;
1308 return noconv;
1309}
1310
1311int
Howard Hinnantc9834542011-05-31 15:34:58 +00001312codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001313{
1314 return 1;
1315}
1316
1317bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001318codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001319{
1320 return true;
1321}
1322
1323int
1324codecvt<char, char, mbstate_t>::do_length(state_type&,
1325 const extern_type* frm, const extern_type* end, size_t mx) const
1326{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001327 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001328}
1329
1330int
Howard Hinnantc9834542011-05-31 15:34:58 +00001331codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001332{
1333 return 1;
1334}
1335
1336// template <> class codecvt<wchar_t, char, mbstate_t>
1337
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001338locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001339
1340codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1341 : locale::facet(refs),
1342 __l(0)
1343{
1344}
1345
1346codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1347 : locale::facet(refs),
1348 __l(newlocale(LC_ALL_MASK, nm, 0))
1349{
Howard Hinnantd4444702010-08-11 17:04:31 +00001350#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001351 if (__l == 0)
1352 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1353 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001354#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001355}
1356
1357codecvt<wchar_t, char, mbstate_t>::~codecvt()
1358{
1359 if (__l != 0)
1360 freelocale(__l);
1361}
1362
1363codecvt<wchar_t, char, mbstate_t>::result
1364codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001365 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001366 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1367{
1368 // look for first internal null in frm
1369 const intern_type* fend = frm;
1370 for (; fend != frm_end; ++fend)
1371 if (*fend == 0)
1372 break;
1373 // loop over all null-terminated sequences in frm
1374 to_nxt = to;
1375 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1376 {
1377 // save state in case needed to reover to_nxt on error
1378 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001379#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001380 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1381 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001382#else
1383 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1384#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001385 if (n == size_t(-1))
1386 {
1387 // need to recover to_nxt
1388 for (to_nxt = to; frm != frm_nxt; ++frm)
1389 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001390#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001391 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1392#else
1393 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1394#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001395 if (n == size_t(-1))
1396 break;
1397 to_nxt += n;
1398 }
1399 frm_nxt = frm;
1400 return error;
1401 }
1402 if (n == 0)
1403 return partial;
1404 to_nxt += n;
1405 if (to_nxt == to_end)
1406 break;
1407 if (fend != frm_end) // set up next null terminated sequence
1408 {
1409 // Try to write the terminating null
1410 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001411#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001412 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1413#else
1414 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1415#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001416 if (n == size_t(-1)) // on error
1417 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001418 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001419 return partial;
1420 for (extern_type* p = tmp; n; --n) // write it
1421 *to_nxt++ = *p++;
1422 ++frm_nxt;
1423 // look for next null in frm
1424 for (fend = frm_nxt; fend != frm_end; ++fend)
1425 if (*fend == 0)
1426 break;
1427 }
1428 }
1429 return frm_nxt == frm_end ? ok : partial;
1430}
1431
1432codecvt<wchar_t, char, mbstate_t>::result
1433codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001434 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001435 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1436{
1437 // look for first internal null in frm
1438 const extern_type* fend = frm;
1439 for (; fend != frm_end; ++fend)
1440 if (*fend == 0)
1441 break;
1442 // loop over all null-terminated sequences in frm
1443 to_nxt = to;
1444 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1445 {
1446 // save state in case needed to reover to_nxt on error
1447 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001448#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001449 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1450 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001451#else
1452 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1453#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001454 if (n == size_t(-1))
1455 {
1456 // need to recover to_nxt
1457 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1458 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001459#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001460 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1461 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001462#else
1463 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1464#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001465 switch (n)
1466 {
1467 case 0:
1468 ++frm;
1469 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001470 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001471 frm_nxt = frm;
1472 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001473 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001474 frm_nxt = frm;
1475 return partial;
1476 default:
1477 frm += n;
1478 break;
1479 }
1480 }
1481 frm_nxt = frm;
1482 return frm_nxt == frm_end ? ok : partial;
1483 }
1484 if (n == 0)
1485 return error;
1486 to_nxt += n;
1487 if (to_nxt == to_end)
1488 break;
1489 if (fend != frm_end) // set up next null terminated sequence
1490 {
1491 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001492#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001493 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1494#else
1495 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1496#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001497 if (n != 0) // on error
1498 return error;
1499 ++to_nxt;
1500 ++frm_nxt;
1501 // look for next null in frm
1502 for (fend = frm_nxt; fend != frm_end; ++fend)
1503 if (*fend == 0)
1504 break;
1505 }
1506 }
1507 return frm_nxt == frm_end ? ok : partial;
1508}
1509
1510codecvt<wchar_t, char, mbstate_t>::result
1511codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1512 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1513{
1514 to_nxt = to;
1515 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001516#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001517 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1518#else
1519 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1520#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001521 if (n == size_t(-1) || n == 0) // on error
1522 return error;
1523 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001524 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001525 return partial;
1526 for (extern_type* p = tmp; n; --n) // write it
1527 *to_nxt++ = *p++;
1528 return ok;
1529}
1530
1531int
Howard Hinnantc9834542011-05-31 15:34:58 +00001532codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001533{
Howard Hinnant866569b2011-09-28 23:39:33 +00001534#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001535 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1536#else
1537 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1538#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001539 {
1540 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001541#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001542 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1543#else
1544 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1545#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001546 return 1; // which take more than 1 char to form a wchar_t
1547 return 0;
1548 }
1549 return -1;
1550}
1551
1552bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001553codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001554{
1555 return false;
1556}
1557
1558int
1559codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1560 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1561{
1562 int nbytes = 0;
1563 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1564 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001565#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001566 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001567#else
1568 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1569#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001570 switch (n)
1571 {
1572 case 0:
1573 ++nbytes;
1574 ++frm;
1575 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001576 case size_t(-1):
1577 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001578 return nbytes;
1579 default:
1580 nbytes += n;
1581 frm += n;
1582 break;
1583 }
1584 }
1585 return nbytes;
1586}
1587
1588int
Howard Hinnantc9834542011-05-31 15:34:58 +00001589codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001590{
Howard Hinnant866569b2011-09-28 23:39:33 +00001591#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001592 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1593#else
1594 return __l == 0 ? 1 : __mb_cur_max_l(__l);
1595#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001596}
1597
1598// Valid UTF ranges
1599// UTF-32 UTF-16 UTF-8 # of code points
1600// first second first second third fourth
1601// 000000 - 00007F 0000 - 007F 00 - 7F 127
1602// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1603// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1604// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1605// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1606// 00D800 - 00DFFF invalid
1607// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1608// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1609// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1610// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1611
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001612static
1613codecvt_base::result
1614utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1615 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1616 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1617{
1618 frm_nxt = frm;
1619 to_nxt = to;
1620 if (mode & generate_header)
1621 {
1622 if (to_end-to_nxt < 3)
1623 return codecvt_base::partial;
1624 *to_nxt++ = static_cast<uint8_t>(0xEF);
1625 *to_nxt++ = static_cast<uint8_t>(0xBB);
1626 *to_nxt++ = static_cast<uint8_t>(0xBF);
1627 }
1628 for (; frm_nxt < frm_end; ++frm_nxt)
1629 {
1630 uint16_t wc1 = *frm_nxt;
1631 if (wc1 > Maxcode)
1632 return codecvt_base::error;
1633 if (wc1 < 0x0080)
1634 {
1635 if (to_end-to_nxt < 1)
1636 return codecvt_base::partial;
1637 *to_nxt++ = static_cast<uint8_t>(wc1);
1638 }
1639 else if (wc1 < 0x0800)
1640 {
1641 if (to_end-to_nxt < 2)
1642 return codecvt_base::partial;
1643 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1644 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1645 }
1646 else if (wc1 < 0xD800)
1647 {
1648 if (to_end-to_nxt < 3)
1649 return codecvt_base::partial;
1650 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1651 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1652 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1653 }
1654 else if (wc1 < 0xDC00)
1655 {
1656 if (frm_end-frm_nxt < 2)
1657 return codecvt_base::partial;
1658 uint16_t wc2 = frm_nxt[1];
1659 if ((wc2 & 0xFC00) != 0xDC00)
1660 return codecvt_base::error;
1661 if (to_end-to_nxt < 4)
1662 return codecvt_base::partial;
1663 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1664 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1665 return codecvt_base::error;
1666 ++frm_nxt;
1667 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1668 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1669 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1670 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1671 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1672 }
1673 else if (wc1 < 0xE000)
1674 {
1675 return codecvt_base::error;
1676 }
1677 else
1678 {
1679 if (to_end-to_nxt < 3)
1680 return codecvt_base::partial;
1681 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1682 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1683 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1684 }
1685 }
1686 return codecvt_base::ok;
1687}
1688
1689static
1690codecvt_base::result
1691utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1692 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1693 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1694{
1695 frm_nxt = frm;
1696 to_nxt = to;
1697 if (mode & generate_header)
1698 {
1699 if (to_end-to_nxt < 3)
1700 return codecvt_base::partial;
1701 *to_nxt++ = static_cast<uint8_t>(0xEF);
1702 *to_nxt++ = static_cast<uint8_t>(0xBB);
1703 *to_nxt++ = static_cast<uint8_t>(0xBF);
1704 }
1705 for (; frm_nxt < frm_end; ++frm_nxt)
1706 {
1707 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1708 if (wc1 > Maxcode)
1709 return codecvt_base::error;
1710 if (wc1 < 0x0080)
1711 {
1712 if (to_end-to_nxt < 1)
1713 return codecvt_base::partial;
1714 *to_nxt++ = static_cast<uint8_t>(wc1);
1715 }
1716 else if (wc1 < 0x0800)
1717 {
1718 if (to_end-to_nxt < 2)
1719 return codecvt_base::partial;
1720 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1721 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1722 }
1723 else if (wc1 < 0xD800)
1724 {
1725 if (to_end-to_nxt < 3)
1726 return codecvt_base::partial;
1727 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1728 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1729 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1730 }
1731 else if (wc1 < 0xDC00)
1732 {
1733 if (frm_end-frm_nxt < 2)
1734 return codecvt_base::partial;
1735 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1736 if ((wc2 & 0xFC00) != 0xDC00)
1737 return codecvt_base::error;
1738 if (to_end-to_nxt < 4)
1739 return codecvt_base::partial;
1740 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1741 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1742 return codecvt_base::error;
1743 ++frm_nxt;
1744 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1745 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1746 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1747 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1748 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1749 }
1750 else if (wc1 < 0xE000)
1751 {
1752 return codecvt_base::error;
1753 }
1754 else
1755 {
1756 if (to_end-to_nxt < 3)
1757 return codecvt_base::partial;
1758 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1759 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1760 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1761 }
1762 }
1763 return codecvt_base::ok;
1764}
1765
1766static
1767codecvt_base::result
1768utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1769 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1770 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1771{
1772 frm_nxt = frm;
1773 to_nxt = to;
1774 if (mode & consume_header)
1775 {
1776 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1777 frm_nxt[2] == 0xBF)
1778 frm_nxt += 3;
1779 }
1780 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1781 {
1782 uint8_t c1 = *frm_nxt;
1783 if (c1 > Maxcode)
1784 return codecvt_base::error;
1785 if (c1 < 0x80)
1786 {
1787 *to_nxt = static_cast<uint16_t>(c1);
1788 ++frm_nxt;
1789 }
1790 else if (c1 < 0xC2)
1791 {
1792 return codecvt_base::error;
1793 }
1794 else if (c1 < 0xE0)
1795 {
1796 if (frm_end-frm_nxt < 2)
1797 return codecvt_base::partial;
1798 uint8_t c2 = frm_nxt[1];
1799 if ((c2 & 0xC0) != 0x80)
1800 return codecvt_base::error;
1801 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1802 if (t > Maxcode)
1803 return codecvt_base::error;
1804 *to_nxt = t;
1805 frm_nxt += 2;
1806 }
1807 else if (c1 < 0xF0)
1808 {
1809 if (frm_end-frm_nxt < 3)
1810 return codecvt_base::partial;
1811 uint8_t c2 = frm_nxt[1];
1812 uint8_t c3 = frm_nxt[2];
1813 switch (c1)
1814 {
1815 case 0xE0:
1816 if ((c2 & 0xE0) != 0xA0)
1817 return codecvt_base::error;
1818 break;
1819 case 0xED:
1820 if ((c2 & 0xE0) != 0x80)
1821 return codecvt_base::error;
1822 break;
1823 default:
1824 if ((c2 & 0xC0) != 0x80)
1825 return codecvt_base::error;
1826 break;
1827 }
1828 if ((c3 & 0xC0) != 0x80)
1829 return codecvt_base::error;
1830 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1831 | ((c2 & 0x3F) << 6)
1832 | (c3 & 0x3F));
1833 if (t > Maxcode)
1834 return codecvt_base::error;
1835 *to_nxt = t;
1836 frm_nxt += 3;
1837 }
1838 else if (c1 < 0xF5)
1839 {
1840 if (frm_end-frm_nxt < 4)
1841 return codecvt_base::partial;
1842 uint8_t c2 = frm_nxt[1];
1843 uint8_t c3 = frm_nxt[2];
1844 uint8_t c4 = frm_nxt[3];
1845 switch (c1)
1846 {
1847 case 0xF0:
1848 if (!(0x90 <= c2 && c2 <= 0xBF))
1849 return codecvt_base::error;
1850 break;
1851 case 0xF4:
1852 if ((c2 & 0xF0) != 0x80)
1853 return codecvt_base::error;
1854 break;
1855 default:
1856 if ((c2 & 0xC0) != 0x80)
1857 return codecvt_base::error;
1858 break;
1859 }
1860 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1861 return codecvt_base::error;
1862 if (to_end-to_nxt < 2)
1863 return codecvt_base::partial;
1864 if (((((unsigned long)c1 & 7) << 18) +
1865 (((unsigned long)c2 & 0x3F) << 12) +
1866 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1867 return codecvt_base::error;
1868 *to_nxt = static_cast<uint16_t>(
1869 0xD800
1870 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1871 | ((c2 & 0x0F) << 2)
1872 | ((c3 & 0x30) >> 4));
1873 *++to_nxt = static_cast<uint16_t>(
1874 0xDC00
1875 | ((c3 & 0x0F) << 6)
1876 | (c4 & 0x3F));
1877 frm_nxt += 4;
1878 }
1879 else
1880 {
1881 return codecvt_base::error;
1882 }
1883 }
1884 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1885}
1886
1887static
1888codecvt_base::result
1889utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1890 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1891 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1892{
1893 frm_nxt = frm;
1894 to_nxt = to;
1895 if (mode & consume_header)
1896 {
1897 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1898 frm_nxt[2] == 0xBF)
1899 frm_nxt += 3;
1900 }
1901 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1902 {
1903 uint8_t c1 = *frm_nxt;
1904 if (c1 > Maxcode)
1905 return codecvt_base::error;
1906 if (c1 < 0x80)
1907 {
1908 *to_nxt = static_cast<uint32_t>(c1);
1909 ++frm_nxt;
1910 }
1911 else if (c1 < 0xC2)
1912 {
1913 return codecvt_base::error;
1914 }
1915 else if (c1 < 0xE0)
1916 {
1917 if (frm_end-frm_nxt < 2)
1918 return codecvt_base::partial;
1919 uint8_t c2 = frm_nxt[1];
1920 if ((c2 & 0xC0) != 0x80)
1921 return codecvt_base::error;
1922 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1923 if (t > Maxcode)
1924 return codecvt_base::error;
1925 *to_nxt = static_cast<uint32_t>(t);
1926 frm_nxt += 2;
1927 }
1928 else if (c1 < 0xF0)
1929 {
1930 if (frm_end-frm_nxt < 3)
1931 return codecvt_base::partial;
1932 uint8_t c2 = frm_nxt[1];
1933 uint8_t c3 = frm_nxt[2];
1934 switch (c1)
1935 {
1936 case 0xE0:
1937 if ((c2 & 0xE0) != 0xA0)
1938 return codecvt_base::error;
1939 break;
1940 case 0xED:
1941 if ((c2 & 0xE0) != 0x80)
1942 return codecvt_base::error;
1943 break;
1944 default:
1945 if ((c2 & 0xC0) != 0x80)
1946 return codecvt_base::error;
1947 break;
1948 }
1949 if ((c3 & 0xC0) != 0x80)
1950 return codecvt_base::error;
1951 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1952 | ((c2 & 0x3F) << 6)
1953 | (c3 & 0x3F));
1954 if (t > Maxcode)
1955 return codecvt_base::error;
1956 *to_nxt = static_cast<uint32_t>(t);
1957 frm_nxt += 3;
1958 }
1959 else if (c1 < 0xF5)
1960 {
1961 if (frm_end-frm_nxt < 4)
1962 return codecvt_base::partial;
1963 uint8_t c2 = frm_nxt[1];
1964 uint8_t c3 = frm_nxt[2];
1965 uint8_t c4 = frm_nxt[3];
1966 switch (c1)
1967 {
1968 case 0xF0:
1969 if (!(0x90 <= c2 && c2 <= 0xBF))
1970 return codecvt_base::error;
1971 break;
1972 case 0xF4:
1973 if ((c2 & 0xF0) != 0x80)
1974 return codecvt_base::error;
1975 break;
1976 default:
1977 if ((c2 & 0xC0) != 0x80)
1978 return codecvt_base::error;
1979 break;
1980 }
1981 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1982 return codecvt_base::error;
1983 if (to_end-to_nxt < 2)
1984 return codecvt_base::partial;
1985 if (((((unsigned long)c1 & 7) << 18) +
1986 (((unsigned long)c2 & 0x3F) << 12) +
1987 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1988 return codecvt_base::error;
1989 *to_nxt = static_cast<uint32_t>(
1990 0xD800
1991 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1992 | ((c2 & 0x0F) << 2)
1993 | ((c3 & 0x30) >> 4));
1994 *++to_nxt = static_cast<uint32_t>(
1995 0xDC00
1996 | ((c3 & 0x0F) << 6)
1997 | (c4 & 0x3F));
1998 frm_nxt += 4;
1999 }
2000 else
2001 {
2002 return codecvt_base::error;
2003 }
2004 }
2005 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2006}
2007
2008static
2009int
2010utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2011 size_t mx, unsigned long Maxcode = 0x10FFFF,
2012 codecvt_mode mode = codecvt_mode(0))
2013{
2014 const uint8_t* frm_nxt = frm;
2015 if (mode & consume_header)
2016 {
2017 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2018 frm_nxt[2] == 0xBF)
2019 frm_nxt += 3;
2020 }
2021 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2022 {
2023 uint8_t c1 = *frm_nxt;
2024 if (c1 > Maxcode)
2025 break;
2026 if (c1 < 0x80)
2027 {
2028 ++frm_nxt;
2029 }
2030 else if (c1 < 0xC2)
2031 {
2032 break;
2033 }
2034 else if (c1 < 0xE0)
2035 {
2036 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2037 break;
2038 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2039 if (t > Maxcode)
2040 break;
2041 frm_nxt += 2;
2042 }
2043 else if (c1 < 0xF0)
2044 {
2045 if (frm_end-frm_nxt < 3)
2046 break;
2047 uint8_t c2 = frm_nxt[1];
2048 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002049 switch (c1)
2050 {
2051 case 0xE0:
2052 if ((c2 & 0xE0) != 0xA0)
2053 return static_cast<int>(frm_nxt - frm);
2054 break;
2055 case 0xED:
2056 if ((c2 & 0xE0) != 0x80)
2057 return static_cast<int>(frm_nxt - frm);
2058 break;
2059 default:
2060 if ((c2 & 0xC0) != 0x80)
2061 return static_cast<int>(frm_nxt - frm);
2062 break;
2063 }
2064 if ((c3 & 0xC0) != 0x80)
2065 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002066 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002067 break;
2068 frm_nxt += 3;
2069 }
2070 else if (c1 < 0xF5)
2071 {
2072 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2073 break;
2074 uint8_t c2 = frm_nxt[1];
2075 uint8_t c3 = frm_nxt[2];
2076 uint8_t c4 = frm_nxt[3];
2077 switch (c1)
2078 {
2079 case 0xF0:
2080 if (!(0x90 <= c2 && c2 <= 0xBF))
2081 return static_cast<int>(frm_nxt - frm);
2082 break;
2083 case 0xF4:
2084 if ((c2 & 0xF0) != 0x80)
2085 return static_cast<int>(frm_nxt - frm);
2086 break;
2087 default:
2088 if ((c2 & 0xC0) != 0x80)
2089 return static_cast<int>(frm_nxt - frm);
2090 break;
2091 }
2092 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2093 break;
2094 if (((((unsigned long)c1 & 7) << 18) +
2095 (((unsigned long)c2 & 0x3F) << 12) +
2096 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2097 break;
2098 ++nchar16_t;
2099 frm_nxt += 4;
2100 }
2101 else
2102 {
2103 break;
2104 }
2105 }
2106 return static_cast<int>(frm_nxt - frm);
2107}
2108
2109static
2110codecvt_base::result
2111ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2112 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2113 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2114{
2115 frm_nxt = frm;
2116 to_nxt = to;
2117 if (mode & generate_header)
2118 {
2119 if (to_end-to_nxt < 3)
2120 return codecvt_base::partial;
2121 *to_nxt++ = static_cast<uint8_t>(0xEF);
2122 *to_nxt++ = static_cast<uint8_t>(0xBB);
2123 *to_nxt++ = static_cast<uint8_t>(0xBF);
2124 }
2125 for (; frm_nxt < frm_end; ++frm_nxt)
2126 {
2127 uint32_t wc = *frm_nxt;
2128 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2129 return codecvt_base::error;
2130 if (wc < 0x000080)
2131 {
2132 if (to_end-to_nxt < 1)
2133 return codecvt_base::partial;
2134 *to_nxt++ = static_cast<uint8_t>(wc);
2135 }
2136 else if (wc < 0x000800)
2137 {
2138 if (to_end-to_nxt < 2)
2139 return codecvt_base::partial;
2140 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2141 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2142 }
2143 else if (wc < 0x010000)
2144 {
2145 if (to_end-to_nxt < 3)
2146 return codecvt_base::partial;
2147 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2148 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2149 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2150 }
2151 else // if (wc < 0x110000)
2152 {
2153 if (to_end-to_nxt < 4)
2154 return codecvt_base::partial;
2155 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2156 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2157 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2158 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2159 }
2160 }
2161 return codecvt_base::ok;
2162}
2163
2164static
2165codecvt_base::result
2166utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2167 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2168 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2169{
2170 frm_nxt = frm;
2171 to_nxt = to;
2172 if (mode & consume_header)
2173 {
2174 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2175 frm_nxt[2] == 0xBF)
2176 frm_nxt += 3;
2177 }
2178 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2179 {
2180 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2181 if (c1 < 0x80)
2182 {
2183 if (c1 > Maxcode)
2184 return codecvt_base::error;
2185 *to_nxt = static_cast<uint32_t>(c1);
2186 ++frm_nxt;
2187 }
2188 else if (c1 < 0xC2)
2189 {
2190 return codecvt_base::error;
2191 }
2192 else if (c1 < 0xE0)
2193 {
2194 if (frm_end-frm_nxt < 2)
2195 return codecvt_base::partial;
2196 uint8_t c2 = frm_nxt[1];
2197 if ((c2 & 0xC0) != 0x80)
2198 return codecvt_base::error;
2199 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2200 | (c2 & 0x3F));
2201 if (t > Maxcode)
2202 return codecvt_base::error;
2203 *to_nxt = t;
2204 frm_nxt += 2;
2205 }
2206 else if (c1 < 0xF0)
2207 {
2208 if (frm_end-frm_nxt < 3)
2209 return codecvt_base::partial;
2210 uint8_t c2 = frm_nxt[1];
2211 uint8_t c3 = frm_nxt[2];
2212 switch (c1)
2213 {
2214 case 0xE0:
2215 if ((c2 & 0xE0) != 0xA0)
2216 return codecvt_base::error;
2217 break;
2218 case 0xED:
2219 if ((c2 & 0xE0) != 0x80)
2220 return codecvt_base::error;
2221 break;
2222 default:
2223 if ((c2 & 0xC0) != 0x80)
2224 return codecvt_base::error;
2225 break;
2226 }
2227 if ((c3 & 0xC0) != 0x80)
2228 return codecvt_base::error;
2229 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2230 | ((c2 & 0x3F) << 6)
2231 | (c3 & 0x3F));
2232 if (t > Maxcode)
2233 return codecvt_base::error;
2234 *to_nxt = t;
2235 frm_nxt += 3;
2236 }
2237 else if (c1 < 0xF5)
2238 {
2239 if (frm_end-frm_nxt < 4)
2240 return codecvt_base::partial;
2241 uint8_t c2 = frm_nxt[1];
2242 uint8_t c3 = frm_nxt[2];
2243 uint8_t c4 = frm_nxt[3];
2244 switch (c1)
2245 {
2246 case 0xF0:
2247 if (!(0x90 <= c2 && c2 <= 0xBF))
2248 return codecvt_base::error;
2249 break;
2250 case 0xF4:
2251 if ((c2 & 0xF0) != 0x80)
2252 return codecvt_base::error;
2253 break;
2254 default:
2255 if ((c2 & 0xC0) != 0x80)
2256 return codecvt_base::error;
2257 break;
2258 }
2259 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2260 return codecvt_base::error;
2261 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2262 | ((c2 & 0x3F) << 12)
2263 | ((c3 & 0x3F) << 6)
2264 | (c4 & 0x3F));
2265 if (t > Maxcode)
2266 return codecvt_base::error;
2267 *to_nxt = t;
2268 frm_nxt += 4;
2269 }
2270 else
2271 {
2272 return codecvt_base::error;
2273 }
2274 }
2275 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2276}
2277
2278static
2279int
2280utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2281 size_t mx, unsigned long Maxcode = 0x10FFFF,
2282 codecvt_mode mode = codecvt_mode(0))
2283{
2284 const uint8_t* frm_nxt = frm;
2285 if (mode & consume_header)
2286 {
2287 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2288 frm_nxt[2] == 0xBF)
2289 frm_nxt += 3;
2290 }
2291 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2292 {
2293 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2294 if (c1 < 0x80)
2295 {
2296 if (c1 > Maxcode)
2297 break;
2298 ++frm_nxt;
2299 }
2300 else if (c1 < 0xC2)
2301 {
2302 break;
2303 }
2304 else if (c1 < 0xE0)
2305 {
2306 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2307 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002308 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002309 break;
2310 frm_nxt += 2;
2311 }
2312 else if (c1 < 0xF0)
2313 {
2314 if (frm_end-frm_nxt < 3)
2315 break;
2316 uint8_t c2 = frm_nxt[1];
2317 uint8_t c3 = frm_nxt[2];
2318 switch (c1)
2319 {
2320 case 0xE0:
2321 if ((c2 & 0xE0) != 0xA0)
2322 return static_cast<int>(frm_nxt - frm);
2323 break;
2324 case 0xED:
2325 if ((c2 & 0xE0) != 0x80)
2326 return static_cast<int>(frm_nxt - frm);
2327 break;
2328 default:
2329 if ((c2 & 0xC0) != 0x80)
2330 return static_cast<int>(frm_nxt - frm);
2331 break;
2332 }
2333 if ((c3 & 0xC0) != 0x80)
2334 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002335 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002336 break;
2337 frm_nxt += 3;
2338 }
2339 else if (c1 < 0xF5)
2340 {
2341 if (frm_end-frm_nxt < 4)
2342 break;
2343 uint8_t c2 = frm_nxt[1];
2344 uint8_t c3 = frm_nxt[2];
2345 uint8_t c4 = frm_nxt[3];
2346 switch (c1)
2347 {
2348 case 0xF0:
2349 if (!(0x90 <= c2 && c2 <= 0xBF))
2350 return static_cast<int>(frm_nxt - frm);
2351 break;
2352 case 0xF4:
2353 if ((c2 & 0xF0) != 0x80)
2354 return static_cast<int>(frm_nxt - frm);
2355 break;
2356 default:
2357 if ((c2 & 0xC0) != 0x80)
2358 return static_cast<int>(frm_nxt - frm);
2359 break;
2360 }
2361 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2362 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002363 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2364 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002365 break;
2366 frm_nxt += 4;
2367 }
2368 else
2369 {
2370 break;
2371 }
2372 }
2373 return static_cast<int>(frm_nxt - frm);
2374}
2375
2376static
2377codecvt_base::result
2378ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2379 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2380 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2381{
2382 frm_nxt = frm;
2383 to_nxt = to;
2384 if (mode & generate_header)
2385 {
2386 if (to_end-to_nxt < 3)
2387 return codecvt_base::partial;
2388 *to_nxt++ = static_cast<uint8_t>(0xEF);
2389 *to_nxt++ = static_cast<uint8_t>(0xBB);
2390 *to_nxt++ = static_cast<uint8_t>(0xBF);
2391 }
2392 for (; frm_nxt < frm_end; ++frm_nxt)
2393 {
2394 uint16_t wc = *frm_nxt;
2395 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2396 return codecvt_base::error;
2397 if (wc < 0x0080)
2398 {
2399 if (to_end-to_nxt < 1)
2400 return codecvt_base::partial;
2401 *to_nxt++ = static_cast<uint8_t>(wc);
2402 }
2403 else if (wc < 0x0800)
2404 {
2405 if (to_end-to_nxt < 2)
2406 return codecvt_base::partial;
2407 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2408 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2409 }
2410 else // if (wc <= 0xFFFF)
2411 {
2412 if (to_end-to_nxt < 3)
2413 return codecvt_base::partial;
2414 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2415 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2416 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2417 }
2418 }
2419 return codecvt_base::ok;
2420}
2421
2422static
2423codecvt_base::result
2424utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2425 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2426 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2427{
2428 frm_nxt = frm;
2429 to_nxt = to;
2430 if (mode & consume_header)
2431 {
2432 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2433 frm_nxt[2] == 0xBF)
2434 frm_nxt += 3;
2435 }
2436 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2437 {
2438 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2439 if (c1 < 0x80)
2440 {
2441 if (c1 > Maxcode)
2442 return codecvt_base::error;
2443 *to_nxt = static_cast<uint16_t>(c1);
2444 ++frm_nxt;
2445 }
2446 else if (c1 < 0xC2)
2447 {
2448 return codecvt_base::error;
2449 }
2450 else if (c1 < 0xE0)
2451 {
2452 if (frm_end-frm_nxt < 2)
2453 return codecvt_base::partial;
2454 uint8_t c2 = frm_nxt[1];
2455 if ((c2 & 0xC0) != 0x80)
2456 return codecvt_base::error;
2457 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2458 | (c2 & 0x3F));
2459 if (t > Maxcode)
2460 return codecvt_base::error;
2461 *to_nxt = t;
2462 frm_nxt += 2;
2463 }
2464 else if (c1 < 0xF0)
2465 {
2466 if (frm_end-frm_nxt < 3)
2467 return codecvt_base::partial;
2468 uint8_t c2 = frm_nxt[1];
2469 uint8_t c3 = frm_nxt[2];
2470 switch (c1)
2471 {
2472 case 0xE0:
2473 if ((c2 & 0xE0) != 0xA0)
2474 return codecvt_base::error;
2475 break;
2476 case 0xED:
2477 if ((c2 & 0xE0) != 0x80)
2478 return codecvt_base::error;
2479 break;
2480 default:
2481 if ((c2 & 0xC0) != 0x80)
2482 return codecvt_base::error;
2483 break;
2484 }
2485 if ((c3 & 0xC0) != 0x80)
2486 return codecvt_base::error;
2487 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2488 | ((c2 & 0x3F) << 6)
2489 | (c3 & 0x3F));
2490 if (t > Maxcode)
2491 return codecvt_base::error;
2492 *to_nxt = t;
2493 frm_nxt += 3;
2494 }
2495 else
2496 {
2497 return codecvt_base::error;
2498 }
2499 }
2500 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2501}
2502
2503static
2504int
2505utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2506 size_t mx, unsigned long Maxcode = 0x10FFFF,
2507 codecvt_mode mode = codecvt_mode(0))
2508{
2509 const uint8_t* frm_nxt = frm;
2510 if (mode & consume_header)
2511 {
2512 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2513 frm_nxt[2] == 0xBF)
2514 frm_nxt += 3;
2515 }
2516 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2517 {
2518 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2519 if (c1 < 0x80)
2520 {
2521 if (c1 > Maxcode)
2522 break;
2523 ++frm_nxt;
2524 }
2525 else if (c1 < 0xC2)
2526 {
2527 break;
2528 }
2529 else if (c1 < 0xE0)
2530 {
2531 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2532 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002533 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002534 break;
2535 frm_nxt += 2;
2536 }
2537 else if (c1 < 0xF0)
2538 {
2539 if (frm_end-frm_nxt < 3)
2540 break;
2541 uint8_t c2 = frm_nxt[1];
2542 uint8_t c3 = frm_nxt[2];
2543 switch (c1)
2544 {
2545 case 0xE0:
2546 if ((c2 & 0xE0) != 0xA0)
2547 return static_cast<int>(frm_nxt - frm);
2548 break;
2549 case 0xED:
2550 if ((c2 & 0xE0) != 0x80)
2551 return static_cast<int>(frm_nxt - frm);
2552 break;
2553 default:
2554 if ((c2 & 0xC0) != 0x80)
2555 return static_cast<int>(frm_nxt - frm);
2556 break;
2557 }
2558 if ((c3 & 0xC0) != 0x80)
2559 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002560 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002561 break;
2562 frm_nxt += 3;
2563 }
2564 else
2565 {
2566 break;
2567 }
2568 }
2569 return static_cast<int>(frm_nxt - frm);
2570}
2571
2572static
2573codecvt_base::result
2574ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2575 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2576 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2577{
2578 frm_nxt = frm;
2579 to_nxt = to;
2580 if (mode & generate_header)
2581 {
2582 if (to_end-to_nxt < 2)
2583 return codecvt_base::partial;
2584 *to_nxt++ = static_cast<uint8_t>(0xFE);
2585 *to_nxt++ = static_cast<uint8_t>(0xFF);
2586 }
2587 for (; frm_nxt < frm_end; ++frm_nxt)
2588 {
2589 uint32_t wc = *frm_nxt;
2590 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2591 return codecvt_base::error;
2592 if (wc < 0x010000)
2593 {
2594 if (to_end-to_nxt < 2)
2595 return codecvt_base::partial;
2596 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2597 *to_nxt++ = static_cast<uint8_t>(wc);
2598 }
2599 else
2600 {
2601 if (to_end-to_nxt < 4)
2602 return codecvt_base::partial;
2603 uint16_t t = static_cast<uint16_t>(
2604 0xD800
2605 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2606 | ((wc & 0x00FC00) >> 10));
2607 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2608 *to_nxt++ = static_cast<uint8_t>(t);
2609 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2610 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2611 *to_nxt++ = static_cast<uint8_t>(t);
2612 }
2613 }
2614 return codecvt_base::ok;
2615}
2616
2617static
2618codecvt_base::result
2619utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2620 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2621 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2622{
2623 frm_nxt = frm;
2624 to_nxt = to;
2625 if (mode & consume_header)
2626 {
2627 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2628 frm_nxt += 2;
2629 }
2630 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2631 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002632 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002633 if ((c1 & 0xFC00) == 0xDC00)
2634 return codecvt_base::error;
2635 if ((c1 & 0xFC00) != 0xD800)
2636 {
2637 if (c1 > Maxcode)
2638 return codecvt_base::error;
2639 *to_nxt = static_cast<uint32_t>(c1);
2640 frm_nxt += 2;
2641 }
2642 else
2643 {
2644 if (frm_end-frm_nxt < 4)
2645 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002646 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002647 if ((c2 & 0xFC00) != 0xDC00)
2648 return codecvt_base::error;
2649 uint32_t t = static_cast<uint32_t>(
2650 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2651 | ((c1 & 0x003F) << 10)
2652 | (c2 & 0x03FF));
2653 if (t > Maxcode)
2654 return codecvt_base::error;
2655 *to_nxt = t;
2656 frm_nxt += 4;
2657 }
2658 }
2659 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2660}
2661
2662static
2663int
2664utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2665 size_t mx, unsigned long Maxcode = 0x10FFFF,
2666 codecvt_mode mode = codecvt_mode(0))
2667{
2668 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002669 if (mode & consume_header)
2670 {
2671 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2672 frm_nxt += 2;
2673 }
2674 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2675 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002676 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002677 if ((c1 & 0xFC00) == 0xDC00)
2678 break;
2679 if ((c1 & 0xFC00) != 0xD800)
2680 {
2681 if (c1 > Maxcode)
2682 break;
2683 frm_nxt += 2;
2684 }
2685 else
2686 {
2687 if (frm_end-frm_nxt < 4)
2688 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002689 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002690 if ((c2 & 0xFC00) != 0xDC00)
2691 break;
2692 uint32_t t = static_cast<uint32_t>(
2693 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2694 | ((c1 & 0x003F) << 10)
2695 | (c2 & 0x03FF));
2696 if (t > Maxcode)
2697 break;
2698 frm_nxt += 4;
2699 }
2700 }
2701 return static_cast<int>(frm_nxt - frm);
2702}
2703
2704static
2705codecvt_base::result
2706ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2707 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2708 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2709{
2710 frm_nxt = frm;
2711 to_nxt = to;
2712 if (mode & generate_header)
2713 {
2714 if (to_end-to_nxt < 2)
2715 return codecvt_base::partial;
2716 *to_nxt++ = static_cast<uint8_t>(0xFF);
2717 *to_nxt++ = static_cast<uint8_t>(0xFE);
2718 }
2719 for (; frm_nxt < frm_end; ++frm_nxt)
2720 {
2721 uint32_t wc = *frm_nxt;
2722 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2723 return codecvt_base::error;
2724 if (wc < 0x010000)
2725 {
2726 if (to_end-to_nxt < 2)
2727 return codecvt_base::partial;
2728 *to_nxt++ = static_cast<uint8_t>(wc);
2729 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2730 }
2731 else
2732 {
2733 if (to_end-to_nxt < 4)
2734 return codecvt_base::partial;
2735 uint16_t t = static_cast<uint16_t>(
2736 0xD800
2737 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2738 | ((wc & 0x00FC00) >> 10));
2739 *to_nxt++ = static_cast<uint8_t>(t);
2740 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2741 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2742 *to_nxt++ = static_cast<uint8_t>(t);
2743 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2744 }
2745 }
2746 return codecvt_base::ok;
2747}
2748
2749static
2750codecvt_base::result
2751utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2752 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2753 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2754{
2755 frm_nxt = frm;
2756 to_nxt = to;
2757 if (mode & consume_header)
2758 {
2759 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2760 frm_nxt += 2;
2761 }
2762 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2763 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002764 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002765 if ((c1 & 0xFC00) == 0xDC00)
2766 return codecvt_base::error;
2767 if ((c1 & 0xFC00) != 0xD800)
2768 {
2769 if (c1 > Maxcode)
2770 return codecvt_base::error;
2771 *to_nxt = static_cast<uint32_t>(c1);
2772 frm_nxt += 2;
2773 }
2774 else
2775 {
2776 if (frm_end-frm_nxt < 4)
2777 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002778 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002779 if ((c2 & 0xFC00) != 0xDC00)
2780 return codecvt_base::error;
2781 uint32_t t = static_cast<uint32_t>(
2782 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2783 | ((c1 & 0x003F) << 10)
2784 | (c2 & 0x03FF));
2785 if (t > Maxcode)
2786 return codecvt_base::error;
2787 *to_nxt = t;
2788 frm_nxt += 4;
2789 }
2790 }
2791 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2792}
2793
2794static
2795int
2796utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2797 size_t mx, unsigned long Maxcode = 0x10FFFF,
2798 codecvt_mode mode = codecvt_mode(0))
2799{
2800 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002801 if (mode & consume_header)
2802 {
2803 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2804 frm_nxt += 2;
2805 }
2806 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2807 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002808 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002809 if ((c1 & 0xFC00) == 0xDC00)
2810 break;
2811 if ((c1 & 0xFC00) != 0xD800)
2812 {
2813 if (c1 > Maxcode)
2814 break;
2815 frm_nxt += 2;
2816 }
2817 else
2818 {
2819 if (frm_end-frm_nxt < 4)
2820 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002821 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002822 if ((c2 & 0xFC00) != 0xDC00)
2823 break;
2824 uint32_t t = static_cast<uint32_t>(
2825 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2826 | ((c1 & 0x003F) << 10)
2827 | (c2 & 0x03FF));
2828 if (t > Maxcode)
2829 break;
2830 frm_nxt += 4;
2831 }
2832 }
2833 return static_cast<int>(frm_nxt - frm);
2834}
2835
2836static
2837codecvt_base::result
2838ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2839 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2840 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2841{
2842 frm_nxt = frm;
2843 to_nxt = to;
2844 if (mode & generate_header)
2845 {
2846 if (to_end-to_nxt < 2)
2847 return codecvt_base::partial;
2848 *to_nxt++ = static_cast<uint8_t>(0xFE);
2849 *to_nxt++ = static_cast<uint8_t>(0xFF);
2850 }
2851 for (; frm_nxt < frm_end; ++frm_nxt)
2852 {
2853 uint16_t wc = *frm_nxt;
2854 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2855 return codecvt_base::error;
2856 if (to_end-to_nxt < 2)
2857 return codecvt_base::partial;
2858 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2859 *to_nxt++ = static_cast<uint8_t>(wc);
2860 }
2861 return codecvt_base::ok;
2862}
2863
2864static
2865codecvt_base::result
2866utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2867 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2868 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2869{
2870 frm_nxt = frm;
2871 to_nxt = to;
2872 if (mode & consume_header)
2873 {
2874 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2875 frm_nxt += 2;
2876 }
2877 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2878 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002879 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002880 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2881 return codecvt_base::error;
2882 *to_nxt = c1;
2883 frm_nxt += 2;
2884 }
2885 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2886}
2887
2888static
2889int
2890utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2891 size_t mx, unsigned long Maxcode = 0x10FFFF,
2892 codecvt_mode mode = codecvt_mode(0))
2893{
2894 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002895 if (mode & consume_header)
2896 {
2897 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2898 frm_nxt += 2;
2899 }
2900 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2901 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002902 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002903 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2904 break;
2905 frm_nxt += 2;
2906 }
2907 return static_cast<int>(frm_nxt - frm);
2908}
2909
2910static
2911codecvt_base::result
2912ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2913 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2914 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2915{
2916 frm_nxt = frm;
2917 to_nxt = to;
2918 if (mode & generate_header)
2919 {
2920 if (to_end-to_nxt < 2)
2921 return codecvt_base::partial;
2922 *to_nxt++ = static_cast<uint8_t>(0xFF);
2923 *to_nxt++ = static_cast<uint8_t>(0xFE);
2924 }
2925 for (; frm_nxt < frm_end; ++frm_nxt)
2926 {
2927 uint16_t wc = *frm_nxt;
2928 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2929 return codecvt_base::error;
2930 if (to_end-to_nxt < 2)
2931 return codecvt_base::partial;
2932 *to_nxt++ = static_cast<uint8_t>(wc);
2933 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2934 }
2935 return codecvt_base::ok;
2936}
2937
2938static
2939codecvt_base::result
2940utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2941 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2942 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2943{
2944 frm_nxt = frm;
2945 to_nxt = to;
2946 if (mode & consume_header)
2947 {
2948 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2949 frm_nxt += 2;
2950 }
2951 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2952 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002953 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002954 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2955 return codecvt_base::error;
2956 *to_nxt = c1;
2957 frm_nxt += 2;
2958 }
2959 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2960}
2961
2962static
2963int
2964utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2965 size_t mx, unsigned long Maxcode = 0x10FFFF,
2966 codecvt_mode mode = codecvt_mode(0))
2967{
2968 const uint8_t* frm_nxt = frm;
2969 frm_nxt = frm;
2970 if (mode & consume_header)
2971 {
2972 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2973 frm_nxt += 2;
2974 }
2975 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2976 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002977 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002978 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2979 break;
2980 frm_nxt += 2;
2981 }
2982 return static_cast<int>(frm_nxt - frm);
2983}
2984
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002985// template <> class codecvt<char16_t, char, mbstate_t>
2986
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002987locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002988
2989codecvt<char16_t, char, mbstate_t>::~codecvt()
2990{
2991}
2992
2993codecvt<char16_t, char, mbstate_t>::result
2994codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002995 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002996 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2997{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002998 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2999 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3000 const uint16_t* _frm_nxt = _frm;
3001 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3002 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3003 uint8_t* _to_nxt = _to;
3004 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3005 frm_nxt = frm + (_frm_nxt - _frm);
3006 to_nxt = to + (_to_nxt - _to);
3007 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003008}
3009
3010codecvt<char16_t, char, mbstate_t>::result
3011codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003012 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003013 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3014{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003015 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3016 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3017 const uint8_t* _frm_nxt = _frm;
3018 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3019 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3020 uint16_t* _to_nxt = _to;
3021 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3022 frm_nxt = frm + (_frm_nxt - _frm);
3023 to_nxt = to + (_to_nxt - _to);
3024 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003025}
3026
3027codecvt<char16_t, char, mbstate_t>::result
3028codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3029 extern_type* to, extern_type*, extern_type*& to_nxt) const
3030{
3031 to_nxt = to;
3032 return noconv;
3033}
3034
3035int
Howard Hinnantc9834542011-05-31 15:34:58 +00003036codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003037{
3038 return 0;
3039}
3040
3041bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003042codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003043{
3044 return false;
3045}
3046
3047int
3048codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3049 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3050{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003051 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3052 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3053 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003054}
3055
3056int
Howard Hinnantc9834542011-05-31 15:34:58 +00003057codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003058{
3059 return 4;
3060}
3061
3062// template <> class codecvt<char32_t, char, mbstate_t>
3063
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003064locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003065
3066codecvt<char32_t, char, mbstate_t>::~codecvt()
3067{
3068}
3069
3070codecvt<char32_t, char, mbstate_t>::result
3071codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003072 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003073 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3074{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003075 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3076 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3077 const uint32_t* _frm_nxt = _frm;
3078 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3079 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3080 uint8_t* _to_nxt = _to;
3081 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3082 frm_nxt = frm + (_frm_nxt - _frm);
3083 to_nxt = to + (_to_nxt - _to);
3084 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003085}
3086
3087codecvt<char32_t, char, mbstate_t>::result
3088codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003089 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003090 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3091{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003092 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3093 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3094 const uint8_t* _frm_nxt = _frm;
3095 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3096 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3097 uint32_t* _to_nxt = _to;
3098 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3099 frm_nxt = frm + (_frm_nxt - _frm);
3100 to_nxt = to + (_to_nxt - _to);
3101 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003102}
3103
3104codecvt<char32_t, char, mbstate_t>::result
3105codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3106 extern_type* to, extern_type*, extern_type*& to_nxt) const
3107{
3108 to_nxt = to;
3109 return noconv;
3110}
3111
3112int
Howard Hinnantc9834542011-05-31 15:34:58 +00003113codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003114{
3115 return 0;
3116}
3117
3118bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003119codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003120{
3121 return false;
3122}
3123
3124int
3125codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3126 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3127{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003128 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3129 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3130 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003131}
3132
3133int
Howard Hinnantc9834542011-05-31 15:34:58 +00003134codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003135{
3136 return 4;
3137}
3138
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003139// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003140
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003141__codecvt_utf8<wchar_t>::result
3142__codecvt_utf8<wchar_t>::do_out(state_type&,
3143 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003144 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3145{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003146 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3147 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3148 const uint32_t* _frm_nxt = _frm;
3149 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3150 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3151 uint8_t* _to_nxt = _to;
3152 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3153 _Maxcode_, _Mode_);
3154 frm_nxt = frm + (_frm_nxt - _frm);
3155 to_nxt = to + (_to_nxt - _to);
3156 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003157}
3158
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003159__codecvt_utf8<wchar_t>::result
3160__codecvt_utf8<wchar_t>::do_in(state_type&,
3161 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003162 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3163{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003164 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3165 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3166 const uint8_t* _frm_nxt = _frm;
3167 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3168 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3169 uint32_t* _to_nxt = _to;
3170 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3171 _Maxcode_, _Mode_);
3172 frm_nxt = frm + (_frm_nxt - _frm);
3173 to_nxt = to + (_to_nxt - _to);
3174 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003175}
3176
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003177__codecvt_utf8<wchar_t>::result
3178__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003179 extern_type* to, extern_type*, extern_type*& to_nxt) const
3180{
3181 to_nxt = to;
3182 return noconv;
3183}
3184
3185int
Howard Hinnantc9834542011-05-31 15:34:58 +00003186__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003187{
3188 return 0;
3189}
3190
3191bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003192__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003193{
3194 return false;
3195}
3196
3197int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003198__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003199 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3200{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003201 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3202 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3203 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003204}
3205
3206int
Howard Hinnantc9834542011-05-31 15:34:58 +00003207__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003208{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003209 if (_Mode_ & consume_header)
3210 return 7;
3211 return 4;
3212}
3213
3214// __codecvt_utf8<char16_t>
3215
3216__codecvt_utf8<char16_t>::result
3217__codecvt_utf8<char16_t>::do_out(state_type&,
3218 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3219 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3220{
3221 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3222 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3223 const uint16_t* _frm_nxt = _frm;
3224 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3225 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3226 uint8_t* _to_nxt = _to;
3227 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3228 _Maxcode_, _Mode_);
3229 frm_nxt = frm + (_frm_nxt - _frm);
3230 to_nxt = to + (_to_nxt - _to);
3231 return r;
3232}
3233
3234__codecvt_utf8<char16_t>::result
3235__codecvt_utf8<char16_t>::do_in(state_type&,
3236 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3237 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3238{
3239 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3240 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3241 const uint8_t* _frm_nxt = _frm;
3242 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3243 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3244 uint16_t* _to_nxt = _to;
3245 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3246 _Maxcode_, _Mode_);
3247 frm_nxt = frm + (_frm_nxt - _frm);
3248 to_nxt = to + (_to_nxt - _to);
3249 return r;
3250}
3251
3252__codecvt_utf8<char16_t>::result
3253__codecvt_utf8<char16_t>::do_unshift(state_type&,
3254 extern_type* to, extern_type*, extern_type*& to_nxt) const
3255{
3256 to_nxt = to;
3257 return noconv;
3258}
3259
3260int
Howard Hinnantc9834542011-05-31 15:34:58 +00003261__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003262{
3263 return 0;
3264}
3265
3266bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003267__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003268{
3269 return false;
3270}
3271
3272int
3273__codecvt_utf8<char16_t>::do_length(state_type&,
3274 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3275{
3276 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3277 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3278 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3279}
3280
3281int
Howard Hinnantc9834542011-05-31 15:34:58 +00003282__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003283{
3284 if (_Mode_ & consume_header)
3285 return 6;
3286 return 3;
3287}
3288
3289// __codecvt_utf8<char32_t>
3290
3291__codecvt_utf8<char32_t>::result
3292__codecvt_utf8<char32_t>::do_out(state_type&,
3293 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3294 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3295{
3296 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3297 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3298 const uint32_t* _frm_nxt = _frm;
3299 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3300 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3301 uint8_t* _to_nxt = _to;
3302 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3303 _Maxcode_, _Mode_);
3304 frm_nxt = frm + (_frm_nxt - _frm);
3305 to_nxt = to + (_to_nxt - _to);
3306 return r;
3307}
3308
3309__codecvt_utf8<char32_t>::result
3310__codecvt_utf8<char32_t>::do_in(state_type&,
3311 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3312 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3313{
3314 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3315 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3316 const uint8_t* _frm_nxt = _frm;
3317 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3318 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3319 uint32_t* _to_nxt = _to;
3320 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3321 _Maxcode_, _Mode_);
3322 frm_nxt = frm + (_frm_nxt - _frm);
3323 to_nxt = to + (_to_nxt - _to);
3324 return r;
3325}
3326
3327__codecvt_utf8<char32_t>::result
3328__codecvt_utf8<char32_t>::do_unshift(state_type&,
3329 extern_type* to, extern_type*, extern_type*& to_nxt) const
3330{
3331 to_nxt = to;
3332 return noconv;
3333}
3334
3335int
Howard Hinnantc9834542011-05-31 15:34:58 +00003336__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003337{
3338 return 0;
3339}
3340
3341bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003342__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003343{
3344 return false;
3345}
3346
3347int
3348__codecvt_utf8<char32_t>::do_length(state_type&,
3349 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3350{
3351 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3352 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3353 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3354}
3355
3356int
Howard Hinnantc9834542011-05-31 15:34:58 +00003357__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003358{
3359 if (_Mode_ & consume_header)
3360 return 7;
3361 return 4;
3362}
3363
3364// __codecvt_utf16<wchar_t, false>
3365
3366__codecvt_utf16<wchar_t, false>::result
3367__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3368 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3369 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3370{
3371 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3372 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3373 const uint32_t* _frm_nxt = _frm;
3374 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3375 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3376 uint8_t* _to_nxt = _to;
3377 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3378 _Maxcode_, _Mode_);
3379 frm_nxt = frm + (_frm_nxt - _frm);
3380 to_nxt = to + (_to_nxt - _to);
3381 return r;
3382}
3383
3384__codecvt_utf16<wchar_t, false>::result
3385__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3386 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3387 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3388{
3389 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3390 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3391 const uint8_t* _frm_nxt = _frm;
3392 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3393 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3394 uint32_t* _to_nxt = _to;
3395 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3396 _Maxcode_, _Mode_);
3397 frm_nxt = frm + (_frm_nxt - _frm);
3398 to_nxt = to + (_to_nxt - _to);
3399 return r;
3400}
3401
3402__codecvt_utf16<wchar_t, false>::result
3403__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3404 extern_type* to, extern_type*, extern_type*& to_nxt) const
3405{
3406 to_nxt = to;
3407 return noconv;
3408}
3409
3410int
Howard Hinnantc9834542011-05-31 15:34:58 +00003411__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003412{
3413 return 0;
3414}
3415
3416bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003417__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003418{
3419 return false;
3420}
3421
3422int
3423__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3424 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3425{
3426 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3427 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3428 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3429}
3430
3431int
Howard Hinnantc9834542011-05-31 15:34:58 +00003432__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003433{
3434 if (_Mode_ & consume_header)
3435 return 6;
3436 return 4;
3437}
3438
3439// __codecvt_utf16<wchar_t, true>
3440
3441__codecvt_utf16<wchar_t, true>::result
3442__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3443 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3444 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3445{
3446 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3447 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3448 const uint32_t* _frm_nxt = _frm;
3449 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3450 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3451 uint8_t* _to_nxt = _to;
3452 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3453 _Maxcode_, _Mode_);
3454 frm_nxt = frm + (_frm_nxt - _frm);
3455 to_nxt = to + (_to_nxt - _to);
3456 return r;
3457}
3458
3459__codecvt_utf16<wchar_t, true>::result
3460__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3461 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3462 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3463{
3464 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3465 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3466 const uint8_t* _frm_nxt = _frm;
3467 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3468 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3469 uint32_t* _to_nxt = _to;
3470 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3471 _Maxcode_, _Mode_);
3472 frm_nxt = frm + (_frm_nxt - _frm);
3473 to_nxt = to + (_to_nxt - _to);
3474 return r;
3475}
3476
3477__codecvt_utf16<wchar_t, true>::result
3478__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3479 extern_type* to, extern_type*, extern_type*& to_nxt) const
3480{
3481 to_nxt = to;
3482 return noconv;
3483}
3484
3485int
Howard Hinnantc9834542011-05-31 15:34:58 +00003486__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003487{
3488 return 0;
3489}
3490
3491bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003492__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003493{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003494 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003495}
3496
3497int
3498__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3499 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3500{
3501 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3502 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3503 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3504}
3505
3506int
Howard Hinnantc9834542011-05-31 15:34:58 +00003507__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003508{
3509 if (_Mode_ & consume_header)
3510 return 6;
3511 return 4;
3512}
3513
3514// __codecvt_utf16<char16_t, false>
3515
3516__codecvt_utf16<char16_t, false>::result
3517__codecvt_utf16<char16_t, false>::do_out(state_type&,
3518 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3519 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3520{
3521 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3522 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3523 const uint16_t* _frm_nxt = _frm;
3524 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3525 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3526 uint8_t* _to_nxt = _to;
3527 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3528 _Maxcode_, _Mode_);
3529 frm_nxt = frm + (_frm_nxt - _frm);
3530 to_nxt = to + (_to_nxt - _to);
3531 return r;
3532}
3533
3534__codecvt_utf16<char16_t, false>::result
3535__codecvt_utf16<char16_t, false>::do_in(state_type&,
3536 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3537 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3538{
3539 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3540 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3541 const uint8_t* _frm_nxt = _frm;
3542 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3543 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3544 uint16_t* _to_nxt = _to;
3545 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3546 _Maxcode_, _Mode_);
3547 frm_nxt = frm + (_frm_nxt - _frm);
3548 to_nxt = to + (_to_nxt - _to);
3549 return r;
3550}
3551
3552__codecvt_utf16<char16_t, false>::result
3553__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3554 extern_type* to, extern_type*, extern_type*& to_nxt) const
3555{
3556 to_nxt = to;
3557 return noconv;
3558}
3559
3560int
Howard Hinnantc9834542011-05-31 15:34:58 +00003561__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003562{
3563 return 0;
3564}
3565
3566bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003567__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003568{
3569 return false;
3570}
3571
3572int
3573__codecvt_utf16<char16_t, false>::do_length(state_type&,
3574 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3575{
3576 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3577 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3578 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3579}
3580
3581int
Howard Hinnantc9834542011-05-31 15:34:58 +00003582__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003583{
3584 if (_Mode_ & consume_header)
3585 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003586 return 2;
3587}
3588
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003589// __codecvt_utf16<char16_t, true>
3590
3591__codecvt_utf16<char16_t, true>::result
3592__codecvt_utf16<char16_t, true>::do_out(state_type&,
3593 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3594 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3595{
3596 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3597 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3598 const uint16_t* _frm_nxt = _frm;
3599 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3600 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3601 uint8_t* _to_nxt = _to;
3602 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3603 _Maxcode_, _Mode_);
3604 frm_nxt = frm + (_frm_nxt - _frm);
3605 to_nxt = to + (_to_nxt - _to);
3606 return r;
3607}
3608
3609__codecvt_utf16<char16_t, true>::result
3610__codecvt_utf16<char16_t, true>::do_in(state_type&,
3611 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3612 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3613{
3614 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3615 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3616 const uint8_t* _frm_nxt = _frm;
3617 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3618 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3619 uint16_t* _to_nxt = _to;
3620 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3621 _Maxcode_, _Mode_);
3622 frm_nxt = frm + (_frm_nxt - _frm);
3623 to_nxt = to + (_to_nxt - _to);
3624 return r;
3625}
3626
3627__codecvt_utf16<char16_t, true>::result
3628__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3629 extern_type* to, extern_type*, extern_type*& to_nxt) const
3630{
3631 to_nxt = to;
3632 return noconv;
3633}
3634
3635int
Howard Hinnantc9834542011-05-31 15:34:58 +00003636__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003637{
3638 return 0;
3639}
3640
3641bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003642__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003643{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003644 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003645}
3646
3647int
3648__codecvt_utf16<char16_t, true>::do_length(state_type&,
3649 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3650{
3651 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3652 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3653 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3654}
3655
3656int
Howard Hinnantc9834542011-05-31 15:34:58 +00003657__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003658{
3659 if (_Mode_ & consume_header)
3660 return 4;
3661 return 2;
3662}
3663
3664// __codecvt_utf16<char32_t, false>
3665
3666__codecvt_utf16<char32_t, false>::result
3667__codecvt_utf16<char32_t, false>::do_out(state_type&,
3668 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3669 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3670{
3671 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3672 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3673 const uint32_t* _frm_nxt = _frm;
3674 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3675 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3676 uint8_t* _to_nxt = _to;
3677 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3678 _Maxcode_, _Mode_);
3679 frm_nxt = frm + (_frm_nxt - _frm);
3680 to_nxt = to + (_to_nxt - _to);
3681 return r;
3682}
3683
3684__codecvt_utf16<char32_t, false>::result
3685__codecvt_utf16<char32_t, false>::do_in(state_type&,
3686 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3687 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3688{
3689 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3690 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3691 const uint8_t* _frm_nxt = _frm;
3692 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3693 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3694 uint32_t* _to_nxt = _to;
3695 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3696 _Maxcode_, _Mode_);
3697 frm_nxt = frm + (_frm_nxt - _frm);
3698 to_nxt = to + (_to_nxt - _to);
3699 return r;
3700}
3701
3702__codecvt_utf16<char32_t, false>::result
3703__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3704 extern_type* to, extern_type*, extern_type*& to_nxt) const
3705{
3706 to_nxt = to;
3707 return noconv;
3708}
3709
3710int
Howard Hinnantc9834542011-05-31 15:34:58 +00003711__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003712{
3713 return 0;
3714}
3715
3716bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003717__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003718{
3719 return false;
3720}
3721
3722int
3723__codecvt_utf16<char32_t, false>::do_length(state_type&,
3724 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3725{
3726 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3727 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3728 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3729}
3730
3731int
Howard Hinnantc9834542011-05-31 15:34:58 +00003732__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003733{
3734 if (_Mode_ & consume_header)
3735 return 6;
3736 return 4;
3737}
3738
3739// __codecvt_utf16<char32_t, true>
3740
3741__codecvt_utf16<char32_t, true>::result
3742__codecvt_utf16<char32_t, true>::do_out(state_type&,
3743 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3744 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3745{
3746 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3747 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3748 const uint32_t* _frm_nxt = _frm;
3749 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3750 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3751 uint8_t* _to_nxt = _to;
3752 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3753 _Maxcode_, _Mode_);
3754 frm_nxt = frm + (_frm_nxt - _frm);
3755 to_nxt = to + (_to_nxt - _to);
3756 return r;
3757}
3758
3759__codecvt_utf16<char32_t, true>::result
3760__codecvt_utf16<char32_t, true>::do_in(state_type&,
3761 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3762 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3763{
3764 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3765 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3766 const uint8_t* _frm_nxt = _frm;
3767 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3768 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3769 uint32_t* _to_nxt = _to;
3770 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3771 _Maxcode_, _Mode_);
3772 frm_nxt = frm + (_frm_nxt - _frm);
3773 to_nxt = to + (_to_nxt - _to);
3774 return r;
3775}
3776
3777__codecvt_utf16<char32_t, true>::result
3778__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3779 extern_type* to, extern_type*, extern_type*& to_nxt) const
3780{
3781 to_nxt = to;
3782 return noconv;
3783}
3784
3785int
Howard Hinnantc9834542011-05-31 15:34:58 +00003786__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003787{
3788 return 0;
3789}
3790
3791bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003792__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003793{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003794 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003795}
3796
3797int
3798__codecvt_utf16<char32_t, true>::do_length(state_type&,
3799 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3800{
3801 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3802 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3803 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3804}
3805
3806int
Howard Hinnantc9834542011-05-31 15:34:58 +00003807__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003808{
3809 if (_Mode_ & consume_header)
3810 return 6;
3811 return 4;
3812}
3813
3814// __codecvt_utf8_utf16<wchar_t>
3815
3816__codecvt_utf8_utf16<wchar_t>::result
3817__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3818 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3819 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3820{
3821 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3822 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3823 const uint32_t* _frm_nxt = _frm;
3824 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3825 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3826 uint8_t* _to_nxt = _to;
3827 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3828 _Maxcode_, _Mode_);
3829 frm_nxt = frm + (_frm_nxt - _frm);
3830 to_nxt = to + (_to_nxt - _to);
3831 return r;
3832}
3833
3834__codecvt_utf8_utf16<wchar_t>::result
3835__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3836 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3837 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3838{
3839 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3840 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3841 const uint8_t* _frm_nxt = _frm;
3842 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3843 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3844 uint32_t* _to_nxt = _to;
3845 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3846 _Maxcode_, _Mode_);
3847 frm_nxt = frm + (_frm_nxt - _frm);
3848 to_nxt = to + (_to_nxt - _to);
3849 return r;
3850}
3851
3852__codecvt_utf8_utf16<wchar_t>::result
3853__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3854 extern_type* to, extern_type*, extern_type*& to_nxt) const
3855{
3856 to_nxt = to;
3857 return noconv;
3858}
3859
3860int
Howard Hinnantc9834542011-05-31 15:34:58 +00003861__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003862{
3863 return 0;
3864}
3865
3866bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003867__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003868{
3869 return false;
3870}
3871
3872int
3873__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3874 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3875{
3876 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3877 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3878 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3879}
3880
3881int
Howard Hinnantc9834542011-05-31 15:34:58 +00003882__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003883{
3884 if (_Mode_ & consume_header)
3885 return 7;
3886 return 4;
3887}
3888
3889// __codecvt_utf8_utf16<char16_t>
3890
3891__codecvt_utf8_utf16<char16_t>::result
3892__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3893 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3894 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3895{
3896 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3897 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3898 const uint16_t* _frm_nxt = _frm;
3899 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3900 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3901 uint8_t* _to_nxt = _to;
3902 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3903 _Maxcode_, _Mode_);
3904 frm_nxt = frm + (_frm_nxt - _frm);
3905 to_nxt = to + (_to_nxt - _to);
3906 return r;
3907}
3908
3909__codecvt_utf8_utf16<char16_t>::result
3910__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3911 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3912 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3913{
3914 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3915 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3916 const uint8_t* _frm_nxt = _frm;
3917 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3918 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3919 uint16_t* _to_nxt = _to;
3920 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3921 _Maxcode_, _Mode_);
3922 frm_nxt = frm + (_frm_nxt - _frm);
3923 to_nxt = to + (_to_nxt - _to);
3924 return r;
3925}
3926
3927__codecvt_utf8_utf16<char16_t>::result
3928__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3929 extern_type* to, extern_type*, extern_type*& to_nxt) const
3930{
3931 to_nxt = to;
3932 return noconv;
3933}
3934
3935int
Howard Hinnantc9834542011-05-31 15:34:58 +00003936__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003937{
3938 return 0;
3939}
3940
3941bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003942__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003943{
3944 return false;
3945}
3946
3947int
3948__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3949 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3950{
3951 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3952 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3953 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3954}
3955
3956int
Howard Hinnantc9834542011-05-31 15:34:58 +00003957__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003958{
3959 if (_Mode_ & consume_header)
3960 return 7;
3961 return 4;
3962}
3963
3964// __codecvt_utf8_utf16<char32_t>
3965
3966__codecvt_utf8_utf16<char32_t>::result
3967__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3968 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3969 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3970{
3971 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3972 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3973 const uint32_t* _frm_nxt = _frm;
3974 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3975 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3976 uint8_t* _to_nxt = _to;
3977 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3978 _Maxcode_, _Mode_);
3979 frm_nxt = frm + (_frm_nxt - _frm);
3980 to_nxt = to + (_to_nxt - _to);
3981 return r;
3982}
3983
3984__codecvt_utf8_utf16<char32_t>::result
3985__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3986 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3987 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3988{
3989 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3990 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3991 const uint8_t* _frm_nxt = _frm;
3992 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3993 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3994 uint32_t* _to_nxt = _to;
3995 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3996 _Maxcode_, _Mode_);
3997 frm_nxt = frm + (_frm_nxt - _frm);
3998 to_nxt = to + (_to_nxt - _to);
3999 return r;
4000}
4001
4002__codecvt_utf8_utf16<char32_t>::result
4003__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4004 extern_type* to, extern_type*, extern_type*& to_nxt) const
4005{
4006 to_nxt = to;
4007 return noconv;
4008}
4009
4010int
Howard Hinnantc9834542011-05-31 15:34:58 +00004011__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004012{
4013 return 0;
4014}
4015
4016bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004017__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004018{
4019 return false;
4020}
4021
4022int
4023__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4024 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4025{
4026 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4027 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4028 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4029}
4030
4031int
Howard Hinnantc9834542011-05-31 15:34:58 +00004032__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004033{
4034 if (_Mode_ & consume_header)
4035 return 7;
4036 return 4;
4037}
4038
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004039// __narrow_to_utf8<16>
4040
4041__narrow_to_utf8<16>::~__narrow_to_utf8()
4042{
4043}
4044
4045// __narrow_to_utf8<32>
4046
4047__narrow_to_utf8<32>::~__narrow_to_utf8()
4048{
4049}
4050
4051// __widen_from_utf8<16>
4052
4053__widen_from_utf8<16>::~__widen_from_utf8()
4054{
4055}
4056
4057// __widen_from_utf8<32>
4058
4059__widen_from_utf8<32>::~__widen_from_utf8()
4060{
4061}
4062
4063// numpunct<char> && numpunct<wchar_t>
4064
4065locale::id numpunct< char >::id;
4066locale::id numpunct<wchar_t>::id;
4067
4068numpunct<char>::numpunct(size_t refs)
4069 : locale::facet(refs),
4070 __decimal_point_('.'),
4071 __thousands_sep_(',')
4072{
4073}
4074
4075numpunct<wchar_t>::numpunct(size_t refs)
4076 : locale::facet(refs),
4077 __decimal_point_(L'.'),
4078 __thousands_sep_(L',')
4079{
4080}
4081
4082numpunct<char>::~numpunct()
4083{
4084}
4085
4086numpunct<wchar_t>::~numpunct()
4087{
4088}
4089
4090 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4091wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4092
4093 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4094wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4095
4096string numpunct< char >::do_grouping() const {return __grouping_;}
4097string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4098
4099 string numpunct< char >::do_truename() const {return "true";}
4100wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4101
4102 string numpunct< char >::do_falsename() const {return "false";}
4103wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4104
4105// numpunct_byname<char>
4106
4107numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4108 : numpunct<char>(refs)
4109{
4110 __init(nm);
4111}
4112
4113numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4114 : numpunct<char>(refs)
4115{
4116 __init(nm.c_str());
4117}
4118
4119numpunct_byname<char>::~numpunct_byname()
4120{
4121}
4122
4123void
4124numpunct_byname<char>::__init(const char* nm)
4125{
4126 if (strcmp(nm, "C") != 0)
4127 {
Sean Huntf3907e62011-07-15 05:40:33 +00004128 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004129#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004130 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004131 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4132 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004133#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004134#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004135 lconv* lc = localeconv_l(loc.get());
4136#else
4137 lconv* lc = __localeconv_l(loc.get());
4138#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004139 if (*lc->decimal_point)
4140 __decimal_point_ = *lc->decimal_point;
4141 if (*lc->thousands_sep)
4142 __thousands_sep_ = *lc->thousands_sep;
4143 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004144 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004145 }
4146}
4147
4148// numpunct_byname<wchar_t>
4149
4150numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4151 : numpunct<wchar_t>(refs)
4152{
4153 __init(nm);
4154}
4155
4156numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4157 : numpunct<wchar_t>(refs)
4158{
4159 __init(nm.c_str());
4160}
4161
4162numpunct_byname<wchar_t>::~numpunct_byname()
4163{
4164}
4165
4166void
4167numpunct_byname<wchar_t>::__init(const char* nm)
4168{
4169 if (strcmp(nm, "C") != 0)
4170 {
Sean Huntf3907e62011-07-15 05:40:33 +00004171 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004172#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004173 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004174 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4175 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004176#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004177#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004178 lconv* lc = localeconv_l(loc.get());
4179#else
4180 lconv* lc = __localeconv_l(loc.get());
4181#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004182 if (*lc->decimal_point)
4183 __decimal_point_ = *lc->decimal_point;
4184 if (*lc->thousands_sep)
4185 __thousands_sep_ = *lc->thousands_sep;
4186 __grouping_ = lc->grouping;
4187 // locallization for truename and falsename is not available
4188 }
4189}
4190
4191// num_get helpers
4192
4193int
4194__num_get_base::__get_base(ios_base& iob)
4195{
4196 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4197 if (__basefield == ios_base::oct)
4198 return 8;
4199 else if (__basefield == ios_base::hex)
4200 return 16;
4201 else if (__basefield == 0)
4202 return 0;
4203 return 10;
4204}
4205
4206const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4207
4208void
4209__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4210 ios_base::iostate& __err)
4211{
4212 if (__grouping.size() != 0)
4213 {
4214 reverse(__g, __g_end);
4215 const char* __ig = __grouping.data();
4216 const char* __eg = __ig + __grouping.size();
4217 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4218 {
4219 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4220 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004221 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004222 {
4223 __err = ios_base::failbit;
4224 return;
4225 }
4226 }
4227 if (__eg - __ig > 1)
4228 ++__ig;
4229 }
4230 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4231 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004232 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004233 __err = ios_base::failbit;
4234 }
4235 }
4236}
4237
4238void
4239__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4240 ios_base::fmtflags __flags)
4241{
4242 if (__flags & ios_base::showpos)
4243 *__fmtp++ = '+';
4244 if (__flags & ios_base::showbase)
4245 *__fmtp++ = '#';
4246 while(*__len)
4247 *__fmtp++ = *__len++;
4248 if ((__flags & ios_base::basefield) == ios_base::oct)
4249 *__fmtp = 'o';
4250 else if ((__flags & ios_base::basefield) == ios_base::hex)
4251 {
4252 if (__flags & ios_base::uppercase)
4253 *__fmtp = 'X';
4254 else
4255 *__fmtp = 'x';
4256 }
4257 else if (__signd)
4258 *__fmtp = 'd';
4259 else
4260 *__fmtp = 'u';
4261}
4262
4263bool
4264__num_put_base::__format_float(char* __fmtp, const char* __len,
4265 ios_base::fmtflags __flags)
4266{
4267 bool specify_precision = true;
4268 if (__flags & ios_base::showpos)
4269 *__fmtp++ = '+';
4270 if (__flags & ios_base::showpoint)
4271 *__fmtp++ = '#';
4272 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4273 bool uppercase = __flags & ios_base::uppercase;
4274 if (floatfield == (ios_base::fixed | ios_base::scientific))
4275 specify_precision = false;
4276 else
4277 {
4278 *__fmtp++ = '.';
4279 *__fmtp++ = '*';
4280 }
4281 while(*__len)
4282 *__fmtp++ = *__len++;
4283 if (floatfield == ios_base::fixed)
4284 {
4285 if (uppercase)
4286 *__fmtp = 'F';
4287 else
4288 *__fmtp = 'f';
4289 }
4290 else if (floatfield == ios_base::scientific)
4291 {
4292 if (uppercase)
4293 *__fmtp = 'E';
4294 else
4295 *__fmtp = 'e';
4296 }
4297 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4298 {
4299 if (uppercase)
4300 *__fmtp = 'A';
4301 else
4302 *__fmtp = 'a';
4303 }
4304 else
4305 {
4306 if (uppercase)
4307 *__fmtp = 'G';
4308 else
4309 *__fmtp = 'g';
4310 }
4311 return specify_precision;
4312}
4313
4314char*
4315__num_put_base::__identify_padding(char* __nb, char* __ne,
4316 const ios_base& __iob)
4317{
4318 switch (__iob.flags() & ios_base::adjustfield)
4319 {
4320 case ios_base::internal:
4321 if (__nb[0] == '-' || __nb[0] == '+')
4322 return __nb+1;
4323 if (__ne - __nb >= 2 && __nb[0] == '0'
4324 && (__nb[1] == 'x' || __nb[1] == 'X'))
4325 return __nb+2;
4326 break;
4327 case ios_base::left:
4328 return __ne;
4329 case ios_base::right:
4330 default:
4331 break;
4332 }
4333 return __nb;
4334}
4335
4336// time_get
4337
4338static
4339string*
4340init_weeks()
4341{
4342 static string weeks[14];
4343 weeks[0] = "Sunday";
4344 weeks[1] = "Monday";
4345 weeks[2] = "Tuesday";
4346 weeks[3] = "Wednesday";
4347 weeks[4] = "Thursday";
4348 weeks[5] = "Friday";
4349 weeks[6] = "Saturday";
4350 weeks[7] = "Sun";
4351 weeks[8] = "Mon";
4352 weeks[9] = "Tue";
4353 weeks[10] = "Wed";
4354 weeks[11] = "Thu";
4355 weeks[12] = "Fri";
4356 weeks[13] = "Sat";
4357 return weeks;
4358}
4359
4360static
4361wstring*
4362init_wweeks()
4363{
4364 static wstring weeks[14];
4365 weeks[0] = L"Sunday";
4366 weeks[1] = L"Monday";
4367 weeks[2] = L"Tuesday";
4368 weeks[3] = L"Wednesday";
4369 weeks[4] = L"Thursday";
4370 weeks[5] = L"Friday";
4371 weeks[6] = L"Saturday";
4372 weeks[7] = L"Sun";
4373 weeks[8] = L"Mon";
4374 weeks[9] = L"Tue";
4375 weeks[10] = L"Wed";
4376 weeks[11] = L"Thu";
4377 weeks[12] = L"Fri";
4378 weeks[13] = L"Sat";
4379 return weeks;
4380}
4381
4382template <>
4383const string*
4384__time_get_c_storage<char>::__weeks() const
4385{
4386 static const string* weeks = init_weeks();
4387 return weeks;
4388}
4389
4390template <>
4391const wstring*
4392__time_get_c_storage<wchar_t>::__weeks() const
4393{
4394 static const wstring* weeks = init_wweeks();
4395 return weeks;
4396}
4397
4398static
4399string*
4400init_months()
4401{
4402 static string months[24];
4403 months[0] = "January";
4404 months[1] = "February";
4405 months[2] = "March";
4406 months[3] = "April";
4407 months[4] = "May";
4408 months[5] = "June";
4409 months[6] = "July";
4410 months[7] = "August";
4411 months[8] = "September";
4412 months[9] = "October";
4413 months[10] = "November";
4414 months[11] = "December";
4415 months[12] = "Jan";
4416 months[13] = "Feb";
4417 months[14] = "Mar";
4418 months[15] = "Apr";
4419 months[16] = "May";
4420 months[17] = "Jun";
4421 months[18] = "Jul";
4422 months[19] = "Aug";
4423 months[20] = "Sep";
4424 months[21] = "Oct";
4425 months[22] = "Nov";
4426 months[23] = "Dec";
4427 return months;
4428}
4429
4430static
4431wstring*
4432init_wmonths()
4433{
4434 static wstring months[24];
4435 months[0] = L"January";
4436 months[1] = L"February";
4437 months[2] = L"March";
4438 months[3] = L"April";
4439 months[4] = L"May";
4440 months[5] = L"June";
4441 months[6] = L"July";
4442 months[7] = L"August";
4443 months[8] = L"September";
4444 months[9] = L"October";
4445 months[10] = L"November";
4446 months[11] = L"December";
4447 months[12] = L"Jan";
4448 months[13] = L"Feb";
4449 months[14] = L"Mar";
4450 months[15] = L"Apr";
4451 months[16] = L"May";
4452 months[17] = L"Jun";
4453 months[18] = L"Jul";
4454 months[19] = L"Aug";
4455 months[20] = L"Sep";
4456 months[21] = L"Oct";
4457 months[22] = L"Nov";
4458 months[23] = L"Dec";
4459 return months;
4460}
4461
4462template <>
4463const string*
4464__time_get_c_storage<char>::__months() const
4465{
4466 static const string* months = init_months();
4467 return months;
4468}
4469
4470template <>
4471const wstring*
4472__time_get_c_storage<wchar_t>::__months() const
4473{
4474 static const wstring* months = init_wmonths();
4475 return months;
4476}
4477
4478static
4479string*
4480init_am_pm()
4481{
4482 static string am_pm[24];
4483 am_pm[0] = "AM";
4484 am_pm[1] = "PM";
4485 return am_pm;
4486}
4487
4488static
4489wstring*
4490init_wam_pm()
4491{
4492 static wstring am_pm[24];
4493 am_pm[0] = L"AM";
4494 am_pm[1] = L"PM";
4495 return am_pm;
4496}
4497
4498template <>
4499const string*
4500__time_get_c_storage<char>::__am_pm() const
4501{
4502 static const string* am_pm = init_am_pm();
4503 return am_pm;
4504}
4505
4506template <>
4507const wstring*
4508__time_get_c_storage<wchar_t>::__am_pm() const
4509{
4510 static const wstring* am_pm = init_wam_pm();
4511 return am_pm;
4512}
4513
4514template <>
4515const string&
4516__time_get_c_storage<char>::__x() const
4517{
4518 static string s("%m/%d/%y");
4519 return s;
4520}
4521
4522template <>
4523const wstring&
4524__time_get_c_storage<wchar_t>::__x() const
4525{
4526 static wstring s(L"%m/%d/%y");
4527 return s;
4528}
4529
4530template <>
4531const string&
4532__time_get_c_storage<char>::__X() const
4533{
4534 static string s("%H:%M:%S");
4535 return s;
4536}
4537
4538template <>
4539const wstring&
4540__time_get_c_storage<wchar_t>::__X() const
4541{
4542 static wstring s(L"%H:%M:%S");
4543 return s;
4544}
4545
4546template <>
4547const string&
4548__time_get_c_storage<char>::__c() const
4549{
4550 static string s("%a %b %d %H:%M:%S %Y");
4551 return s;
4552}
4553
4554template <>
4555const wstring&
4556__time_get_c_storage<wchar_t>::__c() const
4557{
4558 static wstring s(L"%a %b %d %H:%M:%S %Y");
4559 return s;
4560}
4561
4562template <>
4563const string&
4564__time_get_c_storage<char>::__r() const
4565{
4566 static string s("%I:%M:%S %p");
4567 return s;
4568}
4569
4570template <>
4571const wstring&
4572__time_get_c_storage<wchar_t>::__r() const
4573{
4574 static wstring s(L"%I:%M:%S %p");
4575 return s;
4576}
4577
4578// time_get_byname
4579
4580__time_get::__time_get(const char* nm)
4581 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4582{
Howard Hinnantd4444702010-08-11 17:04:31 +00004583#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004584 if (__loc_ == 0)
4585 throw runtime_error("time_get_byname"
4586 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004587#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004588}
4589
4590__time_get::__time_get(const string& nm)
4591 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4592{
Howard Hinnantd4444702010-08-11 17:04:31 +00004593#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004594 if (__loc_ == 0)
4595 throw runtime_error("time_get_byname"
4596 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004597#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004598}
4599
4600__time_get::~__time_get()
4601{
4602 freelocale(__loc_);
4603}
4604
Howard Hinnant335b1512012-02-20 16:51:43 +00004605#pragma clang diagnostic ignored "-Wmissing-field-initializers"
4606
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004607template <>
4608string
4609__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4610{
Howard Hinnant5f767b72012-12-27 23:24:31 +00004611#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
4612#pragma GCC diagnostic push
Howard Hinnant3074a052012-02-19 14:55:32 +00004613 tm t = {0};
Howard Hinnant5f767b72012-12-27 23:24:31 +00004614#pragma GCC diagnostic pop
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004615 t.tm_sec = 59;
4616 t.tm_min = 55;
4617 t.tm_hour = 23;
4618 t.tm_mday = 31;
4619 t.tm_mon = 11;
4620 t.tm_year = 161;
4621 t.tm_wday = 6;
4622 t.tm_yday = 364;
4623 t.tm_isdst = -1;
4624 char buf[100];
4625 char f[3] = {0};
4626 f[0] = '%';
4627 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004628 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004629 char* bb = buf;
4630 char* be = buf + n;
4631 string result;
4632 while (bb != be)
4633 {
4634 if (ct.is(ctype_base::space, *bb))
4635 {
4636 result.push_back(' ');
4637 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4638 ;
4639 continue;
4640 }
4641 char* w = bb;
4642 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004643 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004644 ct, err, false)
4645 - this->__weeks_;
4646 if (i < 14)
4647 {
4648 result.push_back('%');
4649 if (i < 7)
4650 result.push_back('A');
4651 else
4652 result.push_back('a');
4653 bb = w;
4654 continue;
4655 }
4656 w = bb;
4657 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4658 ct, err, false)
4659 - this->__months_;
4660 if (i < 24)
4661 {
4662 result.push_back('%');
4663 if (i < 12)
4664 result.push_back('B');
4665 else
4666 result.push_back('b');
4667 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4668 result.back() = 'm';
4669 bb = w;
4670 continue;
4671 }
4672 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4673 {
4674 w = bb;
4675 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4676 ct, err, false) - this->__am_pm_;
4677 if (i < 2)
4678 {
4679 result.push_back('%');
4680 result.push_back('p');
4681 bb = w;
4682 continue;
4683 }
4684 }
4685 w = bb;
4686 if (ct.is(ctype_base::digit, *bb))
4687 {
4688 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4689 {
4690 case 6:
4691 result.push_back('%');
4692 result.push_back('w');
4693 break;
4694 case 7:
4695 result.push_back('%');
4696 result.push_back('u');
4697 break;
4698 case 11:
4699 result.push_back('%');
4700 result.push_back('I');
4701 break;
4702 case 12:
4703 result.push_back('%');
4704 result.push_back('m');
4705 break;
4706 case 23:
4707 result.push_back('%');
4708 result.push_back('H');
4709 break;
4710 case 31:
4711 result.push_back('%');
4712 result.push_back('d');
4713 break;
4714 case 55:
4715 result.push_back('%');
4716 result.push_back('M');
4717 break;
4718 case 59:
4719 result.push_back('%');
4720 result.push_back('S');
4721 break;
4722 case 61:
4723 result.push_back('%');
4724 result.push_back('y');
4725 break;
4726 case 364:
4727 result.push_back('%');
4728 result.push_back('j');
4729 break;
4730 case 2061:
4731 result.push_back('%');
4732 result.push_back('Y');
4733 break;
4734 default:
4735 for (; w != bb; ++w)
4736 result.push_back(*w);
4737 break;
4738 }
4739 continue;
4740 }
4741 if (*bb == '%')
4742 {
4743 result.push_back('%');
4744 result.push_back('%');
4745 ++bb;
4746 continue;
4747 }
4748 result.push_back(*bb);
4749 ++bb;
4750 }
4751 return result;
4752}
4753
Howard Hinnantec3773c2011-12-01 20:21:04 +00004754#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004755
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004756template <>
4757wstring
4758__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4759{
Howard Hinnant5f767b72012-12-27 23:24:31 +00004760#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
4761#pragma GCC diagnostic push
Howard Hinnant3074a052012-02-19 14:55:32 +00004762 tm t = {0};
Howard Hinnant5f767b72012-12-27 23:24:31 +00004763#pragma GCC diagnositc pop
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004764 t.tm_sec = 59;
4765 t.tm_min = 55;
4766 t.tm_hour = 23;
4767 t.tm_mday = 31;
4768 t.tm_mon = 11;
4769 t.tm_year = 161;
4770 t.tm_wday = 6;
4771 t.tm_yday = 364;
4772 t.tm_isdst = -1;
4773 char buf[100];
4774 char f[3] = {0};
4775 f[0] = '%';
4776 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004777 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004778 wchar_t wbuf[100];
4779 wchar_t* wbb = wbuf;
4780 mbstate_t mb = {0};
4781 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004782#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004783 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004784#else
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#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004787 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004788 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004789 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004790 wstring result;
4791 while (wbb != wbe)
4792 {
4793 if (ct.is(ctype_base::space, *wbb))
4794 {
4795 result.push_back(L' ');
4796 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4797 ;
4798 continue;
4799 }
4800 wchar_t* w = wbb;
4801 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004802 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004803 ct, err, false)
4804 - this->__weeks_;
4805 if (i < 14)
4806 {
4807 result.push_back(L'%');
4808 if (i < 7)
4809 result.push_back(L'A');
4810 else
4811 result.push_back(L'a');
4812 wbb = w;
4813 continue;
4814 }
4815 w = wbb;
4816 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4817 ct, err, false)
4818 - this->__months_;
4819 if (i < 24)
4820 {
4821 result.push_back(L'%');
4822 if (i < 12)
4823 result.push_back(L'B');
4824 else
4825 result.push_back(L'b');
4826 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4827 result.back() = L'm';
4828 wbb = w;
4829 continue;
4830 }
4831 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4832 {
4833 w = wbb;
4834 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4835 ct, err, false) - this->__am_pm_;
4836 if (i < 2)
4837 {
4838 result.push_back(L'%');
4839 result.push_back(L'p');
4840 wbb = w;
4841 continue;
4842 }
4843 }
4844 w = wbb;
4845 if (ct.is(ctype_base::digit, *wbb))
4846 {
4847 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4848 {
4849 case 6:
4850 result.push_back(L'%');
4851 result.push_back(L'w');
4852 break;
4853 case 7:
4854 result.push_back(L'%');
4855 result.push_back(L'u');
4856 break;
4857 case 11:
4858 result.push_back(L'%');
4859 result.push_back(L'I');
4860 break;
4861 case 12:
4862 result.push_back(L'%');
4863 result.push_back(L'm');
4864 break;
4865 case 23:
4866 result.push_back(L'%');
4867 result.push_back(L'H');
4868 break;
4869 case 31:
4870 result.push_back(L'%');
4871 result.push_back(L'd');
4872 break;
4873 case 55:
4874 result.push_back(L'%');
4875 result.push_back(L'M');
4876 break;
4877 case 59:
4878 result.push_back(L'%');
4879 result.push_back(L'S');
4880 break;
4881 case 61:
4882 result.push_back(L'%');
4883 result.push_back(L'y');
4884 break;
4885 case 364:
4886 result.push_back(L'%');
4887 result.push_back(L'j');
4888 break;
4889 case 2061:
4890 result.push_back(L'%');
4891 result.push_back(L'Y');
4892 break;
4893 default:
4894 for (; w != wbb; ++w)
4895 result.push_back(*w);
4896 break;
4897 }
4898 continue;
4899 }
4900 if (ct.narrow(*wbb, 0) == '%')
4901 {
4902 result.push_back(L'%');
4903 result.push_back(L'%');
4904 ++wbb;
4905 continue;
4906 }
4907 result.push_back(*wbb);
4908 ++wbb;
4909 }
4910 return result;
4911}
4912
4913template <>
4914void
4915__time_get_storage<char>::init(const ctype<char>& ct)
4916{
Howard Hinnant5f767b72012-12-27 23:24:31 +00004917#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
4918#pragma GCC diagnostic push
Howard Hinnantcd992362012-08-02 18:44:17 +00004919 tm t = {0};
Howard Hinnant5f767b72012-12-27 23:24:31 +00004920#pragma GCC diagnostic pop
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004921 char buf[100];
4922 // __weeks_
4923 for (int i = 0; i < 7; ++i)
4924 {
4925 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004926 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004927 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004928 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004929 __weeks_[i+7] = buf;
4930 }
4931 // __months_
4932 for (int i = 0; i < 12; ++i)
4933 {
4934 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004935 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004936 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004937 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004938 __months_[i+12] = buf;
4939 }
4940 // __am_pm_
4941 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004942 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004943 __am_pm_[0] = buf;
4944 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004945 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004946 __am_pm_[1] = buf;
4947 __c_ = __analyze('c', ct);
4948 __r_ = __analyze('r', ct);
4949 __x_ = __analyze('x', ct);
4950 __X_ = __analyze('X', ct);
4951}
4952
4953template <>
4954void
4955__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4956{
Howard Hinnant5f767b72012-12-27 23:24:31 +00004957#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
4958#pragma GCC diagnostic push
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004959 tm t = {0};
Howard Hinnant5f767b72012-12-27 23:24:31 +00004960#pragma GCC diagnostic pop
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004961 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004962 wchar_t wbuf[100];
4963 wchar_t* wbe;
Howard Hinnant5f767b72012-12-27 23:24:31 +00004964#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
4965#pragma GCC diagnostic push
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004966 mbstate_t mb = {0};
Howard Hinnant5f767b72012-12-27 23:24:31 +00004967#pragma GCC diagnostic pop
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004968 // __weeks_
4969 for (int i = 0; i < 7; ++i)
4970 {
4971 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004972 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004973 mb = mbstate_t();
4974 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004975#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004976 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004977#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004978 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004979#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004980 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004981 __throw_runtime_error("locale not supported");
4982 wbe = wbuf + j;
4983 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004984 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004985 mb = mbstate_t();
4986 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004987#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004988 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004989#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004990 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004991#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004992 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004993 __throw_runtime_error("locale not supported");
4994 wbe = wbuf + j;
4995 __weeks_[i+7].assign(wbuf, wbe);
4996 }
4997 // __months_
4998 for (int i = 0; i < 12; ++i)
4999 {
5000 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005001 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005002 mb = mbstate_t();
5003 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005004#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005005 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005006#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005007 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005008#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005009 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005010 __throw_runtime_error("locale not supported");
5011 wbe = wbuf + j;
5012 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005013 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005014 mb = mbstate_t();
5015 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005016#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005017 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005018#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005019 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005020#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005021 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005022 __throw_runtime_error("locale not supported");
5023 wbe = wbuf + j;
5024 __months_[i+12].assign(wbuf, wbe);
5025 }
5026 // __am_pm_
5027 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005028 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005029 mb = mbstate_t();
5030 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005031#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005032 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005033#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005034 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005035#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005036 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005037 __throw_runtime_error("locale not supported");
5038 wbe = wbuf + j;
5039 __am_pm_[0].assign(wbuf, wbe);
5040 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005041 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005042 mb = mbstate_t();
5043 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005044#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005045 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005046#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005047 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005048#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005049 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005050 __throw_runtime_error("locale not supported");
5051 wbe = wbuf + j;
5052 __am_pm_[1].assign(wbuf, wbe);
5053 __c_ = __analyze('c', ct);
5054 __r_ = __analyze('r', ct);
5055 __x_ = __analyze('x', ct);
5056 __X_ = __analyze('X', ct);
5057}
5058
5059template <class CharT>
5060struct _LIBCPP_HIDDEN __time_get_temp
5061 : public ctype_byname<CharT>
5062{
5063 explicit __time_get_temp(const char* nm)
5064 : ctype_byname<CharT>(nm, 1) {}
5065 explicit __time_get_temp(const string& nm)
5066 : ctype_byname<CharT>(nm, 1) {}
5067};
5068
5069template <>
5070__time_get_storage<char>::__time_get_storage(const char* __nm)
5071 : __time_get(__nm)
5072{
5073 const __time_get_temp<char> ct(__nm);
5074 init(ct);
5075}
5076
5077template <>
5078__time_get_storage<char>::__time_get_storage(const string& __nm)
5079 : __time_get(__nm)
5080{
5081 const __time_get_temp<char> ct(__nm);
5082 init(ct);
5083}
5084
5085template <>
5086__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5087 : __time_get(__nm)
5088{
5089 const __time_get_temp<wchar_t> ct(__nm);
5090 init(ct);
5091}
5092
5093template <>
5094__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5095 : __time_get(__nm)
5096{
5097 const __time_get_temp<wchar_t> ct(__nm);
5098 init(ct);
5099}
5100
5101template <>
5102time_base::dateorder
5103__time_get_storage<char>::__do_date_order() const
5104{
5105 unsigned i;
5106 for (i = 0; i < __x_.size(); ++i)
5107 if (__x_[i] == '%')
5108 break;
5109 ++i;
5110 switch (__x_[i])
5111 {
5112 case 'y':
5113 case 'Y':
5114 for (++i; i < __x_.size(); ++i)
5115 if (__x_[i] == '%')
5116 break;
5117 if (i == __x_.size())
5118 break;
5119 ++i;
5120 switch (__x_[i])
5121 {
5122 case 'm':
5123 for (++i; i < __x_.size(); ++i)
5124 if (__x_[i] == '%')
5125 break;
5126 if (i == __x_.size())
5127 break;
5128 ++i;
5129 if (__x_[i] == 'd')
5130 return time_base::ymd;
5131 break;
5132 case 'd':
5133 for (++i; i < __x_.size(); ++i)
5134 if (__x_[i] == '%')
5135 break;
5136 if (i == __x_.size())
5137 break;
5138 ++i;
5139 if (__x_[i] == 'm')
5140 return time_base::ydm;
5141 break;
5142 }
5143 break;
5144 case 'm':
5145 for (++i; i < __x_.size(); ++i)
5146 if (__x_[i] == '%')
5147 break;
5148 if (i == __x_.size())
5149 break;
5150 ++i;
5151 if (__x_[i] == 'd')
5152 {
5153 for (++i; i < __x_.size(); ++i)
5154 if (__x_[i] == '%')
5155 break;
5156 if (i == __x_.size())
5157 break;
5158 ++i;
5159 if (__x_[i] == 'y' || __x_[i] == 'Y')
5160 return time_base::mdy;
5161 break;
5162 }
5163 break;
5164 case 'd':
5165 for (++i; i < __x_.size(); ++i)
5166 if (__x_[i] == '%')
5167 break;
5168 if (i == __x_.size())
5169 break;
5170 ++i;
5171 if (__x_[i] == 'm')
5172 {
5173 for (++i; i < __x_.size(); ++i)
5174 if (__x_[i] == '%')
5175 break;
5176 if (i == __x_.size())
5177 break;
5178 ++i;
5179 if (__x_[i] == 'y' || __x_[i] == 'Y')
5180 return time_base::dmy;
5181 break;
5182 }
5183 break;
5184 }
5185 return time_base::no_order;
5186}
5187
5188template <>
5189time_base::dateorder
5190__time_get_storage<wchar_t>::__do_date_order() const
5191{
5192 unsigned i;
5193 for (i = 0; i < __x_.size(); ++i)
5194 if (__x_[i] == L'%')
5195 break;
5196 ++i;
5197 switch (__x_[i])
5198 {
5199 case L'y':
5200 case L'Y':
5201 for (++i; i < __x_.size(); ++i)
5202 if (__x_[i] == L'%')
5203 break;
5204 if (i == __x_.size())
5205 break;
5206 ++i;
5207 switch (__x_[i])
5208 {
5209 case L'm':
5210 for (++i; i < __x_.size(); ++i)
5211 if (__x_[i] == L'%')
5212 break;
5213 if (i == __x_.size())
5214 break;
5215 ++i;
5216 if (__x_[i] == L'd')
5217 return time_base::ymd;
5218 break;
5219 case L'd':
5220 for (++i; i < __x_.size(); ++i)
5221 if (__x_[i] == L'%')
5222 break;
5223 if (i == __x_.size())
5224 break;
5225 ++i;
5226 if (__x_[i] == L'm')
5227 return time_base::ydm;
5228 break;
5229 }
5230 break;
5231 case L'm':
5232 for (++i; i < __x_.size(); ++i)
5233 if (__x_[i] == L'%')
5234 break;
5235 if (i == __x_.size())
5236 break;
5237 ++i;
5238 if (__x_[i] == L'd')
5239 {
5240 for (++i; i < __x_.size(); ++i)
5241 if (__x_[i] == L'%')
5242 break;
5243 if (i == __x_.size())
5244 break;
5245 ++i;
5246 if (__x_[i] == L'y' || __x_[i] == L'Y')
5247 return time_base::mdy;
5248 break;
5249 }
5250 break;
5251 case L'd':
5252 for (++i; i < __x_.size(); ++i)
5253 if (__x_[i] == L'%')
5254 break;
5255 if (i == __x_.size())
5256 break;
5257 ++i;
5258 if (__x_[i] == L'm')
5259 {
5260 for (++i; i < __x_.size(); ++i)
5261 if (__x_[i] == L'%')
5262 break;
5263 if (i == __x_.size())
5264 break;
5265 ++i;
5266 if (__x_[i] == L'y' || __x_[i] == L'Y')
5267 return time_base::dmy;
5268 break;
5269 }
5270 break;
5271 }
5272 return time_base::no_order;
5273}
5274
5275// time_put
5276
5277__time_put::__time_put(const char* nm)
5278 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5279{
Howard Hinnantd4444702010-08-11 17:04:31 +00005280#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005281 if (__loc_ == 0)
5282 throw runtime_error("time_put_byname"
5283 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005284#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005285}
5286
5287__time_put::__time_put(const string& nm)
5288 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5289{
Howard Hinnantd4444702010-08-11 17:04:31 +00005290#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005291 if (__loc_ == 0)
5292 throw runtime_error("time_put_byname"
5293 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005294#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005295}
5296
5297__time_put::~__time_put()
5298{
5299 if (__loc_)
5300 freelocale(__loc_);
5301}
5302
5303void
5304__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5305 char __fmt, char __mod) const
5306{
5307 char fmt[] = {'%', __fmt, __mod, 0};
5308 if (__mod != 0)
5309 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005310 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005311 __ne = __nb + n;
5312}
5313
5314void
5315__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5316 char __fmt, char __mod) const
5317{
5318 char __nar[100];
5319 char* __ne = __nar + 100;
5320 __do_put(__nar, __ne, __tm, __fmt, __mod);
Howard Hinnant5f767b72012-12-27 23:24:31 +00005321#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
5322#pragma GCC diagnostic push
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005323 mbstate_t mb = {0};
Howard Hinnant5f767b72012-12-27 23:24:31 +00005324#pragma GCC diagnostic pop
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005325 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005326#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005327 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005328#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005329 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005330#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005331 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005332 __throw_runtime_error("locale not supported");
5333 __we = __wb + j;
5334}
5335
5336// moneypunct_byname
5337
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005338template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005339static
5340void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005341__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5342 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5343 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005344{
5345 const char sign = static_cast<char>(money_base::sign);
5346 const char space = static_cast<char>(money_base::space);
5347 const char none = static_cast<char>(money_base::none);
5348 const char symbol = static_cast<char>(money_base::symbol);
5349 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005350 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5351
5352 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5353 // function'. "Space between sign and symbol or value" means that
5354 // if the sign is adjacent to the symbol, there's a space between
5355 // them, and otherwise there's a space between the sign and value.
5356 //
5357 // C11's localeconv specifies that the fourth character of an
5358 // international curr_symbol is used to separate the sign and
5359 // value when sep_by_space says to do so. C++ can't represent
5360 // that, so we just use a space. When sep_by_space says to
5361 // separate the symbol and value-or-sign with a space, we rearrange the
5362 // curr_symbol to put its spacing character on the correct side of
5363 // the symbol.
5364 //
5365 // We also need to avoid adding an extra space between the sign
5366 // and value when the currency symbol is suppressed (by not
5367 // setting showbase). We match glibc's strfmon by interpreting
5368 // sep_by_space==1 as "omit the space when the currency symbol is
5369 // absent".
5370 //
5371 // Users who want to get this right should use ICU instead.
5372
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005373 switch (cs_precedes)
5374 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005375 case 0: // value before curr_symbol
5376 if (symbol_contains_sep) {
5377 // Move the separator to before the symbol, to place it
5378 // between the value and symbol.
5379 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5380 __curr_symbol_.end());
5381 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005382 switch (sign_posn)
5383 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005384 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005385 pat.field[0] = sign;
5386 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005387 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005388 pat.field[3] = symbol;
5389 switch (sep_by_space)
5390 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005391 case 0: // No space separates the currency symbol and value.
5392 // This case may have changed between C99 and C11;
5393 // assume the currency symbol matches the intention.
5394 case 2: // Space between sign and currency or value.
5395 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005396 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005397 case 1: // Space between currency-and-sign or currency and value.
5398 if (!symbol_contains_sep) {
5399 // We insert the space into the symbol instead of
5400 // setting pat.field[2]=space so that when
5401 // showbase is not set, the space goes away too.
5402 __curr_symbol_.insert(0, 1, space_char);
5403 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005404 return;
5405 default:
5406 break;
5407 }
5408 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005409 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005410 pat.field[0] = sign;
5411 pat.field[3] = symbol;
5412 switch (sep_by_space)
5413 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005414 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005415 pat.field[1] = value;
5416 pat.field[2] = none;
5417 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005418 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005419 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005420 pat.field[2] = none;
5421 if (!symbol_contains_sep) {
5422 // We insert the space into the symbol instead of
5423 // setting pat.field[2]=space so that when
5424 // showbase is not set, the space goes away too.
5425 __curr_symbol_.insert(0, 1, space_char);
5426 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005427 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005428 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005429 pat.field[1] = space;
5430 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005431 if (symbol_contains_sep) {
5432 // Remove the separator from the symbol, since it
5433 // has already appeared after the sign.
5434 __curr_symbol_.erase(__curr_symbol_.begin());
5435 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005436 return;
5437 default:
5438 break;
5439 }
5440 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005441 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005442 pat.field[0] = value;
5443 pat.field[3] = sign;
5444 switch (sep_by_space)
5445 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005446 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005447 pat.field[1] = none;
5448 pat.field[2] = symbol;
5449 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005450 case 1: // Space between currency-and-sign or currency and value.
5451 if (!symbol_contains_sep) {
5452 // We insert the space into the symbol instead of
5453 // setting pat.field[1]=space so that when
5454 // showbase is not set, the space goes away too.
5455 __curr_symbol_.insert(0, 1, space_char);
5456 }
5457 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005458 pat.field[2] = symbol;
5459 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005460 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005461 pat.field[1] = symbol;
5462 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005463 if (symbol_contains_sep) {
5464 // Remove the separator from the symbol, since it
5465 // should not be removed if showbase is absent.
5466 __curr_symbol_.erase(__curr_symbol_.begin());
5467 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005468 return;
5469 default:
5470 break;
5471 }
5472 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005473 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005474 pat.field[0] = value;
5475 pat.field[3] = symbol;
5476 switch (sep_by_space)
5477 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005478 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005479 pat.field[1] = none;
5480 pat.field[2] = sign;
5481 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005482 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005483 pat.field[1] = space;
5484 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005485 if (symbol_contains_sep) {
5486 // Remove the separator from the symbol, since it
5487 // has already appeared before the sign.
5488 __curr_symbol_.erase(__curr_symbol_.begin());
5489 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005490 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005491 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005492 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005493 pat.field[2] = none;
5494 if (!symbol_contains_sep) {
5495 // We insert the space into the symbol instead of
5496 // setting pat.field[2]=space so that when
5497 // showbase is not set, the space goes away too.
5498 __curr_symbol_.insert(0, 1, space_char);
5499 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005500 return;
5501 default:
5502 break;
5503 }
5504 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005505 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005506 pat.field[0] = value;
5507 pat.field[3] = sign;
5508 switch (sep_by_space)
5509 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005510 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005511 pat.field[1] = none;
5512 pat.field[2] = symbol;
5513 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005514 case 1: // Space between currency-and-sign or currency and value.
5515 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005516 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005517 if (!symbol_contains_sep) {
5518 // We insert the space into the symbol instead of
5519 // setting pat.field[1]=space so that when
5520 // showbase is not set, the space goes away too.
5521 __curr_symbol_.insert(0, 1, space_char);
5522 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005523 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005524 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005525 pat.field[1] = symbol;
5526 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005527 if (symbol_contains_sep) {
5528 // Remove the separator from the symbol, since it
5529 // should not disappear when showbase is absent.
5530 __curr_symbol_.erase(__curr_symbol_.begin());
5531 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005532 return;
5533 default:
5534 break;
5535 }
5536 break;
5537 default:
5538 break;
5539 }
5540 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005541 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005542 switch (sign_posn)
5543 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005544 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005545 pat.field[0] = sign;
5546 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005547 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005548 pat.field[3] = value;
5549 switch (sep_by_space)
5550 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005551 case 0: // No space separates the currency symbol and value.
5552 // This case may have changed between C99 and C11;
5553 // assume the currency symbol matches the intention.
5554 case 2: // Space between sign and currency or value.
5555 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005556 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005557 case 1: // Space between currency-and-sign or currency and value.
5558 if (!symbol_contains_sep) {
5559 // We insert the space into the symbol instead of
5560 // setting pat.field[2]=space so that when
5561 // showbase is not set, the space goes away too.
5562 __curr_symbol_.insert(0, 1, space_char);
5563 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005564 return;
5565 default:
5566 break;
5567 }
5568 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005569 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005570 pat.field[0] = sign;
5571 pat.field[3] = value;
5572 switch (sep_by_space)
5573 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005574 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005575 pat.field[1] = symbol;
5576 pat.field[2] = none;
5577 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005578 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005579 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005580 pat.field[2] = none;
5581 if (!symbol_contains_sep) {
5582 // We insert the space into the symbol instead of
5583 // setting pat.field[2]=space so that when
5584 // showbase is not set, the space goes away too.
5585 __curr_symbol_.push_back(space_char);
5586 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005587 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005588 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005589 pat.field[1] = space;
5590 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005591 if (symbol_contains_sep) {
5592 // Remove the separator from the symbol, since it
5593 // has already appeared after the sign.
5594 __curr_symbol_.pop_back();
5595 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005596 return;
5597 default:
5598 break;
5599 }
5600 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005601 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005602 pat.field[0] = symbol;
5603 pat.field[3] = sign;
5604 switch (sep_by_space)
5605 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005606 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005607 pat.field[1] = none;
5608 pat.field[2] = value;
5609 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005610 case 1: // Space between currency-and-sign or currency and value.
5611 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005612 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005613 if (!symbol_contains_sep) {
5614 // We insert the space into the symbol instead of
5615 // setting pat.field[1]=space so that when
5616 // showbase is not set, the space goes away too.
5617 __curr_symbol_.push_back(space_char);
5618 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005619 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005620 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005621 pat.field[1] = value;
5622 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005623 if (symbol_contains_sep) {
5624 // Remove the separator from the symbol, since it
5625 // will appear before the sign.
5626 __curr_symbol_.pop_back();
5627 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005628 return;
5629 default:
5630 break;
5631 }
5632 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005633 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005634 pat.field[0] = sign;
5635 pat.field[3] = value;
5636 switch (sep_by_space)
5637 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005638 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005639 pat.field[1] = symbol;
5640 pat.field[2] = none;
5641 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005642 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005643 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005644 pat.field[2] = none;
5645 if (!symbol_contains_sep) {
5646 // We insert the space into the symbol instead of
5647 // setting pat.field[2]=space so that when
5648 // showbase is not set, the space goes away too.
5649 __curr_symbol_.push_back(space_char);
5650 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005651 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005652 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005653 pat.field[1] = space;
5654 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005655 if (symbol_contains_sep) {
5656 // Remove the separator from the symbol, since it
5657 // has already appeared after the sign.
5658 __curr_symbol_.pop_back();
5659 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005660 return;
5661 default:
5662 break;
5663 }
5664 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005665 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005666 pat.field[0] = symbol;
5667 pat.field[3] = value;
5668 switch (sep_by_space)
5669 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005670 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005671 pat.field[1] = sign;
5672 pat.field[2] = none;
5673 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005674 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005675 pat.field[1] = sign;
5676 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005677 if (symbol_contains_sep) {
5678 // Remove the separator from the symbol, since it
5679 // should not disappear when showbase is absent.
5680 __curr_symbol_.pop_back();
5681 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005682 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005683 case 2: // Space between sign and currency or value.
5684 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005685 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005686 if (!symbol_contains_sep) {
5687 // We insert the space into the symbol instead of
5688 // setting pat.field[1]=space so that when
5689 // showbase is not set, the space goes away too.
5690 __curr_symbol_.push_back(space_char);
5691 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005692 return;
5693 default:
5694 break;
5695 }
5696 break;
5697 default:
5698 break;
5699 }
5700 break;
5701 default:
5702 break;
5703 }
5704 pat.field[0] = symbol;
5705 pat.field[1] = sign;
5706 pat.field[2] = none;
5707 pat.field[3] = value;
5708}
5709
5710template<>
5711void
5712moneypunct_byname<char, false>::init(const char* nm)
5713{
5714 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005715 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005716#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005717 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005718 throw runtime_error("moneypunct_byname"
5719 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005720#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005721#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005722 lconv* lc = localeconv_l(loc.get());
5723#else
5724 lconv* lc = __localeconv_l(loc.get());
5725#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005726 if (*lc->mon_decimal_point)
5727 __decimal_point_ = *lc->mon_decimal_point;
5728 else
5729 __decimal_point_ = base::do_decimal_point();
5730 if (*lc->mon_thousands_sep)
5731 __thousands_sep_ = *lc->mon_thousands_sep;
5732 else
5733 __thousands_sep_ = base::do_thousands_sep();
5734 __grouping_ = lc->mon_grouping;
5735 __curr_symbol_ = lc->currency_symbol;
5736 if (lc->frac_digits != CHAR_MAX)
5737 __frac_digits_ = lc->frac_digits;
5738 else
5739 __frac_digits_ = base::do_frac_digits();
5740 if (lc->p_sign_posn == 0)
5741 __positive_sign_ = "()";
5742 else
5743 __positive_sign_ = lc->positive_sign;
5744 if (lc->n_sign_posn == 0)
5745 __negative_sign_ = "()";
5746 else
5747 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005748 // Assume the positive and negative formats will want spaces in
5749 // the same places in curr_symbol since there's no way to
5750 // represent anything else.
5751 string_type __dummy_curr_symbol = __curr_symbol_;
5752 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5753 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5754 __init_pat(__neg_format_, __curr_symbol_, false,
5755 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005756}
5757
5758template<>
5759void
5760moneypunct_byname<char, true>::init(const char* nm)
5761{
5762 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005763 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005764#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005765 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005766 throw runtime_error("moneypunct_byname"
5767 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005768#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005769#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005770 lconv* lc = localeconv_l(loc.get());
5771#else
5772 lconv* lc = __localeconv_l(loc.get());
5773#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005774 if (*lc->mon_decimal_point)
5775 __decimal_point_ = *lc->mon_decimal_point;
5776 else
5777 __decimal_point_ = base::do_decimal_point();
5778 if (*lc->mon_thousands_sep)
5779 __thousands_sep_ = *lc->mon_thousands_sep;
5780 else
5781 __thousands_sep_ = base::do_thousands_sep();
5782 __grouping_ = lc->mon_grouping;
5783 __curr_symbol_ = lc->int_curr_symbol;
5784 if (lc->int_frac_digits != CHAR_MAX)
5785 __frac_digits_ = lc->int_frac_digits;
5786 else
5787 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005788#if _WIN32
5789 if (lc->p_sign_posn == 0)
5790#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005791 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005792#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005793 __positive_sign_ = "()";
5794 else
5795 __positive_sign_ = lc->positive_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005796#if _WIN32
5797 if(lc->n_sign_posn == 0)
5798#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005799 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005800#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005801 __negative_sign_ = "()";
5802 else
5803 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005804 // Assume the positive and negative formats will want spaces in
5805 // the same places in curr_symbol since there's no way to
5806 // represent anything else.
5807 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005808#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005809 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5810 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5811 __init_pat(__neg_format_, __curr_symbol_, true,
5812 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005813#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005814 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5815 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5816 lc->int_p_sign_posn, ' ');
5817 __init_pat(__neg_format_, __curr_symbol_, true,
5818 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5819 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005820#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005821}
5822
5823template<>
5824void
5825moneypunct_byname<wchar_t, false>::init(const char* nm)
5826{
5827 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005828 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005829#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005830 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005831 throw runtime_error("moneypunct_byname"
5832 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005833#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005834#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005835 lconv* lc = localeconv_l(loc.get());
5836#else
5837 lconv* lc = __localeconv_l(loc.get());
5838#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005839 if (*lc->mon_decimal_point)
5840 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5841 else
5842 __decimal_point_ = base::do_decimal_point();
5843 if (*lc->mon_thousands_sep)
5844 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5845 else
5846 __thousands_sep_ = base::do_thousands_sep();
5847 __grouping_ = lc->mon_grouping;
5848 wchar_t wbuf[100];
Howard Hinnant5f767b72012-12-27 23:24:31 +00005849#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
5850#pragma GCC diagnostic push
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005851 mbstate_t mb = {0};
Howard Hinnant5f767b72012-12-27 23:24:31 +00005852#pragma GCC diagnostic pop
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005853 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005854#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005855 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005856#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005857 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005858#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005859 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005860 __throw_runtime_error("locale not supported");
5861 wchar_t* wbe = wbuf + j;
5862 __curr_symbol_.assign(wbuf, wbe);
5863 if (lc->frac_digits != CHAR_MAX)
5864 __frac_digits_ = lc->frac_digits;
5865 else
5866 __frac_digits_ = base::do_frac_digits();
5867 if (lc->p_sign_posn == 0)
5868 __positive_sign_ = L"()";
5869 else
5870 {
5871 mb = mbstate_t();
5872 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005873#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005874 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005875#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005876 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005877#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005878 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005879 __throw_runtime_error("locale not supported");
5880 wbe = wbuf + j;
5881 __positive_sign_.assign(wbuf, wbe);
5882 }
5883 if (lc->n_sign_posn == 0)
5884 __negative_sign_ = L"()";
5885 else
5886 {
5887 mb = mbstate_t();
5888 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005889#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005890 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005891#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005892 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005893#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005894 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005895 __throw_runtime_error("locale not supported");
5896 wbe = wbuf + j;
5897 __negative_sign_.assign(wbuf, wbe);
5898 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005899 // Assume the positive and negative formats will want spaces in
5900 // the same places in curr_symbol since there's no way to
5901 // represent anything else.
5902 string_type __dummy_curr_symbol = __curr_symbol_;
5903 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5904 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5905 __init_pat(__neg_format_, __curr_symbol_, false,
5906 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005907}
5908
5909template<>
5910void
5911moneypunct_byname<wchar_t, true>::init(const char* nm)
5912{
5913 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005914 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005915#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005916 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005917 throw runtime_error("moneypunct_byname"
5918 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005919#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005920#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005921 lconv* lc = localeconv_l(loc.get());
5922#else
5923 lconv* lc = __localeconv_l(loc.get());
5924#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005925 if (*lc->mon_decimal_point)
5926 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5927 else
5928 __decimal_point_ = base::do_decimal_point();
5929 if (*lc->mon_thousands_sep)
5930 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5931 else
5932 __thousands_sep_ = base::do_thousands_sep();
5933 __grouping_ = lc->mon_grouping;
5934 wchar_t wbuf[100];
Howard Hinnant5f767b72012-12-27 23:24:31 +00005935#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
5936#pragma GCC diagnostic push
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005937 mbstate_t mb = {0};
Howard Hinnant5f767b72012-12-27 23:24:31 +00005938#pragma GCC diagnostic pop
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005939 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005940#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005941 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005942#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005943 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005944#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005945 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005946 __throw_runtime_error("locale not supported");
5947 wchar_t* wbe = wbuf + j;
5948 __curr_symbol_.assign(wbuf, wbe);
5949 if (lc->int_frac_digits != CHAR_MAX)
5950 __frac_digits_ = lc->int_frac_digits;
5951 else
5952 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005953#if _WIN32
5954 if (lc->p_sign_posn == 0)
5955#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005956 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005957#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005958 __positive_sign_ = L"()";
5959 else
5960 {
5961 mb = mbstate_t();
5962 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005963#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005964 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005965#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005966 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005967#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005968 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005969 __throw_runtime_error("locale not supported");
5970 wbe = wbuf + j;
5971 __positive_sign_.assign(wbuf, wbe);
5972 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005973#if _WIN32
5974 if (lc->n_sign_posn == 0)
5975#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005976 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005977#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005978 __negative_sign_ = L"()";
5979 else
5980 {
5981 mb = mbstate_t();
5982 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005983#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005984 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005985#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005986 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005987#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005988 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005989 __throw_runtime_error("locale not supported");
5990 wbe = wbuf + j;
5991 __negative_sign_.assign(wbuf, wbe);
5992 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005993 // Assume the positive and negative formats will want spaces in
5994 // the same places in curr_symbol since there's no way to
5995 // represent anything else.
5996 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005997#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005998 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5999 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6000 __init_pat(__neg_format_, __curr_symbol_, true,
6001 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006002#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006003 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6004 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6005 lc->int_p_sign_posn, L' ');
6006 __init_pat(__neg_format_, __curr_symbol_, true,
6007 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6008 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006009#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006010}
6011
6012void __do_nothing(void*) {}
6013
6014void __throw_runtime_error(const char* msg)
6015{
Howard Hinnantd4444702010-08-11 17:04:31 +00006016#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006017 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00006018#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006019}
6020
6021template class collate<char>;
6022template class collate<wchar_t>;
6023
6024template class num_get<char>;
6025template class num_get<wchar_t>;
6026
Howard Hinnantec3773c2011-12-01 20:21:04 +00006027template struct __num_get<char>;
6028template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006029
6030template class num_put<char>;
6031template class num_put<wchar_t>;
6032
Howard Hinnantec3773c2011-12-01 20:21:04 +00006033template struct __num_put<char>;
6034template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006035
6036template class time_get<char>;
6037template class time_get<wchar_t>;
6038
6039template class time_get_byname<char>;
6040template class time_get_byname<wchar_t>;
6041
6042template class time_put<char>;
6043template class time_put<wchar_t>;
6044
6045template class time_put_byname<char>;
6046template class time_put_byname<wchar_t>;
6047
6048template class moneypunct<char, false>;
6049template class moneypunct<char, true>;
6050template class moneypunct<wchar_t, false>;
6051template class moneypunct<wchar_t, true>;
6052
6053template class moneypunct_byname<char, false>;
6054template class moneypunct_byname<char, true>;
6055template class moneypunct_byname<wchar_t, false>;
6056template class moneypunct_byname<wchar_t, true>;
6057
6058template class money_get<char>;
6059template class money_get<wchar_t>;
6060
6061template class __money_get<char>;
6062template class __money_get<wchar_t>;
6063
6064template class money_put<char>;
6065template class money_put<wchar_t>;
6066
6067template class __money_put<char>;
6068template class __money_put<wchar_t>;
6069
6070template class messages<char>;
6071template class messages<wchar_t>;
6072
6073template class messages_byname<char>;
6074template class messages_byname<wchar_t>;
6075
6076template class codecvt_byname<char, char, mbstate_t>;
6077template class codecvt_byname<wchar_t, char, mbstate_t>;
6078template class codecvt_byname<char16_t, char, mbstate_t>;
6079template class codecvt_byname<char32_t, char, mbstate_t>;
6080
6081template class __vector_base_common<true>;
6082
6083_LIBCPP_END_NAMESPACE_STD