blob: 214979036ccb01005230f322c6d780753662f650 [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
Marshall Clow9ae96d02013-02-07 17:20:56 +000035// On Linux, wint_t and wchar_t have different signed-ness, and this causes
36// lots of noise in the build log, but no bugs that I know of.
37#pragma clang diagnostic ignored "-Wsign-conversion"
38
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000039_LIBCPP_BEGIN_NAMESPACE_STD
40
Howard Hinnant866569b2011-09-28 23:39:33 +000041#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000042locale_t __cloc() {
43 // In theory this could create a race condition. In practice
44 // the race condition is non-fatal since it will just create
45 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000046 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
47 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000048}
Howard Hinnant866569b2011-09-28 23:39:33 +000049#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000050
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000051namespace {
52
53struct release
54{
55 void operator()(locale::facet* p) {p->__release_shared();}
56};
57
58template <class T, class A0>
59inline
60T&
61make(A0 a0)
62{
63 static typename aligned_storage<sizeof(T)>::type buf;
64 ::new (&buf) T(a0);
65 return *(T*)&buf;
66}
67
68template <class T, class A0, class A1>
69inline
70T&
71make(A0 a0, A1 a1)
72{
73 static typename aligned_storage<sizeof(T)>::type buf;
74 ::new (&buf) T(a0, a1);
75 return *(T*)&buf;
76}
77
78template <class T, class A0, class A1, class A2>
79inline
80T&
81make(A0 a0, A1 a1, A2 a2)
82{
83 static typename aligned_storage<sizeof(T)>::type buf;
84 ::new (&buf) T(a0, a1, a2);
85 return *(T*)&buf;
86}
87
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000088template <typename T, size_t N>
Howard Hinnant21772ec2012-12-28 18:15:01 +000089inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000090_LIBCPP_CONSTEXPR
91size_t
92countof(const T (&)[N])
93{
94 return N;
95}
96
97template <typename T>
Howard Hinnant21772ec2012-12-28 18:15:01 +000098inline
Howard Hinnantbf68bdc2012-12-27 21:17:53 +000099_LIBCPP_CONSTEXPR
100size_t
101countof(const T * const begin, const T * const end)
102{
103 return static_cast<size_t>(end - begin);
104}
105
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000106}
107
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000108const locale::category locale::none;
109const locale::category locale::collate;
110const locale::category locale::ctype;
111const locale::category locale::monetary;
112const locale::category locale::numeric;
113const locale::category locale::time;
114const locale::category locale::messages;
115const locale::category locale::all;
116
Howard Hinnantec3773c2011-12-01 20:21:04 +0000117#pragma clang diagnostic push
118#pragma clang diagnostic ignored "-Wpadded"
119
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000120class _LIBCPP_HIDDEN locale::__imp
121 : public facet
122{
123 enum {N = 28};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000124 vector<facet*, __sso_allocator<facet*, N> > facets_;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000125 string name_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000126public:
127 explicit __imp(size_t refs = 0);
128 explicit __imp(const string& name, size_t refs = 0);
129 __imp(const __imp&);
130 __imp(const __imp&, const string&, locale::category c);
131 __imp(const __imp& other, const __imp& one, locale::category c);
132 __imp(const __imp&, facet* f, long id);
133 ~__imp();
134
135 const string& name() const {return name_;}
Howard Hinnantec3773c2011-12-01 20:21:04 +0000136 bool has_facet(long id) const
137 {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000138 const locale::facet* use_facet(long id) const;
139
140 static const locale& make_classic();
141 static locale& make_global();
142private:
143 void install(facet* f, long id);
144 template <class F> void install(F* f) {install(f, f->id.__get());}
145 template <class F> void install_from(const __imp& other);
146};
147
Howard Hinnantec3773c2011-12-01 20:21:04 +0000148#pragma clang diagnostic pop
149
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000150locale::__imp::__imp(size_t refs)
151 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000152 facets_(N),
153 name_("C")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000154{
155 facets_.clear();
Howard Hinnantec3773c2011-12-01 20:21:04 +0000156 install(&make<_VSTD::collate<char> >(1u));
157 install(&make<_VSTD::collate<wchar_t> >(1u));
158 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
159 install(&make<_VSTD::ctype<wchar_t> >(1u));
160 install(&make<codecvt<char, char, mbstate_t> >(1u));
161 install(&make<codecvt<wchar_t, char, mbstate_t> >(1u));
162 install(&make<codecvt<char16_t, char, mbstate_t> >(1u));
163 install(&make<codecvt<char32_t, char, mbstate_t> >(1u));
164 install(&make<numpunct<char> >(1u));
165 install(&make<numpunct<wchar_t> >(1u));
166 install(&make<num_get<char> >(1u));
167 install(&make<num_get<wchar_t> >(1u));
168 install(&make<num_put<char> >(1u));
169 install(&make<num_put<wchar_t> >(1u));
170 install(&make<moneypunct<char, false> >(1u));
171 install(&make<moneypunct<char, true> >(1u));
172 install(&make<moneypunct<wchar_t, false> >(1u));
173 install(&make<moneypunct<wchar_t, true> >(1u));
174 install(&make<money_get<char> >(1u));
175 install(&make<money_get<wchar_t> >(1u));
176 install(&make<money_put<char> >(1u));
177 install(&make<money_put<wchar_t> >(1u));
178 install(&make<time_get<char> >(1u));
179 install(&make<time_get<wchar_t> >(1u));
180 install(&make<time_put<char> >(1u));
181 install(&make<time_put<wchar_t> >(1u));
182 install(&make<_VSTD::messages<char> >(1u));
183 install(&make<_VSTD::messages<wchar_t> >(1u));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000184}
185
186locale::__imp::__imp(const string& name, size_t refs)
187 : facet(refs),
Howard Hinnantec3773c2011-12-01 20:21:04 +0000188 facets_(N),
189 name_(name)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000190{
Howard Hinnantd4444702010-08-11 17:04:31 +0000191#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192 try
193 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000194#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000195 facets_ = locale::classic().__locale_->facets_;
196 for (unsigned i = 0; i < facets_.size(); ++i)
197 if (facets_[i])
198 facets_[i]->__add_shared();
199 install(new collate_byname<char>(name_));
200 install(new collate_byname<wchar_t>(name_));
201 install(new ctype_byname<char>(name_));
202 install(new ctype_byname<wchar_t>(name_));
203 install(new codecvt_byname<char, char, mbstate_t>(name_));
204 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
205 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
206 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
207 install(new numpunct_byname<char>(name_));
208 install(new numpunct_byname<wchar_t>(name_));
209 install(new moneypunct_byname<char, false>(name_));
210 install(new moneypunct_byname<char, true>(name_));
211 install(new moneypunct_byname<wchar_t, false>(name_));
212 install(new moneypunct_byname<wchar_t, true>(name_));
213 install(new time_get_byname<char>(name_));
214 install(new time_get_byname<wchar_t>(name_));
215 install(new time_put_byname<char>(name_));
216 install(new time_put_byname<wchar_t>(name_));
217 install(new messages_byname<char>(name_));
218 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000219#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000220 }
221 catch (...)
222 {
223 for (unsigned i = 0; i < facets_.size(); ++i)
224 if (facets_[i])
225 facets_[i]->__release_shared();
226 throw;
227 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000228#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000229}
230
Howard Hinnant21772ec2012-12-28 18:15:01 +0000231// NOTE avoid the `base class should be explicitly initialized in the
Howard Hinnant5f767b72012-12-27 23:24:31 +0000232// copy constructor` warning emitted by GCC
Howard Hinnant5f767b72012-12-27 23:24:31 +0000233#pragma GCC diagnostic push
Howard Hinnant21772ec2012-12-28 18:15:01 +0000234#pragma GCC diagnostic ignored "-Wextra"
Howard Hinnant5f767b72012-12-27 23:24:31 +0000235
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000236locale::__imp::__imp(const __imp& other)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000237 : facets_(max<size_t>(N, other.facets_.size())),
238 name_(other.name_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000239{
240 facets_ = other.facets_;
241 for (unsigned i = 0; i < facets_.size(); ++i)
242 if (facets_[i])
243 facets_[i]->__add_shared();
244}
245
Howard Hinnant5f767b72012-12-27 23:24:31 +0000246#pragma GCC diagnostic pop
247
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000248locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000249 : facets_(N),
250 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000251{
252 facets_ = other.facets_;
253 for (unsigned i = 0; i < facets_.size(); ++i)
254 if (facets_[i])
255 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000256#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000257 try
258 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000259#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000260 if (c & locale::collate)
261 {
262 install(new collate_byname<char>(name));
263 install(new collate_byname<wchar_t>(name));
264 }
265 if (c & locale::ctype)
266 {
267 install(new ctype_byname<char>(name));
268 install(new ctype_byname<wchar_t>(name));
269 install(new codecvt_byname<char, char, mbstate_t>(name));
270 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
271 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
272 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
273 }
274 if (c & locale::monetary)
275 {
276 install(new moneypunct_byname<char, false>(name));
277 install(new moneypunct_byname<char, true>(name));
278 install(new moneypunct_byname<wchar_t, false>(name));
279 install(new moneypunct_byname<wchar_t, true>(name));
280 }
281 if (c & locale::numeric)
282 {
283 install(new numpunct_byname<char>(name));
284 install(new numpunct_byname<wchar_t>(name));
285 }
286 if (c & locale::time)
287 {
288 install(new time_get_byname<char>(name));
289 install(new time_get_byname<wchar_t>(name));
290 install(new time_put_byname<char>(name));
291 install(new time_put_byname<wchar_t>(name));
292 }
293 if (c & locale::messages)
294 {
295 install(new messages_byname<char>(name));
296 install(new messages_byname<wchar_t>(name));
297 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000298#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000299 }
300 catch (...)
301 {
302 for (unsigned i = 0; i < facets_.size(); ++i)
303 if (facets_[i])
304 facets_[i]->__release_shared();
305 throw;
306 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000307#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000308}
309
310template<class F>
311inline
312void
313locale::__imp::install_from(const locale::__imp& one)
314{
315 long id = F::id.__get();
316 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
317}
318
319locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000320 : facets_(N),
321 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000322{
323 facets_ = other.facets_;
324 for (unsigned i = 0; i < facets_.size(); ++i)
325 if (facets_[i])
326 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000327#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000328 try
329 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000330#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000331 if (c & locale::collate)
332 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000333 install_from<_VSTD::collate<char> >(one);
334 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000335 }
336 if (c & locale::ctype)
337 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000338 install_from<_VSTD::ctype<char> >(one);
339 install_from<_VSTD::ctype<wchar_t> >(one);
340 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
341 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
342 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
343 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000344 }
345 if (c & locale::monetary)
346 {
347 install_from<moneypunct<char, false> >(one);
348 install_from<moneypunct<char, true> >(one);
349 install_from<moneypunct<wchar_t, false> >(one);
350 install_from<moneypunct<wchar_t, true> >(one);
351 install_from<money_get<char> >(one);
352 install_from<money_get<wchar_t> >(one);
353 install_from<money_put<char> >(one);
354 install_from<money_put<wchar_t> >(one);
355 }
356 if (c & locale::numeric)
357 {
358 install_from<numpunct<char> >(one);
359 install_from<numpunct<wchar_t> >(one);
360 install_from<num_get<char> >(one);
361 install_from<num_get<wchar_t> >(one);
362 install_from<num_put<char> >(one);
363 install_from<num_put<wchar_t> >(one);
364 }
365 if (c & locale::time)
366 {
367 install_from<time_get<char> >(one);
368 install_from<time_get<wchar_t> >(one);
369 install_from<time_put<char> >(one);
370 install_from<time_put<wchar_t> >(one);
371 }
372 if (c & locale::messages)
373 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000374 install_from<_VSTD::messages<char> >(one);
375 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000376 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000377#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000378 }
379 catch (...)
380 {
381 for (unsigned i = 0; i < facets_.size(); ++i)
382 if (facets_[i])
383 facets_[i]->__release_shared();
384 throw;
385 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000386#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000387}
388
389locale::__imp::__imp(const __imp& other, facet* f, long id)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000390 : facets_(max<size_t>(N, other.facets_.size()+1)),
391 name_("*")
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000392{
393 f->__add_shared();
394 unique_ptr<facet, release> hold(f);
395 facets_ = other.facets_;
396 for (unsigned i = 0; i < other.facets_.size(); ++i)
397 if (facets_[i])
398 facets_[i]->__add_shared();
399 install(hold.get(), id);
400}
401
402locale::__imp::~__imp()
403{
404 for (unsigned i = 0; i < facets_.size(); ++i)
405 if (facets_[i])
406 facets_[i]->__release_shared();
407}
408
409void
410locale::__imp::install(facet* f, long id)
411{
412 f->__add_shared();
413 unique_ptr<facet, release> hold(f);
Howard Hinnantec3773c2011-12-01 20:21:04 +0000414 if (static_cast<size_t>(id) >= facets_.size())
415 facets_.resize(static_cast<size_t>(id+1));
416 if (facets_[static_cast<size_t>(id)])
417 facets_[static_cast<size_t>(id)]->__release_shared();
418 facets_[static_cast<size_t>(id)] = hold.release();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000419}
420
421const locale::facet*
422locale::__imp::use_facet(long id) const
423{
Howard Hinnantd4444702010-08-11 17:04:31 +0000424#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000425 if (!has_facet(id))
426 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000427#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +0000428 return facets_[static_cast<size_t>(id)];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000429}
430
431// locale
432
433const locale&
434locale::__imp::make_classic()
435{
436 // only one thread can get in here and it only gets in once
437 static aligned_storage<sizeof(locale)>::type buf;
438 locale* c = (locale*)&buf;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000439 c->__locale_ = &make<__imp>(1u);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000440 return *c;
441}
442
443const locale&
444locale::classic()
445{
446 static const locale& c = __imp::make_classic();
447 return c;
448}
449
450locale&
451locale::__imp::make_global()
452{
453 // only one thread can get in here and it only gets in once
454 static aligned_storage<sizeof(locale)>::type buf;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000455 ::new (&buf) locale(locale::classic());
456 return *(locale*)&buf;
457}
458
459locale&
460locale::__global()
461{
462 static locale& g = __imp::make_global();
463 return g;
464}
465
Howard Hinnantc9834542011-05-31 15:34:58 +0000466locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000467 : __locale_(__global().__locale_)
468{
469 __locale_->__add_shared();
470}
471
Howard Hinnantc9834542011-05-31 15:34:58 +0000472locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000473 : __locale_(l.__locale_)
474{
475 __locale_->__add_shared();
476}
477
Howard Hinnantc9834542011-05-31 15:34:58 +0000478locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000479{
480 __locale_->__release_shared();
481}
482
483const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000484locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000485{
486 other.__locale_->__add_shared();
487 __locale_->__release_shared();
488 __locale_ = other.__locale_;
489 return *this;
490}
491
492locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000493#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000494 : __locale_(name ? new __imp(name)
495 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000496#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000497 : __locale_(new __imp(name))
498#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000499{
500 __locale_->__add_shared();
501}
502
503locale::locale(const string& name)
504 : __locale_(new __imp(name))
505{
506 __locale_->__add_shared();
507}
508
509locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000510#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000511 : __locale_(name ? new __imp(*other.__locale_, name, c)
512 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000513#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000514 : __locale_(new __imp(*other.__locale_, name, c))
515#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000516{
517 __locale_->__add_shared();
518}
519
520locale::locale(const locale& other, const string& name, category c)
521 : __locale_(new __imp(*other.__locale_, name, c))
522{
523 __locale_->__add_shared();
524}
525
526locale::locale(const locale& other, const locale& one, category c)
527 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
528{
529 __locale_->__add_shared();
530}
531
532string
533locale::name() const
534{
535 return __locale_->name();
536}
537
538void
539locale::__install_ctor(const locale& other, facet* f, long id)
540{
541 if (f)
542 __locale_ = new __imp(*other.__locale_, f, id);
543 else
544 __locale_ = other.__locale_;
545 __locale_->__add_shared();
546}
547
548locale
549locale::global(const locale& loc)
550{
551 locale& g = __global();
552 locale r = g;
553 g = loc;
554 if (g.name() != "*")
555 setlocale(LC_ALL, g.name().c_str());
556 return r;
557}
558
559bool
560locale::has_facet(id& x) const
561{
562 return __locale_->has_facet(x.__get());
563}
564
565const locale::facet*
566locale::use_facet(id& x) const
567{
568 return __locale_->use_facet(x.__get());
569}
570
571bool
572locale::operator==(const locale& y) const
573{
574 return (__locale_ == y.__locale_)
575 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
576}
577
578// locale::facet
579
580locale::facet::~facet()
581{
582}
583
584void
Howard Hinnant1694d232011-05-28 14:41:13 +0000585locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000586{
587 delete this;
588}
589
590// locale::id
591
592int32_t locale::id::__next_id = 0;
593
594namespace
595{
596
597class __fake_bind
598{
599 locale::id* id_;
600 void (locale::id::* pmf_)();
601public:
602 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
603 : id_(id), pmf_(pmf) {}
604
605 void operator()() const
606 {
607 (id_->*pmf_)();
608 }
609};
610
611}
612
613long
614locale::id::__get()
615{
616 call_once(__flag_, __fake_bind(&locale::id::__init, this));
617 return __id_ - 1;
618}
619
620void
621locale::id::__init()
622{
Howard Hinnantadff4892010-05-24 17:49:41 +0000623 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000624}
625
626// template <> class collate_byname<char>
627
628collate_byname<char>::collate_byname(const char* n, size_t refs)
629 : collate<char>(refs),
630 __l(newlocale(LC_ALL_MASK, n, 0))
631{
Howard Hinnantd4444702010-08-11 17:04:31 +0000632#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000633 if (__l == 0)
634 throw runtime_error("collate_byname<char>::collate_byname"
635 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000636#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000637}
638
639collate_byname<char>::collate_byname(const string& name, size_t refs)
640 : collate<char>(refs),
641 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
642{
Howard Hinnantd4444702010-08-11 17:04:31 +0000643#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000644 if (__l == 0)
645 throw runtime_error("collate_byname<char>::collate_byname"
646 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000647#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000648}
649
650collate_byname<char>::~collate_byname()
651{
652 freelocale(__l);
653}
654
655int
656collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
657 const char_type* __lo2, const char_type* __hi2) const
658{
659 string_type lhs(__lo1, __hi1);
660 string_type rhs(__lo2, __hi2);
661 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
662 if (r < 0)
663 return -1;
664 if (r > 0)
665 return 1;
666 return r;
667}
668
669collate_byname<char>::string_type
670collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
671{
672 const string_type in(lo, hi);
673 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
674 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
675 return out;
676}
677
678// template <> class collate_byname<wchar_t>
679
680collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
681 : collate<wchar_t>(refs),
682 __l(newlocale(LC_ALL_MASK, n, 0))
683{
Howard Hinnantd4444702010-08-11 17:04:31 +0000684#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000685 if (__l == 0)
686 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
687 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000688#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000689}
690
691collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
692 : collate<wchar_t>(refs),
693 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
694{
Howard Hinnantd4444702010-08-11 17:04:31 +0000695#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000696 if (__l == 0)
697 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
698 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000699#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000700}
701
702collate_byname<wchar_t>::~collate_byname()
703{
704 freelocale(__l);
705}
706
707int
708collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
709 const char_type* __lo2, const char_type* __hi2) const
710{
711 string_type lhs(__lo1, __hi1);
712 string_type rhs(__lo2, __hi2);
713 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
714 if (r < 0)
715 return -1;
716 if (r > 0)
717 return 1;
718 return r;
719}
720
721collate_byname<wchar_t>::string_type
722collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
723{
724 const string_type in(lo, hi);
725 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
726 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
727 return out;
728}
729
730// template <> class ctype<wchar_t>;
731
Howard Hinnant0a69fa12012-12-12 21:14:28 +0000732const ctype_base::mask ctype_base::space;
733const ctype_base::mask ctype_base::print;
734const ctype_base::mask ctype_base::cntrl;
735const ctype_base::mask ctype_base::upper;
736const ctype_base::mask ctype_base::lower;
737const ctype_base::mask ctype_base::alpha;
738const ctype_base::mask ctype_base::digit;
739const ctype_base::mask ctype_base::punct;
740const ctype_base::mask ctype_base::xdigit;
741const ctype_base::mask ctype_base::blank;
742const ctype_base::mask ctype_base::alnum;
743const ctype_base::mask ctype_base::graph;
744
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000745locale::id ctype<wchar_t>::id;
746
747ctype<wchar_t>::~ctype()
748{
749}
750
751bool
752ctype<wchar_t>::do_is(mask m, char_type c) const
753{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000754 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000755}
756
757const wchar_t*
758ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
759{
760 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000761 *vec = static_cast<mask>(isascii(*low) ?
762 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000763 return low;
764}
765
766const wchar_t*
767ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
768{
769 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000770 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000771 break;
772 return low;
773}
774
775const wchar_t*
776ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
777{
778 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000779 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000780 break;
781 return low;
782}
783
784wchar_t
785ctype<wchar_t>::do_toupper(char_type c) const
786{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000787#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
788 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
789#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000790 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000791#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000792 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000793#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000794}
795
796const wchar_t*
797ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
798{
799 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000800#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
801 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
802#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000803 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
804 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000805#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000806 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000807#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000808 return low;
809}
810
811wchar_t
812ctype<wchar_t>::do_tolower(char_type c) const
813{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000814#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
815 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
816#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000817 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000818#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000819 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000820#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000821}
822
823const wchar_t*
824ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
825{
826 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000827#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
828 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
829#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000830 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
831 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000832#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000833 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000834#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000835 return low;
836}
837
838wchar_t
839ctype<wchar_t>::do_widen(char c) const
840{
841 return c;
842}
843
844const char*
845ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
846{
847 for (; low != high; ++low, ++dest)
848 *dest = *low;
849 return low;
850}
851
852char
853ctype<wchar_t>::do_narrow(char_type c, char dfault) const
854{
855 if (isascii(c))
856 return static_cast<char>(c);
857 return dfault;
858}
859
860const wchar_t*
861ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
862{
863 for (; low != high; ++low, ++dest)
864 if (isascii(*low))
Howard Hinnantec3773c2011-12-01 20:21:04 +0000865 *dest = static_cast<char>(*low);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000866 else
867 *dest = dfault;
868 return low;
869}
870
871// template <> class ctype<char>;
872
873locale::id ctype<char>::id;
874
875ctype<char>::ctype(const mask* tab, bool del, size_t refs)
876 : locale::facet(refs),
877 __tab_(tab),
878 __del_(del)
879{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000880 if (__tab_ == 0)
881 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000882}
883
884ctype<char>::~ctype()
885{
886 if (__tab_ && __del_)
887 delete [] __tab_;
888}
889
890char
891ctype<char>::do_toupper(char_type c) const
892{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000893#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000894 return isascii(c) ?
895 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000896#elif defined(__GLIBC__)
Marshall Clow88c31902013-02-07 14:22:51 +0000897 return isascii(c) ?
898 static_cast<char>(__classic_upper_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000899#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000900 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000901#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000902}
903
904const char*
905ctype<char>::do_toupper(char_type* low, const char_type* high) const
906{
907 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000908#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000909 *low = isascii(*low) ?
910 static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000911#elif defined(__GLIBC__)
Marshall Clow88c31902013-02-07 14:22:51 +0000912 *low = isascii(*low) ?
913 static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000914#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000915 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000916#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000917 return low;
918}
919
920char
921ctype<char>::do_tolower(char_type c) const
922{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000923#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000924 return isascii(c) ?
925 static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000926#elif defined(__GLIBC__)
Marshall Clow88c31902013-02-07 14:22:51 +0000927 return isascii(c) ?
928 static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000929#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000930 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000931#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000932}
933
934const char*
935ctype<char>::do_tolower(char_type* low, const char_type* high) const
936{
937 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000938#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantec3773c2011-12-01 20:21:04 +0000939 *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000940#elif defined(__GLIBC__)
Marshall Clow88c31902013-02-07 14:22:51 +0000941 *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000942#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000943 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000944#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000945 return low;
946}
947
948char
949ctype<char>::do_widen(char c) const
950{
951 return c;
952}
953
954const char*
955ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
956{
957 for (; low != high; ++low, ++dest)
958 *dest = *low;
959 return low;
960}
961
962char
963ctype<char>::do_narrow(char_type c, char dfault) const
964{
965 if (isascii(c))
966 return static_cast<char>(c);
967 return dfault;
968}
969
970const char*
971ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
972{
973 for (; low != high; ++low, ++dest)
974 if (isascii(*low))
975 *dest = *low;
976 else
977 *dest = dfault;
978 return low;
979}
980
981const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000982ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000983{
David Chisnallc512df12011-09-21 08:39:44 +0000984#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000985 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000986#elif defined(__GLIBC__)
987 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +0000988#elif __sun__
989 return __ctype_mask;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000990#elif _WIN32
991 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +0000992// This is assumed to be safe, which is a nonsense assumption because we're
993// going to end up dereferencing it later...
Sean Hunt62a6ac32011-07-09 00:56:23 +0000994#else
David Chisnall997e4542012-02-29 13:05:08 +0000995 // Platform not supported: abort so the person doing the port knows what to
996 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +0000997# warning ctype<char>::classic_table() is not implemented
David Chisnall997e4542012-02-29 13:05:08 +0000998 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +0000999 return NULL;
1000#endif
1001}
1002
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001003#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001004const int*
1005ctype<char>::__classic_lower_table() _NOEXCEPT
1006{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001007 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001008}
1009
1010const int*
1011ctype<char>::__classic_upper_table() _NOEXCEPT
1012{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001013 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001014}
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001015#endif // __GLIBC__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001016
1017// template <> class ctype_byname<char>
1018
1019ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1020 : ctype<char>(0, false, refs),
1021 __l(newlocale(LC_ALL_MASK, name, 0))
1022{
Howard Hinnantd4444702010-08-11 17:04:31 +00001023#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001024 if (__l == 0)
1025 throw runtime_error("ctype_byname<char>::ctype_byname"
1026 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001027#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001028}
1029
1030ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1031 : ctype<char>(0, false, refs),
1032 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1033{
Howard Hinnantd4444702010-08-11 17:04:31 +00001034#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001035 if (__l == 0)
1036 throw runtime_error("ctype_byname<char>::ctype_byname"
1037 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001038#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001039}
1040
1041ctype_byname<char>::~ctype_byname()
1042{
1043 freelocale(__l);
1044}
1045
1046char
1047ctype_byname<char>::do_toupper(char_type c) const
1048{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001049 return static_cast<char>(toupper_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001050}
1051
1052const char*
1053ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1054{
1055 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001056 *low = static_cast<char>(toupper_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001057 return low;
1058}
1059
1060char
1061ctype_byname<char>::do_tolower(char_type c) const
1062{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001063 return static_cast<char>(tolower_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001064}
1065
1066const char*
1067ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1068{
1069 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001070 *low = static_cast<char>(tolower_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001071 return low;
1072}
1073
1074// template <> class ctype_byname<wchar_t>
1075
1076ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1077 : ctype<wchar_t>(refs),
1078 __l(newlocale(LC_ALL_MASK, name, 0))
1079{
Howard Hinnantd4444702010-08-11 17:04:31 +00001080#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001081 if (__l == 0)
1082 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1083 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001084#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001085}
1086
1087ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1088 : ctype<wchar_t>(refs),
1089 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1090{
Howard Hinnantd4444702010-08-11 17:04:31 +00001091#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001092 if (__l == 0)
1093 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1094 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001095#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001096}
1097
1098ctype_byname<wchar_t>::~ctype_byname()
1099{
1100 freelocale(__l);
1101}
1102
1103bool
1104ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1105{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001106#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001107 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001108#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001109 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001110 wint_t ch = static_cast<wint_t>(c);
1111 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1112 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1113 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1114 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1115 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1116 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1117 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1118 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1119 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1120 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001121 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001122#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001123}
1124
1125const wchar_t*
1126ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1127{
1128 for (; low != high; ++low, ++vec)
1129 {
1130 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001131 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001132 else
1133 {
1134 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001135 wint_t ch = static_cast<wint_t>(*low);
1136 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001137 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001138 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001139 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001140 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001141 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001142 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001143 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001144 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001145 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001146 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001147 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001148 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001149 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001150 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001151 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001152 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001153 *vec |= xdigit;
1154 }
1155 }
1156 return low;
1157}
1158
1159const wchar_t*
1160ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1161{
1162 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001163 {
1164#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001165 if (iswctype_l(*low, m, __l))
1166 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001167#else
Marshall Clow88c31902013-02-07 14:22:51 +00001168 wint_t ch = static_cast<wint_t>(*low);
1169 if (m & space && iswspace_l(ch, __l)) break;
1170 if (m & print && iswprint_l(ch, __l)) break;
1171 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1172 if (m & upper && iswupper_l(ch, __l)) break;
1173 if (m & lower && iswlower_l(ch, __l)) break;
1174 if (m & alpha && iswalpha_l(ch, __l)) break;
1175 if (m & digit && iswdigit_l(ch, __l)) break;
1176 if (m & punct && iswpunct_l(ch, __l)) break;
1177 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1178 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001179#endif
1180 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001181 return low;
1182}
1183
1184const wchar_t*
1185ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1186{
1187 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001188 {
1189#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001190 if (!iswctype_l(*low, m, __l))
1191 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001192#else
Marshall Clow88c31902013-02-07 14:22:51 +00001193 wint_t ch = static_cast<wint_t>(*low);
1194 if (m & space && iswspace_l(ch, __l)) continue;
1195 if (m & print && iswprint_l(ch, __l)) continue;
1196 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1197 if (m & upper && iswupper_l(ch, __l)) continue;
1198 if (m & lower && iswlower_l(ch, __l)) continue;
1199 if (m & alpha && iswalpha_l(ch, __l)) continue;
1200 if (m & digit && iswdigit_l(ch, __l)) continue;
1201 if (m & punct && iswpunct_l(ch, __l)) continue;
1202 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1203 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001204 break;
1205#endif
1206 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001207 return low;
1208}
1209
1210wchar_t
1211ctype_byname<wchar_t>::do_toupper(char_type c) const
1212{
1213 return towupper_l(c, __l);
1214}
1215
1216const wchar_t*
1217ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1218{
1219 for (; low != high; ++low)
1220 *low = towupper_l(*low, __l);
1221 return low;
1222}
1223
1224wchar_t
1225ctype_byname<wchar_t>::do_tolower(char_type c) const
1226{
1227 return towlower_l(c, __l);
1228}
1229
1230const wchar_t*
1231ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1232{
1233 for (; low != high; ++low)
1234 *low = towlower_l(*low, __l);
1235 return low;
1236}
1237
1238wchar_t
1239ctype_byname<wchar_t>::do_widen(char c) const
1240{
Howard Hinnant866569b2011-09-28 23:39:33 +00001241#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001242 return btowc_l(c, __l);
1243#else
1244 return __btowc_l(c, __l);
1245#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001246}
1247
1248const char*
1249ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1250{
1251 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001252#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001253 *dest = btowc_l(*low, __l);
1254#else
1255 *dest = __btowc_l(*low, __l);
1256#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001257 return low;
1258}
1259
1260char
1261ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1262{
Howard Hinnant866569b2011-09-28 23:39:33 +00001263#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001264 int r = wctob_l(c, __l);
1265#else
1266 int r = __wctob_l(c, __l);
1267#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001268 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001269}
1270
1271const wchar_t*
1272ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1273{
1274 for (; low != high; ++low, ++dest)
1275 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001276#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001277 int r = wctob_l(*low, __l);
1278#else
1279 int r = __wctob_l(*low, __l);
1280#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001281 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001282 }
1283 return low;
1284}
1285
1286// template <> class codecvt<char, char, mbstate_t>
1287
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001288locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001289
1290codecvt<char, char, mbstate_t>::~codecvt()
1291{
1292}
1293
1294codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001295codecvt<char, char, mbstate_t>::do_out(state_type&,
1296 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001297 extern_type* to, extern_type*, extern_type*& to_nxt) const
1298{
1299 frm_nxt = frm;
1300 to_nxt = to;
1301 return noconv;
1302}
1303
1304codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001305codecvt<char, char, mbstate_t>::do_in(state_type&,
1306 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001307 intern_type* to, intern_type*, intern_type*& to_nxt) const
1308{
1309 frm_nxt = frm;
1310 to_nxt = to;
1311 return noconv;
1312}
1313
1314codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001315codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001316 extern_type* to, extern_type*, extern_type*& to_nxt) const
1317{
1318 to_nxt = to;
1319 return noconv;
1320}
1321
1322int
Howard Hinnantc9834542011-05-31 15:34:58 +00001323codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001324{
1325 return 1;
1326}
1327
1328bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001329codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001330{
1331 return true;
1332}
1333
1334int
1335codecvt<char, char, mbstate_t>::do_length(state_type&,
1336 const extern_type* frm, const extern_type* end, size_t mx) const
1337{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001338 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001339}
1340
1341int
Howard Hinnantc9834542011-05-31 15:34:58 +00001342codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001343{
1344 return 1;
1345}
1346
1347// template <> class codecvt<wchar_t, char, mbstate_t>
1348
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001349locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001350
1351codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1352 : locale::facet(refs),
1353 __l(0)
1354{
1355}
1356
1357codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1358 : locale::facet(refs),
1359 __l(newlocale(LC_ALL_MASK, nm, 0))
1360{
Howard Hinnantd4444702010-08-11 17:04:31 +00001361#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001362 if (__l == 0)
1363 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1364 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001365#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001366}
1367
1368codecvt<wchar_t, char, mbstate_t>::~codecvt()
1369{
1370 if (__l != 0)
1371 freelocale(__l);
1372}
1373
1374codecvt<wchar_t, char, mbstate_t>::result
1375codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001376 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001377 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1378{
1379 // look for first internal null in frm
1380 const intern_type* fend = frm;
1381 for (; fend != frm_end; ++fend)
1382 if (*fend == 0)
1383 break;
1384 // loop over all null-terminated sequences in frm
1385 to_nxt = to;
1386 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1387 {
1388 // save state in case needed to reover to_nxt on error
1389 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001390#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001391 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1392 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001393#else
1394 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1395#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001396 if (n == size_t(-1))
1397 {
1398 // need to recover to_nxt
1399 for (to_nxt = to; frm != frm_nxt; ++frm)
1400 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001401#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001402 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1403#else
1404 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1405#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001406 if (n == size_t(-1))
1407 break;
1408 to_nxt += n;
1409 }
1410 frm_nxt = frm;
1411 return error;
1412 }
1413 if (n == 0)
1414 return partial;
1415 to_nxt += n;
1416 if (to_nxt == to_end)
1417 break;
1418 if (fend != frm_end) // set up next null terminated sequence
1419 {
1420 // Try to write the terminating null
1421 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001422#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001423 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1424#else
1425 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1426#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001427 if (n == size_t(-1)) // on error
1428 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001429 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001430 return partial;
1431 for (extern_type* p = tmp; n; --n) // write it
1432 *to_nxt++ = *p++;
1433 ++frm_nxt;
1434 // look for next null in frm
1435 for (fend = frm_nxt; fend != frm_end; ++fend)
1436 if (*fend == 0)
1437 break;
1438 }
1439 }
1440 return frm_nxt == frm_end ? ok : partial;
1441}
1442
1443codecvt<wchar_t, char, mbstate_t>::result
1444codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001445 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001446 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1447{
1448 // look for first internal null in frm
1449 const extern_type* fend = frm;
1450 for (; fend != frm_end; ++fend)
1451 if (*fend == 0)
1452 break;
1453 // loop over all null-terminated sequences in frm
1454 to_nxt = to;
1455 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1456 {
1457 // save state in case needed to reover to_nxt on error
1458 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001459#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001460 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1461 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001462#else
1463 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1464#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001465 if (n == size_t(-1))
1466 {
1467 // need to recover to_nxt
1468 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1469 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001470#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001471 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1472 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001473#else
1474 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1475#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001476 switch (n)
1477 {
1478 case 0:
1479 ++frm;
1480 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001481 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001482 frm_nxt = frm;
1483 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001484 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001485 frm_nxt = frm;
1486 return partial;
1487 default:
1488 frm += n;
1489 break;
1490 }
1491 }
1492 frm_nxt = frm;
1493 return frm_nxt == frm_end ? ok : partial;
1494 }
1495 if (n == 0)
1496 return error;
1497 to_nxt += n;
1498 if (to_nxt == to_end)
1499 break;
1500 if (fend != frm_end) // set up next null terminated sequence
1501 {
1502 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001503#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001504 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1505#else
1506 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1507#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001508 if (n != 0) // on error
1509 return error;
1510 ++to_nxt;
1511 ++frm_nxt;
1512 // look for next null in frm
1513 for (fend = frm_nxt; fend != frm_end; ++fend)
1514 if (*fend == 0)
1515 break;
1516 }
1517 }
1518 return frm_nxt == frm_end ? ok : partial;
1519}
1520
1521codecvt<wchar_t, char, mbstate_t>::result
1522codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1523 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1524{
1525 to_nxt = to;
1526 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001527#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001528 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1529#else
1530 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1531#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001532 if (n == size_t(-1) || n == 0) // on error
1533 return error;
1534 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001535 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001536 return partial;
1537 for (extern_type* p = tmp; n; --n) // write it
1538 *to_nxt++ = *p++;
1539 return ok;
1540}
1541
1542int
Howard Hinnantc9834542011-05-31 15:34:58 +00001543codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001544{
Howard Hinnant866569b2011-09-28 23:39:33 +00001545#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001546 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1547#else
1548 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1549#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001550 {
1551 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001552#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001553 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1554#else
1555 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1556#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001557 return 1; // which take more than 1 char to form a wchar_t
1558 return 0;
1559 }
1560 return -1;
1561}
1562
1563bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001564codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001565{
1566 return false;
1567}
1568
1569int
1570codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1571 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1572{
1573 int nbytes = 0;
1574 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1575 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001576#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001577 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001578#else
1579 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1580#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001581 switch (n)
1582 {
1583 case 0:
1584 ++nbytes;
1585 ++frm;
1586 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001587 case size_t(-1):
1588 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001589 return nbytes;
1590 default:
1591 nbytes += n;
1592 frm += n;
1593 break;
1594 }
1595 }
1596 return nbytes;
1597}
1598
1599int
Howard Hinnantc9834542011-05-31 15:34:58 +00001600codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001601{
Howard Hinnant866569b2011-09-28 23:39:33 +00001602#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001603 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001604#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001605 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001606#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001607}
1608
1609// Valid UTF ranges
1610// UTF-32 UTF-16 UTF-8 # of code points
1611// first second first second third fourth
1612// 000000 - 00007F 0000 - 007F 00 - 7F 127
1613// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1614// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1615// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1616// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1617// 00D800 - 00DFFF invalid
1618// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1619// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1620// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1621// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1622
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001623static
1624codecvt_base::result
1625utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1626 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1627 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1628{
1629 frm_nxt = frm;
1630 to_nxt = to;
1631 if (mode & generate_header)
1632 {
1633 if (to_end-to_nxt < 3)
1634 return codecvt_base::partial;
1635 *to_nxt++ = static_cast<uint8_t>(0xEF);
1636 *to_nxt++ = static_cast<uint8_t>(0xBB);
1637 *to_nxt++ = static_cast<uint8_t>(0xBF);
1638 }
1639 for (; frm_nxt < frm_end; ++frm_nxt)
1640 {
1641 uint16_t wc1 = *frm_nxt;
1642 if (wc1 > Maxcode)
1643 return codecvt_base::error;
1644 if (wc1 < 0x0080)
1645 {
1646 if (to_end-to_nxt < 1)
1647 return codecvt_base::partial;
1648 *to_nxt++ = static_cast<uint8_t>(wc1);
1649 }
1650 else if (wc1 < 0x0800)
1651 {
1652 if (to_end-to_nxt < 2)
1653 return codecvt_base::partial;
1654 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1655 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1656 }
1657 else if (wc1 < 0xD800)
1658 {
1659 if (to_end-to_nxt < 3)
1660 return codecvt_base::partial;
1661 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1662 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1663 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1664 }
1665 else if (wc1 < 0xDC00)
1666 {
1667 if (frm_end-frm_nxt < 2)
1668 return codecvt_base::partial;
1669 uint16_t wc2 = frm_nxt[1];
1670 if ((wc2 & 0xFC00) != 0xDC00)
1671 return codecvt_base::error;
1672 if (to_end-to_nxt < 4)
1673 return codecvt_base::partial;
1674 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1675 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1676 return codecvt_base::error;
1677 ++frm_nxt;
1678 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1679 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1680 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1681 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1682 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1683 }
1684 else if (wc1 < 0xE000)
1685 {
1686 return codecvt_base::error;
1687 }
1688 else
1689 {
1690 if (to_end-to_nxt < 3)
1691 return codecvt_base::partial;
1692 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1693 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1694 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1695 }
1696 }
1697 return codecvt_base::ok;
1698}
1699
1700static
1701codecvt_base::result
1702utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1703 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1704 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1705{
1706 frm_nxt = frm;
1707 to_nxt = to;
1708 if (mode & generate_header)
1709 {
1710 if (to_end-to_nxt < 3)
1711 return codecvt_base::partial;
1712 *to_nxt++ = static_cast<uint8_t>(0xEF);
1713 *to_nxt++ = static_cast<uint8_t>(0xBB);
1714 *to_nxt++ = static_cast<uint8_t>(0xBF);
1715 }
1716 for (; frm_nxt < frm_end; ++frm_nxt)
1717 {
1718 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1719 if (wc1 > Maxcode)
1720 return codecvt_base::error;
1721 if (wc1 < 0x0080)
1722 {
1723 if (to_end-to_nxt < 1)
1724 return codecvt_base::partial;
1725 *to_nxt++ = static_cast<uint8_t>(wc1);
1726 }
1727 else if (wc1 < 0x0800)
1728 {
1729 if (to_end-to_nxt < 2)
1730 return codecvt_base::partial;
1731 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1732 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1733 }
1734 else if (wc1 < 0xD800)
1735 {
1736 if (to_end-to_nxt < 3)
1737 return codecvt_base::partial;
1738 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1739 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1740 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1741 }
1742 else if (wc1 < 0xDC00)
1743 {
1744 if (frm_end-frm_nxt < 2)
1745 return codecvt_base::partial;
1746 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1747 if ((wc2 & 0xFC00) != 0xDC00)
1748 return codecvt_base::error;
1749 if (to_end-to_nxt < 4)
1750 return codecvt_base::partial;
1751 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1752 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1753 return codecvt_base::error;
1754 ++frm_nxt;
1755 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1756 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1757 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1758 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1759 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1760 }
1761 else if (wc1 < 0xE000)
1762 {
1763 return codecvt_base::error;
1764 }
1765 else
1766 {
1767 if (to_end-to_nxt < 3)
1768 return codecvt_base::partial;
1769 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1770 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1771 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1772 }
1773 }
1774 return codecvt_base::ok;
1775}
1776
1777static
1778codecvt_base::result
1779utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1780 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1781 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1782{
1783 frm_nxt = frm;
1784 to_nxt = to;
1785 if (mode & consume_header)
1786 {
1787 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1788 frm_nxt[2] == 0xBF)
1789 frm_nxt += 3;
1790 }
1791 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1792 {
1793 uint8_t c1 = *frm_nxt;
1794 if (c1 > Maxcode)
1795 return codecvt_base::error;
1796 if (c1 < 0x80)
1797 {
1798 *to_nxt = static_cast<uint16_t>(c1);
1799 ++frm_nxt;
1800 }
1801 else if (c1 < 0xC2)
1802 {
1803 return codecvt_base::error;
1804 }
1805 else if (c1 < 0xE0)
1806 {
1807 if (frm_end-frm_nxt < 2)
1808 return codecvt_base::partial;
1809 uint8_t c2 = frm_nxt[1];
1810 if ((c2 & 0xC0) != 0x80)
1811 return codecvt_base::error;
1812 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1813 if (t > Maxcode)
1814 return codecvt_base::error;
1815 *to_nxt = t;
1816 frm_nxt += 2;
1817 }
1818 else if (c1 < 0xF0)
1819 {
1820 if (frm_end-frm_nxt < 3)
1821 return codecvt_base::partial;
1822 uint8_t c2 = frm_nxt[1];
1823 uint8_t c3 = frm_nxt[2];
1824 switch (c1)
1825 {
1826 case 0xE0:
1827 if ((c2 & 0xE0) != 0xA0)
1828 return codecvt_base::error;
1829 break;
1830 case 0xED:
1831 if ((c2 & 0xE0) != 0x80)
1832 return codecvt_base::error;
1833 break;
1834 default:
1835 if ((c2 & 0xC0) != 0x80)
1836 return codecvt_base::error;
1837 break;
1838 }
1839 if ((c3 & 0xC0) != 0x80)
1840 return codecvt_base::error;
1841 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1842 | ((c2 & 0x3F) << 6)
1843 | (c3 & 0x3F));
1844 if (t > Maxcode)
1845 return codecvt_base::error;
1846 *to_nxt = t;
1847 frm_nxt += 3;
1848 }
1849 else if (c1 < 0xF5)
1850 {
1851 if (frm_end-frm_nxt < 4)
1852 return codecvt_base::partial;
1853 uint8_t c2 = frm_nxt[1];
1854 uint8_t c3 = frm_nxt[2];
1855 uint8_t c4 = frm_nxt[3];
1856 switch (c1)
1857 {
1858 case 0xF0:
1859 if (!(0x90 <= c2 && c2 <= 0xBF))
1860 return codecvt_base::error;
1861 break;
1862 case 0xF4:
1863 if ((c2 & 0xF0) != 0x80)
1864 return codecvt_base::error;
1865 break;
1866 default:
1867 if ((c2 & 0xC0) != 0x80)
1868 return codecvt_base::error;
1869 break;
1870 }
1871 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1872 return codecvt_base::error;
1873 if (to_end-to_nxt < 2)
1874 return codecvt_base::partial;
1875 if (((((unsigned long)c1 & 7) << 18) +
1876 (((unsigned long)c2 & 0x3F) << 12) +
1877 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1878 return codecvt_base::error;
1879 *to_nxt = static_cast<uint16_t>(
1880 0xD800
1881 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1882 | ((c2 & 0x0F) << 2)
1883 | ((c3 & 0x30) >> 4));
1884 *++to_nxt = static_cast<uint16_t>(
1885 0xDC00
1886 | ((c3 & 0x0F) << 6)
1887 | (c4 & 0x3F));
1888 frm_nxt += 4;
1889 }
1890 else
1891 {
1892 return codecvt_base::error;
1893 }
1894 }
1895 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1896}
1897
1898static
1899codecvt_base::result
1900utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1901 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1902 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1903{
1904 frm_nxt = frm;
1905 to_nxt = to;
1906 if (mode & consume_header)
1907 {
1908 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1909 frm_nxt[2] == 0xBF)
1910 frm_nxt += 3;
1911 }
1912 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1913 {
1914 uint8_t c1 = *frm_nxt;
1915 if (c1 > Maxcode)
1916 return codecvt_base::error;
1917 if (c1 < 0x80)
1918 {
1919 *to_nxt = static_cast<uint32_t>(c1);
1920 ++frm_nxt;
1921 }
1922 else if (c1 < 0xC2)
1923 {
1924 return codecvt_base::error;
1925 }
1926 else if (c1 < 0xE0)
1927 {
1928 if (frm_end-frm_nxt < 2)
1929 return codecvt_base::partial;
1930 uint8_t c2 = frm_nxt[1];
1931 if ((c2 & 0xC0) != 0x80)
1932 return codecvt_base::error;
1933 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1934 if (t > Maxcode)
1935 return codecvt_base::error;
1936 *to_nxt = static_cast<uint32_t>(t);
1937 frm_nxt += 2;
1938 }
1939 else if (c1 < 0xF0)
1940 {
1941 if (frm_end-frm_nxt < 3)
1942 return codecvt_base::partial;
1943 uint8_t c2 = frm_nxt[1];
1944 uint8_t c3 = frm_nxt[2];
1945 switch (c1)
1946 {
1947 case 0xE0:
1948 if ((c2 & 0xE0) != 0xA0)
1949 return codecvt_base::error;
1950 break;
1951 case 0xED:
1952 if ((c2 & 0xE0) != 0x80)
1953 return codecvt_base::error;
1954 break;
1955 default:
1956 if ((c2 & 0xC0) != 0x80)
1957 return codecvt_base::error;
1958 break;
1959 }
1960 if ((c3 & 0xC0) != 0x80)
1961 return codecvt_base::error;
1962 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1963 | ((c2 & 0x3F) << 6)
1964 | (c3 & 0x3F));
1965 if (t > Maxcode)
1966 return codecvt_base::error;
1967 *to_nxt = static_cast<uint32_t>(t);
1968 frm_nxt += 3;
1969 }
1970 else if (c1 < 0xF5)
1971 {
1972 if (frm_end-frm_nxt < 4)
1973 return codecvt_base::partial;
1974 uint8_t c2 = frm_nxt[1];
1975 uint8_t c3 = frm_nxt[2];
1976 uint8_t c4 = frm_nxt[3];
1977 switch (c1)
1978 {
1979 case 0xF0:
1980 if (!(0x90 <= c2 && c2 <= 0xBF))
1981 return codecvt_base::error;
1982 break;
1983 case 0xF4:
1984 if ((c2 & 0xF0) != 0x80)
1985 return codecvt_base::error;
1986 break;
1987 default:
1988 if ((c2 & 0xC0) != 0x80)
1989 return codecvt_base::error;
1990 break;
1991 }
1992 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1993 return codecvt_base::error;
1994 if (to_end-to_nxt < 2)
1995 return codecvt_base::partial;
1996 if (((((unsigned long)c1 & 7) << 18) +
1997 (((unsigned long)c2 & 0x3F) << 12) +
1998 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1999 return codecvt_base::error;
2000 *to_nxt = static_cast<uint32_t>(
2001 0xD800
2002 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2003 | ((c2 & 0x0F) << 2)
2004 | ((c3 & 0x30) >> 4));
2005 *++to_nxt = static_cast<uint32_t>(
2006 0xDC00
2007 | ((c3 & 0x0F) << 6)
2008 | (c4 & 0x3F));
2009 frm_nxt += 4;
2010 }
2011 else
2012 {
2013 return codecvt_base::error;
2014 }
2015 }
2016 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2017}
2018
2019static
2020int
2021utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2022 size_t mx, unsigned long Maxcode = 0x10FFFF,
2023 codecvt_mode mode = codecvt_mode(0))
2024{
2025 const uint8_t* frm_nxt = frm;
2026 if (mode & consume_header)
2027 {
2028 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2029 frm_nxt[2] == 0xBF)
2030 frm_nxt += 3;
2031 }
2032 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2033 {
2034 uint8_t c1 = *frm_nxt;
2035 if (c1 > Maxcode)
2036 break;
2037 if (c1 < 0x80)
2038 {
2039 ++frm_nxt;
2040 }
2041 else if (c1 < 0xC2)
2042 {
2043 break;
2044 }
2045 else if (c1 < 0xE0)
2046 {
2047 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2048 break;
2049 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2050 if (t > Maxcode)
2051 break;
2052 frm_nxt += 2;
2053 }
2054 else if (c1 < 0xF0)
2055 {
2056 if (frm_end-frm_nxt < 3)
2057 break;
2058 uint8_t c2 = frm_nxt[1];
2059 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002060 switch (c1)
2061 {
2062 case 0xE0:
2063 if ((c2 & 0xE0) != 0xA0)
2064 return static_cast<int>(frm_nxt - frm);
2065 break;
2066 case 0xED:
2067 if ((c2 & 0xE0) != 0x80)
2068 return static_cast<int>(frm_nxt - frm);
2069 break;
2070 default:
2071 if ((c2 & 0xC0) != 0x80)
2072 return static_cast<int>(frm_nxt - frm);
2073 break;
2074 }
2075 if ((c3 & 0xC0) != 0x80)
2076 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002077 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002078 break;
2079 frm_nxt += 3;
2080 }
2081 else if (c1 < 0xF5)
2082 {
2083 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2084 break;
2085 uint8_t c2 = frm_nxt[1];
2086 uint8_t c3 = frm_nxt[2];
2087 uint8_t c4 = frm_nxt[3];
2088 switch (c1)
2089 {
2090 case 0xF0:
2091 if (!(0x90 <= c2 && c2 <= 0xBF))
2092 return static_cast<int>(frm_nxt - frm);
2093 break;
2094 case 0xF4:
2095 if ((c2 & 0xF0) != 0x80)
2096 return static_cast<int>(frm_nxt - frm);
2097 break;
2098 default:
2099 if ((c2 & 0xC0) != 0x80)
2100 return static_cast<int>(frm_nxt - frm);
2101 break;
2102 }
2103 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2104 break;
2105 if (((((unsigned long)c1 & 7) << 18) +
2106 (((unsigned long)c2 & 0x3F) << 12) +
2107 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2108 break;
2109 ++nchar16_t;
2110 frm_nxt += 4;
2111 }
2112 else
2113 {
2114 break;
2115 }
2116 }
2117 return static_cast<int>(frm_nxt - frm);
2118}
2119
2120static
2121codecvt_base::result
2122ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2123 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2124 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2125{
2126 frm_nxt = frm;
2127 to_nxt = to;
2128 if (mode & generate_header)
2129 {
2130 if (to_end-to_nxt < 3)
2131 return codecvt_base::partial;
2132 *to_nxt++ = static_cast<uint8_t>(0xEF);
2133 *to_nxt++ = static_cast<uint8_t>(0xBB);
2134 *to_nxt++ = static_cast<uint8_t>(0xBF);
2135 }
2136 for (; frm_nxt < frm_end; ++frm_nxt)
2137 {
2138 uint32_t wc = *frm_nxt;
2139 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2140 return codecvt_base::error;
2141 if (wc < 0x000080)
2142 {
2143 if (to_end-to_nxt < 1)
2144 return codecvt_base::partial;
2145 *to_nxt++ = static_cast<uint8_t>(wc);
2146 }
2147 else if (wc < 0x000800)
2148 {
2149 if (to_end-to_nxt < 2)
2150 return codecvt_base::partial;
2151 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2152 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2153 }
2154 else if (wc < 0x010000)
2155 {
2156 if (to_end-to_nxt < 3)
2157 return codecvt_base::partial;
2158 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2159 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2160 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2161 }
2162 else // if (wc < 0x110000)
2163 {
2164 if (to_end-to_nxt < 4)
2165 return codecvt_base::partial;
2166 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2167 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2168 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2169 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2170 }
2171 }
2172 return codecvt_base::ok;
2173}
2174
2175static
2176codecvt_base::result
2177utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2178 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2179 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2180{
2181 frm_nxt = frm;
2182 to_nxt = to;
2183 if (mode & consume_header)
2184 {
2185 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2186 frm_nxt[2] == 0xBF)
2187 frm_nxt += 3;
2188 }
2189 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2190 {
2191 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2192 if (c1 < 0x80)
2193 {
2194 if (c1 > Maxcode)
2195 return codecvt_base::error;
2196 *to_nxt = static_cast<uint32_t>(c1);
2197 ++frm_nxt;
2198 }
2199 else if (c1 < 0xC2)
2200 {
2201 return codecvt_base::error;
2202 }
2203 else if (c1 < 0xE0)
2204 {
2205 if (frm_end-frm_nxt < 2)
2206 return codecvt_base::partial;
2207 uint8_t c2 = frm_nxt[1];
2208 if ((c2 & 0xC0) != 0x80)
2209 return codecvt_base::error;
2210 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2211 | (c2 & 0x3F));
2212 if (t > Maxcode)
2213 return codecvt_base::error;
2214 *to_nxt = t;
2215 frm_nxt += 2;
2216 }
2217 else if (c1 < 0xF0)
2218 {
2219 if (frm_end-frm_nxt < 3)
2220 return codecvt_base::partial;
2221 uint8_t c2 = frm_nxt[1];
2222 uint8_t c3 = frm_nxt[2];
2223 switch (c1)
2224 {
2225 case 0xE0:
2226 if ((c2 & 0xE0) != 0xA0)
2227 return codecvt_base::error;
2228 break;
2229 case 0xED:
2230 if ((c2 & 0xE0) != 0x80)
2231 return codecvt_base::error;
2232 break;
2233 default:
2234 if ((c2 & 0xC0) != 0x80)
2235 return codecvt_base::error;
2236 break;
2237 }
2238 if ((c3 & 0xC0) != 0x80)
2239 return codecvt_base::error;
2240 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2241 | ((c2 & 0x3F) << 6)
2242 | (c3 & 0x3F));
2243 if (t > Maxcode)
2244 return codecvt_base::error;
2245 *to_nxt = t;
2246 frm_nxt += 3;
2247 }
2248 else if (c1 < 0xF5)
2249 {
2250 if (frm_end-frm_nxt < 4)
2251 return codecvt_base::partial;
2252 uint8_t c2 = frm_nxt[1];
2253 uint8_t c3 = frm_nxt[2];
2254 uint8_t c4 = frm_nxt[3];
2255 switch (c1)
2256 {
2257 case 0xF0:
2258 if (!(0x90 <= c2 && c2 <= 0xBF))
2259 return codecvt_base::error;
2260 break;
2261 case 0xF4:
2262 if ((c2 & 0xF0) != 0x80)
2263 return codecvt_base::error;
2264 break;
2265 default:
2266 if ((c2 & 0xC0) != 0x80)
2267 return codecvt_base::error;
2268 break;
2269 }
2270 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2271 return codecvt_base::error;
2272 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2273 | ((c2 & 0x3F) << 12)
2274 | ((c3 & 0x3F) << 6)
2275 | (c4 & 0x3F));
2276 if (t > Maxcode)
2277 return codecvt_base::error;
2278 *to_nxt = t;
2279 frm_nxt += 4;
2280 }
2281 else
2282 {
2283 return codecvt_base::error;
2284 }
2285 }
2286 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2287}
2288
2289static
2290int
2291utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2292 size_t mx, unsigned long Maxcode = 0x10FFFF,
2293 codecvt_mode mode = codecvt_mode(0))
2294{
2295 const uint8_t* frm_nxt = frm;
2296 if (mode & consume_header)
2297 {
2298 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2299 frm_nxt[2] == 0xBF)
2300 frm_nxt += 3;
2301 }
2302 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2303 {
2304 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2305 if (c1 < 0x80)
2306 {
2307 if (c1 > Maxcode)
2308 break;
2309 ++frm_nxt;
2310 }
2311 else if (c1 < 0xC2)
2312 {
2313 break;
2314 }
2315 else if (c1 < 0xE0)
2316 {
2317 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2318 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002319 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002320 break;
2321 frm_nxt += 2;
2322 }
2323 else if (c1 < 0xF0)
2324 {
2325 if (frm_end-frm_nxt < 3)
2326 break;
2327 uint8_t c2 = frm_nxt[1];
2328 uint8_t c3 = frm_nxt[2];
2329 switch (c1)
2330 {
2331 case 0xE0:
2332 if ((c2 & 0xE0) != 0xA0)
2333 return static_cast<int>(frm_nxt - frm);
2334 break;
2335 case 0xED:
2336 if ((c2 & 0xE0) != 0x80)
2337 return static_cast<int>(frm_nxt - frm);
2338 break;
2339 default:
2340 if ((c2 & 0xC0) != 0x80)
2341 return static_cast<int>(frm_nxt - frm);
2342 break;
2343 }
2344 if ((c3 & 0xC0) != 0x80)
2345 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002346 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002347 break;
2348 frm_nxt += 3;
2349 }
2350 else if (c1 < 0xF5)
2351 {
2352 if (frm_end-frm_nxt < 4)
2353 break;
2354 uint8_t c2 = frm_nxt[1];
2355 uint8_t c3 = frm_nxt[2];
2356 uint8_t c4 = frm_nxt[3];
2357 switch (c1)
2358 {
2359 case 0xF0:
2360 if (!(0x90 <= c2 && c2 <= 0xBF))
2361 return static_cast<int>(frm_nxt - frm);
2362 break;
2363 case 0xF4:
2364 if ((c2 & 0xF0) != 0x80)
2365 return static_cast<int>(frm_nxt - frm);
2366 break;
2367 default:
2368 if ((c2 & 0xC0) != 0x80)
2369 return static_cast<int>(frm_nxt - frm);
2370 break;
2371 }
2372 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2373 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002374 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2375 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002376 break;
2377 frm_nxt += 4;
2378 }
2379 else
2380 {
2381 break;
2382 }
2383 }
2384 return static_cast<int>(frm_nxt - frm);
2385}
2386
2387static
2388codecvt_base::result
2389ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2390 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2391 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2392{
2393 frm_nxt = frm;
2394 to_nxt = to;
2395 if (mode & generate_header)
2396 {
2397 if (to_end-to_nxt < 3)
2398 return codecvt_base::partial;
2399 *to_nxt++ = static_cast<uint8_t>(0xEF);
2400 *to_nxt++ = static_cast<uint8_t>(0xBB);
2401 *to_nxt++ = static_cast<uint8_t>(0xBF);
2402 }
2403 for (; frm_nxt < frm_end; ++frm_nxt)
2404 {
2405 uint16_t wc = *frm_nxt;
2406 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2407 return codecvt_base::error;
2408 if (wc < 0x0080)
2409 {
2410 if (to_end-to_nxt < 1)
2411 return codecvt_base::partial;
2412 *to_nxt++ = static_cast<uint8_t>(wc);
2413 }
2414 else if (wc < 0x0800)
2415 {
2416 if (to_end-to_nxt < 2)
2417 return codecvt_base::partial;
2418 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2419 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2420 }
2421 else // if (wc <= 0xFFFF)
2422 {
2423 if (to_end-to_nxt < 3)
2424 return codecvt_base::partial;
2425 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2426 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2427 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2428 }
2429 }
2430 return codecvt_base::ok;
2431}
2432
2433static
2434codecvt_base::result
2435utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2436 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2437 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2438{
2439 frm_nxt = frm;
2440 to_nxt = to;
2441 if (mode & consume_header)
2442 {
2443 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2444 frm_nxt[2] == 0xBF)
2445 frm_nxt += 3;
2446 }
2447 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2448 {
2449 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2450 if (c1 < 0x80)
2451 {
2452 if (c1 > Maxcode)
2453 return codecvt_base::error;
2454 *to_nxt = static_cast<uint16_t>(c1);
2455 ++frm_nxt;
2456 }
2457 else if (c1 < 0xC2)
2458 {
2459 return codecvt_base::error;
2460 }
2461 else if (c1 < 0xE0)
2462 {
2463 if (frm_end-frm_nxt < 2)
2464 return codecvt_base::partial;
2465 uint8_t c2 = frm_nxt[1];
2466 if ((c2 & 0xC0) != 0x80)
2467 return codecvt_base::error;
2468 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2469 | (c2 & 0x3F));
2470 if (t > Maxcode)
2471 return codecvt_base::error;
2472 *to_nxt = t;
2473 frm_nxt += 2;
2474 }
2475 else if (c1 < 0xF0)
2476 {
2477 if (frm_end-frm_nxt < 3)
2478 return codecvt_base::partial;
2479 uint8_t c2 = frm_nxt[1];
2480 uint8_t c3 = frm_nxt[2];
2481 switch (c1)
2482 {
2483 case 0xE0:
2484 if ((c2 & 0xE0) != 0xA0)
2485 return codecvt_base::error;
2486 break;
2487 case 0xED:
2488 if ((c2 & 0xE0) != 0x80)
2489 return codecvt_base::error;
2490 break;
2491 default:
2492 if ((c2 & 0xC0) != 0x80)
2493 return codecvt_base::error;
2494 break;
2495 }
2496 if ((c3 & 0xC0) != 0x80)
2497 return codecvt_base::error;
2498 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2499 | ((c2 & 0x3F) << 6)
2500 | (c3 & 0x3F));
2501 if (t > Maxcode)
2502 return codecvt_base::error;
2503 *to_nxt = t;
2504 frm_nxt += 3;
2505 }
2506 else
2507 {
2508 return codecvt_base::error;
2509 }
2510 }
2511 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2512}
2513
2514static
2515int
2516utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2517 size_t mx, unsigned long Maxcode = 0x10FFFF,
2518 codecvt_mode mode = codecvt_mode(0))
2519{
2520 const uint8_t* frm_nxt = frm;
2521 if (mode & consume_header)
2522 {
2523 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2524 frm_nxt[2] == 0xBF)
2525 frm_nxt += 3;
2526 }
2527 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2528 {
2529 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2530 if (c1 < 0x80)
2531 {
2532 if (c1 > Maxcode)
2533 break;
2534 ++frm_nxt;
2535 }
2536 else if (c1 < 0xC2)
2537 {
2538 break;
2539 }
2540 else if (c1 < 0xE0)
2541 {
2542 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2543 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002544 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002545 break;
2546 frm_nxt += 2;
2547 }
2548 else if (c1 < 0xF0)
2549 {
2550 if (frm_end-frm_nxt < 3)
2551 break;
2552 uint8_t c2 = frm_nxt[1];
2553 uint8_t c3 = frm_nxt[2];
2554 switch (c1)
2555 {
2556 case 0xE0:
2557 if ((c2 & 0xE0) != 0xA0)
2558 return static_cast<int>(frm_nxt - frm);
2559 break;
2560 case 0xED:
2561 if ((c2 & 0xE0) != 0x80)
2562 return static_cast<int>(frm_nxt - frm);
2563 break;
2564 default:
2565 if ((c2 & 0xC0) != 0x80)
2566 return static_cast<int>(frm_nxt - frm);
2567 break;
2568 }
2569 if ((c3 & 0xC0) != 0x80)
2570 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002571 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002572 break;
2573 frm_nxt += 3;
2574 }
2575 else
2576 {
2577 break;
2578 }
2579 }
2580 return static_cast<int>(frm_nxt - frm);
2581}
2582
2583static
2584codecvt_base::result
2585ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2586 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2587 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2588{
2589 frm_nxt = frm;
2590 to_nxt = to;
2591 if (mode & generate_header)
2592 {
2593 if (to_end-to_nxt < 2)
2594 return codecvt_base::partial;
2595 *to_nxt++ = static_cast<uint8_t>(0xFE);
2596 *to_nxt++ = static_cast<uint8_t>(0xFF);
2597 }
2598 for (; frm_nxt < frm_end; ++frm_nxt)
2599 {
2600 uint32_t wc = *frm_nxt;
2601 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2602 return codecvt_base::error;
2603 if (wc < 0x010000)
2604 {
2605 if (to_end-to_nxt < 2)
2606 return codecvt_base::partial;
2607 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2608 *to_nxt++ = static_cast<uint8_t>(wc);
2609 }
2610 else
2611 {
2612 if (to_end-to_nxt < 4)
2613 return codecvt_base::partial;
2614 uint16_t t = static_cast<uint16_t>(
2615 0xD800
2616 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2617 | ((wc & 0x00FC00) >> 10));
2618 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2619 *to_nxt++ = static_cast<uint8_t>(t);
2620 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2621 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2622 *to_nxt++ = static_cast<uint8_t>(t);
2623 }
2624 }
2625 return codecvt_base::ok;
2626}
2627
2628static
2629codecvt_base::result
2630utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2631 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2632 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2633{
2634 frm_nxt = frm;
2635 to_nxt = to;
2636 if (mode & consume_header)
2637 {
2638 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2639 frm_nxt += 2;
2640 }
2641 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2642 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002643 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002644 if ((c1 & 0xFC00) == 0xDC00)
2645 return codecvt_base::error;
2646 if ((c1 & 0xFC00) != 0xD800)
2647 {
2648 if (c1 > Maxcode)
2649 return codecvt_base::error;
2650 *to_nxt = static_cast<uint32_t>(c1);
2651 frm_nxt += 2;
2652 }
2653 else
2654 {
2655 if (frm_end-frm_nxt < 4)
2656 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002657 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002658 if ((c2 & 0xFC00) != 0xDC00)
2659 return codecvt_base::error;
2660 uint32_t t = static_cast<uint32_t>(
2661 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2662 | ((c1 & 0x003F) << 10)
2663 | (c2 & 0x03FF));
2664 if (t > Maxcode)
2665 return codecvt_base::error;
2666 *to_nxt = t;
2667 frm_nxt += 4;
2668 }
2669 }
2670 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2671}
2672
2673static
2674int
2675utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2676 size_t mx, unsigned long Maxcode = 0x10FFFF,
2677 codecvt_mode mode = codecvt_mode(0))
2678{
2679 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002680 if (mode & consume_header)
2681 {
2682 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2683 frm_nxt += 2;
2684 }
2685 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2686 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002687 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002688 if ((c1 & 0xFC00) == 0xDC00)
2689 break;
2690 if ((c1 & 0xFC00) != 0xD800)
2691 {
2692 if (c1 > Maxcode)
2693 break;
2694 frm_nxt += 2;
2695 }
2696 else
2697 {
2698 if (frm_end-frm_nxt < 4)
2699 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002700 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002701 if ((c2 & 0xFC00) != 0xDC00)
2702 break;
2703 uint32_t t = static_cast<uint32_t>(
2704 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2705 | ((c1 & 0x003F) << 10)
2706 | (c2 & 0x03FF));
2707 if (t > Maxcode)
2708 break;
2709 frm_nxt += 4;
2710 }
2711 }
2712 return static_cast<int>(frm_nxt - frm);
2713}
2714
2715static
2716codecvt_base::result
2717ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2718 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2719 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2720{
2721 frm_nxt = frm;
2722 to_nxt = to;
2723 if (mode & generate_header)
2724 {
2725 if (to_end-to_nxt < 2)
2726 return codecvt_base::partial;
2727 *to_nxt++ = static_cast<uint8_t>(0xFF);
2728 *to_nxt++ = static_cast<uint8_t>(0xFE);
2729 }
2730 for (; frm_nxt < frm_end; ++frm_nxt)
2731 {
2732 uint32_t wc = *frm_nxt;
2733 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2734 return codecvt_base::error;
2735 if (wc < 0x010000)
2736 {
2737 if (to_end-to_nxt < 2)
2738 return codecvt_base::partial;
2739 *to_nxt++ = static_cast<uint8_t>(wc);
2740 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2741 }
2742 else
2743 {
2744 if (to_end-to_nxt < 4)
2745 return codecvt_base::partial;
2746 uint16_t t = static_cast<uint16_t>(
2747 0xD800
2748 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2749 | ((wc & 0x00FC00) >> 10));
2750 *to_nxt++ = static_cast<uint8_t>(t);
2751 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2752 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2753 *to_nxt++ = static_cast<uint8_t>(t);
2754 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2755 }
2756 }
2757 return codecvt_base::ok;
2758}
2759
2760static
2761codecvt_base::result
2762utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2763 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2764 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2765{
2766 frm_nxt = frm;
2767 to_nxt = to;
2768 if (mode & consume_header)
2769 {
2770 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2771 frm_nxt += 2;
2772 }
2773 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2774 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002775 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002776 if ((c1 & 0xFC00) == 0xDC00)
2777 return codecvt_base::error;
2778 if ((c1 & 0xFC00) != 0xD800)
2779 {
2780 if (c1 > Maxcode)
2781 return codecvt_base::error;
2782 *to_nxt = static_cast<uint32_t>(c1);
2783 frm_nxt += 2;
2784 }
2785 else
2786 {
2787 if (frm_end-frm_nxt < 4)
2788 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002789 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002790 if ((c2 & 0xFC00) != 0xDC00)
2791 return codecvt_base::error;
2792 uint32_t t = static_cast<uint32_t>(
2793 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2794 | ((c1 & 0x003F) << 10)
2795 | (c2 & 0x03FF));
2796 if (t > Maxcode)
2797 return codecvt_base::error;
2798 *to_nxt = t;
2799 frm_nxt += 4;
2800 }
2801 }
2802 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2803}
2804
2805static
2806int
2807utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2808 size_t mx, unsigned long Maxcode = 0x10FFFF,
2809 codecvt_mode mode = codecvt_mode(0))
2810{
2811 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002812 if (mode & consume_header)
2813 {
2814 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2815 frm_nxt += 2;
2816 }
2817 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2818 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002819 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002820 if ((c1 & 0xFC00) == 0xDC00)
2821 break;
2822 if ((c1 & 0xFC00) != 0xD800)
2823 {
2824 if (c1 > Maxcode)
2825 break;
2826 frm_nxt += 2;
2827 }
2828 else
2829 {
2830 if (frm_end-frm_nxt < 4)
2831 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002832 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002833 if ((c2 & 0xFC00) != 0xDC00)
2834 break;
2835 uint32_t t = static_cast<uint32_t>(
2836 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2837 | ((c1 & 0x003F) << 10)
2838 | (c2 & 0x03FF));
2839 if (t > Maxcode)
2840 break;
2841 frm_nxt += 4;
2842 }
2843 }
2844 return static_cast<int>(frm_nxt - frm);
2845}
2846
2847static
2848codecvt_base::result
2849ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2850 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2851 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2852{
2853 frm_nxt = frm;
2854 to_nxt = to;
2855 if (mode & generate_header)
2856 {
2857 if (to_end-to_nxt < 2)
2858 return codecvt_base::partial;
2859 *to_nxt++ = static_cast<uint8_t>(0xFE);
2860 *to_nxt++ = static_cast<uint8_t>(0xFF);
2861 }
2862 for (; frm_nxt < frm_end; ++frm_nxt)
2863 {
2864 uint16_t wc = *frm_nxt;
2865 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2866 return codecvt_base::error;
2867 if (to_end-to_nxt < 2)
2868 return codecvt_base::partial;
2869 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2870 *to_nxt++ = static_cast<uint8_t>(wc);
2871 }
2872 return codecvt_base::ok;
2873}
2874
2875static
2876codecvt_base::result
2877utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2878 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2879 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2880{
2881 frm_nxt = frm;
2882 to_nxt = to;
2883 if (mode & consume_header)
2884 {
2885 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2886 frm_nxt += 2;
2887 }
2888 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2889 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002890 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002891 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2892 return codecvt_base::error;
2893 *to_nxt = c1;
2894 frm_nxt += 2;
2895 }
2896 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2897}
2898
2899static
2900int
2901utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2902 size_t mx, unsigned long Maxcode = 0x10FFFF,
2903 codecvt_mode mode = codecvt_mode(0))
2904{
2905 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002906 if (mode & consume_header)
2907 {
2908 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2909 frm_nxt += 2;
2910 }
2911 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2912 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002913 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002914 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2915 break;
2916 frm_nxt += 2;
2917 }
2918 return static_cast<int>(frm_nxt - frm);
2919}
2920
2921static
2922codecvt_base::result
2923ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2924 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2925 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2926{
2927 frm_nxt = frm;
2928 to_nxt = to;
2929 if (mode & generate_header)
2930 {
2931 if (to_end-to_nxt < 2)
2932 return codecvt_base::partial;
2933 *to_nxt++ = static_cast<uint8_t>(0xFF);
2934 *to_nxt++ = static_cast<uint8_t>(0xFE);
2935 }
2936 for (; frm_nxt < frm_end; ++frm_nxt)
2937 {
2938 uint16_t wc = *frm_nxt;
2939 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2940 return codecvt_base::error;
2941 if (to_end-to_nxt < 2)
2942 return codecvt_base::partial;
2943 *to_nxt++ = static_cast<uint8_t>(wc);
2944 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2945 }
2946 return codecvt_base::ok;
2947}
2948
2949static
2950codecvt_base::result
2951utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2952 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2953 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2954{
2955 frm_nxt = frm;
2956 to_nxt = to;
2957 if (mode & consume_header)
2958 {
2959 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2960 frm_nxt += 2;
2961 }
2962 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2963 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002964 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002965 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2966 return codecvt_base::error;
2967 *to_nxt = c1;
2968 frm_nxt += 2;
2969 }
2970 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2971}
2972
2973static
2974int
2975utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2976 size_t mx, unsigned long Maxcode = 0x10FFFF,
2977 codecvt_mode mode = codecvt_mode(0))
2978{
2979 const uint8_t* frm_nxt = frm;
2980 frm_nxt = frm;
2981 if (mode & consume_header)
2982 {
2983 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2984 frm_nxt += 2;
2985 }
2986 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2987 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002988 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002989 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2990 break;
2991 frm_nxt += 2;
2992 }
2993 return static_cast<int>(frm_nxt - frm);
2994}
2995
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002996// template <> class codecvt<char16_t, char, mbstate_t>
2997
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002998locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002999
3000codecvt<char16_t, char, mbstate_t>::~codecvt()
3001{
3002}
3003
3004codecvt<char16_t, char, mbstate_t>::result
3005codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003006 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003007 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3008{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003009 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3010 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3011 const uint16_t* _frm_nxt = _frm;
3012 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3013 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3014 uint8_t* _to_nxt = _to;
3015 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3016 frm_nxt = frm + (_frm_nxt - _frm);
3017 to_nxt = to + (_to_nxt - _to);
3018 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003019}
3020
3021codecvt<char16_t, char, mbstate_t>::result
3022codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003023 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003024 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3025{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003026 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3027 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3028 const uint8_t* _frm_nxt = _frm;
3029 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3030 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3031 uint16_t* _to_nxt = _to;
3032 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3033 frm_nxt = frm + (_frm_nxt - _frm);
3034 to_nxt = to + (_to_nxt - _to);
3035 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003036}
3037
3038codecvt<char16_t, char, mbstate_t>::result
3039codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3040 extern_type* to, extern_type*, extern_type*& to_nxt) const
3041{
3042 to_nxt = to;
3043 return noconv;
3044}
3045
3046int
Howard Hinnantc9834542011-05-31 15:34:58 +00003047codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003048{
3049 return 0;
3050}
3051
3052bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003053codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003054{
3055 return false;
3056}
3057
3058int
3059codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3060 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3061{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003062 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3063 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3064 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003065}
3066
3067int
Howard Hinnantc9834542011-05-31 15:34:58 +00003068codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003069{
3070 return 4;
3071}
3072
3073// template <> class codecvt<char32_t, char, mbstate_t>
3074
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003075locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003076
3077codecvt<char32_t, char, mbstate_t>::~codecvt()
3078{
3079}
3080
3081codecvt<char32_t, char, mbstate_t>::result
3082codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003083 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003084 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3085{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003086 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3087 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3088 const uint32_t* _frm_nxt = _frm;
3089 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3090 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3091 uint8_t* _to_nxt = _to;
3092 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3093 frm_nxt = frm + (_frm_nxt - _frm);
3094 to_nxt = to + (_to_nxt - _to);
3095 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003096}
3097
3098codecvt<char32_t, char, mbstate_t>::result
3099codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003100 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003101 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3102{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003103 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3104 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3105 const uint8_t* _frm_nxt = _frm;
3106 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3107 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3108 uint32_t* _to_nxt = _to;
3109 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3110 frm_nxt = frm + (_frm_nxt - _frm);
3111 to_nxt = to + (_to_nxt - _to);
3112 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003113}
3114
3115codecvt<char32_t, char, mbstate_t>::result
3116codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3117 extern_type* to, extern_type*, extern_type*& to_nxt) const
3118{
3119 to_nxt = to;
3120 return noconv;
3121}
3122
3123int
Howard Hinnantc9834542011-05-31 15:34:58 +00003124codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003125{
3126 return 0;
3127}
3128
3129bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003130codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003131{
3132 return false;
3133}
3134
3135int
3136codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3137 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3138{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003139 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3140 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3141 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003142}
3143
3144int
Howard Hinnantc9834542011-05-31 15:34:58 +00003145codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003146{
3147 return 4;
3148}
3149
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003150// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003151
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003152__codecvt_utf8<wchar_t>::result
3153__codecvt_utf8<wchar_t>::do_out(state_type&,
3154 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003155 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3156{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003157 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3158 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3159 const uint32_t* _frm_nxt = _frm;
3160 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3161 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3162 uint8_t* _to_nxt = _to;
3163 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3164 _Maxcode_, _Mode_);
3165 frm_nxt = frm + (_frm_nxt - _frm);
3166 to_nxt = to + (_to_nxt - _to);
3167 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003168}
3169
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003170__codecvt_utf8<wchar_t>::result
3171__codecvt_utf8<wchar_t>::do_in(state_type&,
3172 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003173 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3174{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003175 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3176 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3177 const uint8_t* _frm_nxt = _frm;
3178 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3179 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3180 uint32_t* _to_nxt = _to;
3181 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3182 _Maxcode_, _Mode_);
3183 frm_nxt = frm + (_frm_nxt - _frm);
3184 to_nxt = to + (_to_nxt - _to);
3185 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003186}
3187
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003188__codecvt_utf8<wchar_t>::result
3189__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003190 extern_type* to, extern_type*, extern_type*& to_nxt) const
3191{
3192 to_nxt = to;
3193 return noconv;
3194}
3195
3196int
Howard Hinnantc9834542011-05-31 15:34:58 +00003197__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003198{
3199 return 0;
3200}
3201
3202bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003203__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003204{
3205 return false;
3206}
3207
3208int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003209__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003210 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3211{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003212 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3213 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3214 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003215}
3216
3217int
Howard Hinnantc9834542011-05-31 15:34:58 +00003218__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003219{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003220 if (_Mode_ & consume_header)
3221 return 7;
3222 return 4;
3223}
3224
3225// __codecvt_utf8<char16_t>
3226
3227__codecvt_utf8<char16_t>::result
3228__codecvt_utf8<char16_t>::do_out(state_type&,
3229 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3230 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3231{
3232 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3233 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3234 const uint16_t* _frm_nxt = _frm;
3235 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3236 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3237 uint8_t* _to_nxt = _to;
3238 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3239 _Maxcode_, _Mode_);
3240 frm_nxt = frm + (_frm_nxt - _frm);
3241 to_nxt = to + (_to_nxt - _to);
3242 return r;
3243}
3244
3245__codecvt_utf8<char16_t>::result
3246__codecvt_utf8<char16_t>::do_in(state_type&,
3247 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3248 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3249{
3250 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3251 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3252 const uint8_t* _frm_nxt = _frm;
3253 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3254 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3255 uint16_t* _to_nxt = _to;
3256 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3257 _Maxcode_, _Mode_);
3258 frm_nxt = frm + (_frm_nxt - _frm);
3259 to_nxt = to + (_to_nxt - _to);
3260 return r;
3261}
3262
3263__codecvt_utf8<char16_t>::result
3264__codecvt_utf8<char16_t>::do_unshift(state_type&,
3265 extern_type* to, extern_type*, extern_type*& to_nxt) const
3266{
3267 to_nxt = to;
3268 return noconv;
3269}
3270
3271int
Howard Hinnantc9834542011-05-31 15:34:58 +00003272__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003273{
3274 return 0;
3275}
3276
3277bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003278__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003279{
3280 return false;
3281}
3282
3283int
3284__codecvt_utf8<char16_t>::do_length(state_type&,
3285 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3286{
3287 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3288 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3289 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3290}
3291
3292int
Howard Hinnantc9834542011-05-31 15:34:58 +00003293__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003294{
3295 if (_Mode_ & consume_header)
3296 return 6;
3297 return 3;
3298}
3299
3300// __codecvt_utf8<char32_t>
3301
3302__codecvt_utf8<char32_t>::result
3303__codecvt_utf8<char32_t>::do_out(state_type&,
3304 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3305 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3306{
3307 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3308 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3309 const uint32_t* _frm_nxt = _frm;
3310 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3311 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3312 uint8_t* _to_nxt = _to;
3313 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3314 _Maxcode_, _Mode_);
3315 frm_nxt = frm + (_frm_nxt - _frm);
3316 to_nxt = to + (_to_nxt - _to);
3317 return r;
3318}
3319
3320__codecvt_utf8<char32_t>::result
3321__codecvt_utf8<char32_t>::do_in(state_type&,
3322 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3323 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3324{
3325 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3326 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3327 const uint8_t* _frm_nxt = _frm;
3328 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3329 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3330 uint32_t* _to_nxt = _to;
3331 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3332 _Maxcode_, _Mode_);
3333 frm_nxt = frm + (_frm_nxt - _frm);
3334 to_nxt = to + (_to_nxt - _to);
3335 return r;
3336}
3337
3338__codecvt_utf8<char32_t>::result
3339__codecvt_utf8<char32_t>::do_unshift(state_type&,
3340 extern_type* to, extern_type*, extern_type*& to_nxt) const
3341{
3342 to_nxt = to;
3343 return noconv;
3344}
3345
3346int
Howard Hinnantc9834542011-05-31 15:34:58 +00003347__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003348{
3349 return 0;
3350}
3351
3352bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003353__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003354{
3355 return false;
3356}
3357
3358int
3359__codecvt_utf8<char32_t>::do_length(state_type&,
3360 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3361{
3362 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3363 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3364 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3365}
3366
3367int
Howard Hinnantc9834542011-05-31 15:34:58 +00003368__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003369{
3370 if (_Mode_ & consume_header)
3371 return 7;
3372 return 4;
3373}
3374
3375// __codecvt_utf16<wchar_t, false>
3376
3377__codecvt_utf16<wchar_t, false>::result
3378__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3379 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3380 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3381{
3382 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3383 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3384 const uint32_t* _frm_nxt = _frm;
3385 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3386 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3387 uint8_t* _to_nxt = _to;
3388 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3389 _Maxcode_, _Mode_);
3390 frm_nxt = frm + (_frm_nxt - _frm);
3391 to_nxt = to + (_to_nxt - _to);
3392 return r;
3393}
3394
3395__codecvt_utf16<wchar_t, false>::result
3396__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3397 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3398 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3399{
3400 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3401 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3402 const uint8_t* _frm_nxt = _frm;
3403 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3404 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3405 uint32_t* _to_nxt = _to;
3406 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3407 _Maxcode_, _Mode_);
3408 frm_nxt = frm + (_frm_nxt - _frm);
3409 to_nxt = to + (_to_nxt - _to);
3410 return r;
3411}
3412
3413__codecvt_utf16<wchar_t, false>::result
3414__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3415 extern_type* to, extern_type*, extern_type*& to_nxt) const
3416{
3417 to_nxt = to;
3418 return noconv;
3419}
3420
3421int
Howard Hinnantc9834542011-05-31 15:34:58 +00003422__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003423{
3424 return 0;
3425}
3426
3427bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003428__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003429{
3430 return false;
3431}
3432
3433int
3434__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3435 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3436{
3437 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3438 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3439 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3440}
3441
3442int
Howard Hinnantc9834542011-05-31 15:34:58 +00003443__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003444{
3445 if (_Mode_ & consume_header)
3446 return 6;
3447 return 4;
3448}
3449
3450// __codecvt_utf16<wchar_t, true>
3451
3452__codecvt_utf16<wchar_t, true>::result
3453__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3454 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3455 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3456{
3457 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3458 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3459 const uint32_t* _frm_nxt = _frm;
3460 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3461 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3462 uint8_t* _to_nxt = _to;
3463 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3464 _Maxcode_, _Mode_);
3465 frm_nxt = frm + (_frm_nxt - _frm);
3466 to_nxt = to + (_to_nxt - _to);
3467 return r;
3468}
3469
3470__codecvt_utf16<wchar_t, true>::result
3471__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3472 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3473 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3474{
3475 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3476 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3477 const uint8_t* _frm_nxt = _frm;
3478 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3479 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3480 uint32_t* _to_nxt = _to;
3481 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3482 _Maxcode_, _Mode_);
3483 frm_nxt = frm + (_frm_nxt - _frm);
3484 to_nxt = to + (_to_nxt - _to);
3485 return r;
3486}
3487
3488__codecvt_utf16<wchar_t, true>::result
3489__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3490 extern_type* to, extern_type*, extern_type*& to_nxt) const
3491{
3492 to_nxt = to;
3493 return noconv;
3494}
3495
3496int
Howard Hinnantc9834542011-05-31 15:34:58 +00003497__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003498{
3499 return 0;
3500}
3501
3502bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003503__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003504{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003505 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003506}
3507
3508int
3509__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3510 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3511{
3512 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3513 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3514 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3515}
3516
3517int
Howard Hinnantc9834542011-05-31 15:34:58 +00003518__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003519{
3520 if (_Mode_ & consume_header)
3521 return 6;
3522 return 4;
3523}
3524
3525// __codecvt_utf16<char16_t, false>
3526
3527__codecvt_utf16<char16_t, false>::result
3528__codecvt_utf16<char16_t, false>::do_out(state_type&,
3529 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3530 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3531{
3532 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3533 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3534 const uint16_t* _frm_nxt = _frm;
3535 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3536 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3537 uint8_t* _to_nxt = _to;
3538 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3539 _Maxcode_, _Mode_);
3540 frm_nxt = frm + (_frm_nxt - _frm);
3541 to_nxt = to + (_to_nxt - _to);
3542 return r;
3543}
3544
3545__codecvt_utf16<char16_t, false>::result
3546__codecvt_utf16<char16_t, false>::do_in(state_type&,
3547 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3548 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3549{
3550 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3551 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3552 const uint8_t* _frm_nxt = _frm;
3553 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3554 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3555 uint16_t* _to_nxt = _to;
3556 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3557 _Maxcode_, _Mode_);
3558 frm_nxt = frm + (_frm_nxt - _frm);
3559 to_nxt = to + (_to_nxt - _to);
3560 return r;
3561}
3562
3563__codecvt_utf16<char16_t, false>::result
3564__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3565 extern_type* to, extern_type*, extern_type*& to_nxt) const
3566{
3567 to_nxt = to;
3568 return noconv;
3569}
3570
3571int
Howard Hinnantc9834542011-05-31 15:34:58 +00003572__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003573{
3574 return 0;
3575}
3576
3577bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003578__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003579{
3580 return false;
3581}
3582
3583int
3584__codecvt_utf16<char16_t, false>::do_length(state_type&,
3585 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3586{
3587 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3588 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3589 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3590}
3591
3592int
Howard Hinnantc9834542011-05-31 15:34:58 +00003593__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003594{
3595 if (_Mode_ & consume_header)
3596 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003597 return 2;
3598}
3599
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003600// __codecvt_utf16<char16_t, true>
3601
3602__codecvt_utf16<char16_t, true>::result
3603__codecvt_utf16<char16_t, true>::do_out(state_type&,
3604 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3605 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3606{
3607 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3608 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3609 const uint16_t* _frm_nxt = _frm;
3610 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3611 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3612 uint8_t* _to_nxt = _to;
3613 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3614 _Maxcode_, _Mode_);
3615 frm_nxt = frm + (_frm_nxt - _frm);
3616 to_nxt = to + (_to_nxt - _to);
3617 return r;
3618}
3619
3620__codecvt_utf16<char16_t, true>::result
3621__codecvt_utf16<char16_t, true>::do_in(state_type&,
3622 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3623 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3624{
3625 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3626 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3627 const uint8_t* _frm_nxt = _frm;
3628 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3629 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3630 uint16_t* _to_nxt = _to;
3631 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3632 _Maxcode_, _Mode_);
3633 frm_nxt = frm + (_frm_nxt - _frm);
3634 to_nxt = to + (_to_nxt - _to);
3635 return r;
3636}
3637
3638__codecvt_utf16<char16_t, true>::result
3639__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3640 extern_type* to, extern_type*, extern_type*& to_nxt) const
3641{
3642 to_nxt = to;
3643 return noconv;
3644}
3645
3646int
Howard Hinnantc9834542011-05-31 15:34:58 +00003647__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003648{
3649 return 0;
3650}
3651
3652bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003653__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003654{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003655 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003656}
3657
3658int
3659__codecvt_utf16<char16_t, true>::do_length(state_type&,
3660 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3661{
3662 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3663 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3664 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3665}
3666
3667int
Howard Hinnantc9834542011-05-31 15:34:58 +00003668__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003669{
3670 if (_Mode_ & consume_header)
3671 return 4;
3672 return 2;
3673}
3674
3675// __codecvt_utf16<char32_t, false>
3676
3677__codecvt_utf16<char32_t, false>::result
3678__codecvt_utf16<char32_t, false>::do_out(state_type&,
3679 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3680 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3681{
3682 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3683 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3684 const uint32_t* _frm_nxt = _frm;
3685 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3686 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3687 uint8_t* _to_nxt = _to;
3688 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3689 _Maxcode_, _Mode_);
3690 frm_nxt = frm + (_frm_nxt - _frm);
3691 to_nxt = to + (_to_nxt - _to);
3692 return r;
3693}
3694
3695__codecvt_utf16<char32_t, false>::result
3696__codecvt_utf16<char32_t, false>::do_in(state_type&,
3697 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3698 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3699{
3700 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3701 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3702 const uint8_t* _frm_nxt = _frm;
3703 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3704 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3705 uint32_t* _to_nxt = _to;
3706 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3707 _Maxcode_, _Mode_);
3708 frm_nxt = frm + (_frm_nxt - _frm);
3709 to_nxt = to + (_to_nxt - _to);
3710 return r;
3711}
3712
3713__codecvt_utf16<char32_t, false>::result
3714__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3715 extern_type* to, extern_type*, extern_type*& to_nxt) const
3716{
3717 to_nxt = to;
3718 return noconv;
3719}
3720
3721int
Howard Hinnantc9834542011-05-31 15:34:58 +00003722__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003723{
3724 return 0;
3725}
3726
3727bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003728__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003729{
3730 return false;
3731}
3732
3733int
3734__codecvt_utf16<char32_t, false>::do_length(state_type&,
3735 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3736{
3737 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3738 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3739 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3740}
3741
3742int
Howard Hinnantc9834542011-05-31 15:34:58 +00003743__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003744{
3745 if (_Mode_ & consume_header)
3746 return 6;
3747 return 4;
3748}
3749
3750// __codecvt_utf16<char32_t, true>
3751
3752__codecvt_utf16<char32_t, true>::result
3753__codecvt_utf16<char32_t, true>::do_out(state_type&,
3754 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3755 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3756{
3757 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3758 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3759 const uint32_t* _frm_nxt = _frm;
3760 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3761 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3762 uint8_t* _to_nxt = _to;
3763 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3764 _Maxcode_, _Mode_);
3765 frm_nxt = frm + (_frm_nxt - _frm);
3766 to_nxt = to + (_to_nxt - _to);
3767 return r;
3768}
3769
3770__codecvt_utf16<char32_t, true>::result
3771__codecvt_utf16<char32_t, true>::do_in(state_type&,
3772 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3773 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3774{
3775 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3776 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3777 const uint8_t* _frm_nxt = _frm;
3778 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3779 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3780 uint32_t* _to_nxt = _to;
3781 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3782 _Maxcode_, _Mode_);
3783 frm_nxt = frm + (_frm_nxt - _frm);
3784 to_nxt = to + (_to_nxt - _to);
3785 return r;
3786}
3787
3788__codecvt_utf16<char32_t, true>::result
3789__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3790 extern_type* to, extern_type*, extern_type*& to_nxt) const
3791{
3792 to_nxt = to;
3793 return noconv;
3794}
3795
3796int
Howard Hinnantc9834542011-05-31 15:34:58 +00003797__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003798{
3799 return 0;
3800}
3801
3802bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003803__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003804{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003805 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003806}
3807
3808int
3809__codecvt_utf16<char32_t, true>::do_length(state_type&,
3810 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3811{
3812 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3813 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3814 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3815}
3816
3817int
Howard Hinnantc9834542011-05-31 15:34:58 +00003818__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003819{
3820 if (_Mode_ & consume_header)
3821 return 6;
3822 return 4;
3823}
3824
3825// __codecvt_utf8_utf16<wchar_t>
3826
3827__codecvt_utf8_utf16<wchar_t>::result
3828__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3829 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3830 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3831{
3832 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3833 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3834 const uint32_t* _frm_nxt = _frm;
3835 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3836 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3837 uint8_t* _to_nxt = _to;
3838 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3839 _Maxcode_, _Mode_);
3840 frm_nxt = frm + (_frm_nxt - _frm);
3841 to_nxt = to + (_to_nxt - _to);
3842 return r;
3843}
3844
3845__codecvt_utf8_utf16<wchar_t>::result
3846__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3847 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3848 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3849{
3850 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3851 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3852 const uint8_t* _frm_nxt = _frm;
3853 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3854 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3855 uint32_t* _to_nxt = _to;
3856 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3857 _Maxcode_, _Mode_);
3858 frm_nxt = frm + (_frm_nxt - _frm);
3859 to_nxt = to + (_to_nxt - _to);
3860 return r;
3861}
3862
3863__codecvt_utf8_utf16<wchar_t>::result
3864__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3865 extern_type* to, extern_type*, extern_type*& to_nxt) const
3866{
3867 to_nxt = to;
3868 return noconv;
3869}
3870
3871int
Howard Hinnantc9834542011-05-31 15:34:58 +00003872__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003873{
3874 return 0;
3875}
3876
3877bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003878__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003879{
3880 return false;
3881}
3882
3883int
3884__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3885 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3886{
3887 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3888 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3889 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3890}
3891
3892int
Howard Hinnantc9834542011-05-31 15:34:58 +00003893__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003894{
3895 if (_Mode_ & consume_header)
3896 return 7;
3897 return 4;
3898}
3899
3900// __codecvt_utf8_utf16<char16_t>
3901
3902__codecvt_utf8_utf16<char16_t>::result
3903__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3904 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3905 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3906{
3907 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3908 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3909 const uint16_t* _frm_nxt = _frm;
3910 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3911 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3912 uint8_t* _to_nxt = _to;
3913 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3914 _Maxcode_, _Mode_);
3915 frm_nxt = frm + (_frm_nxt - _frm);
3916 to_nxt = to + (_to_nxt - _to);
3917 return r;
3918}
3919
3920__codecvt_utf8_utf16<char16_t>::result
3921__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3922 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3923 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3924{
3925 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3926 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3927 const uint8_t* _frm_nxt = _frm;
3928 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3929 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3930 uint16_t* _to_nxt = _to;
3931 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3932 _Maxcode_, _Mode_);
3933 frm_nxt = frm + (_frm_nxt - _frm);
3934 to_nxt = to + (_to_nxt - _to);
3935 return r;
3936}
3937
3938__codecvt_utf8_utf16<char16_t>::result
3939__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3940 extern_type* to, extern_type*, extern_type*& to_nxt) const
3941{
3942 to_nxt = to;
3943 return noconv;
3944}
3945
3946int
Howard Hinnantc9834542011-05-31 15:34:58 +00003947__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003948{
3949 return 0;
3950}
3951
3952bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003953__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003954{
3955 return false;
3956}
3957
3958int
3959__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3960 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3961{
3962 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3963 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3964 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3965}
3966
3967int
Howard Hinnantc9834542011-05-31 15:34:58 +00003968__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003969{
3970 if (_Mode_ & consume_header)
3971 return 7;
3972 return 4;
3973}
3974
3975// __codecvt_utf8_utf16<char32_t>
3976
3977__codecvt_utf8_utf16<char32_t>::result
3978__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3979 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3980 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3981{
3982 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3983 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3984 const uint32_t* _frm_nxt = _frm;
3985 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3986 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3987 uint8_t* _to_nxt = _to;
3988 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3989 _Maxcode_, _Mode_);
3990 frm_nxt = frm + (_frm_nxt - _frm);
3991 to_nxt = to + (_to_nxt - _to);
3992 return r;
3993}
3994
3995__codecvt_utf8_utf16<char32_t>::result
3996__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3997 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3998 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3999{
4000 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4001 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4002 const uint8_t* _frm_nxt = _frm;
4003 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4004 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4005 uint32_t* _to_nxt = _to;
4006 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4007 _Maxcode_, _Mode_);
4008 frm_nxt = frm + (_frm_nxt - _frm);
4009 to_nxt = to + (_to_nxt - _to);
4010 return r;
4011}
4012
4013__codecvt_utf8_utf16<char32_t>::result
4014__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4015 extern_type* to, extern_type*, extern_type*& to_nxt) const
4016{
4017 to_nxt = to;
4018 return noconv;
4019}
4020
4021int
Howard Hinnantc9834542011-05-31 15:34:58 +00004022__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004023{
4024 return 0;
4025}
4026
4027bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004028__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004029{
4030 return false;
4031}
4032
4033int
4034__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4035 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4036{
4037 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4038 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4039 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4040}
4041
4042int
Howard Hinnantc9834542011-05-31 15:34:58 +00004043__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004044{
4045 if (_Mode_ & consume_header)
4046 return 7;
4047 return 4;
4048}
4049
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004050// __narrow_to_utf8<16>
4051
4052__narrow_to_utf8<16>::~__narrow_to_utf8()
4053{
4054}
4055
4056// __narrow_to_utf8<32>
4057
4058__narrow_to_utf8<32>::~__narrow_to_utf8()
4059{
4060}
4061
4062// __widen_from_utf8<16>
4063
4064__widen_from_utf8<16>::~__widen_from_utf8()
4065{
4066}
4067
4068// __widen_from_utf8<32>
4069
4070__widen_from_utf8<32>::~__widen_from_utf8()
4071{
4072}
4073
4074// numpunct<char> && numpunct<wchar_t>
4075
4076locale::id numpunct< char >::id;
4077locale::id numpunct<wchar_t>::id;
4078
4079numpunct<char>::numpunct(size_t refs)
4080 : locale::facet(refs),
4081 __decimal_point_('.'),
4082 __thousands_sep_(',')
4083{
4084}
4085
4086numpunct<wchar_t>::numpunct(size_t refs)
4087 : locale::facet(refs),
4088 __decimal_point_(L'.'),
4089 __thousands_sep_(L',')
4090{
4091}
4092
4093numpunct<char>::~numpunct()
4094{
4095}
4096
4097numpunct<wchar_t>::~numpunct()
4098{
4099}
4100
4101 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4102wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4103
4104 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4105wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4106
4107string numpunct< char >::do_grouping() const {return __grouping_;}
4108string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4109
4110 string numpunct< char >::do_truename() const {return "true";}
4111wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4112
4113 string numpunct< char >::do_falsename() const {return "false";}
4114wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4115
4116// numpunct_byname<char>
4117
4118numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4119 : numpunct<char>(refs)
4120{
4121 __init(nm);
4122}
4123
4124numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4125 : numpunct<char>(refs)
4126{
4127 __init(nm.c_str());
4128}
4129
4130numpunct_byname<char>::~numpunct_byname()
4131{
4132}
4133
4134void
4135numpunct_byname<char>::__init(const char* nm)
4136{
4137 if (strcmp(nm, "C") != 0)
4138 {
Sean Huntf3907e62011-07-15 05:40:33 +00004139 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004140#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004141 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004142 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4143 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004144#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004145#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004146 lconv* lc = localeconv_l(loc.get());
4147#else
4148 lconv* lc = __localeconv_l(loc.get());
4149#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004150 if (*lc->decimal_point)
4151 __decimal_point_ = *lc->decimal_point;
4152 if (*lc->thousands_sep)
4153 __thousands_sep_ = *lc->thousands_sep;
4154 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004155 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004156 }
4157}
4158
4159// numpunct_byname<wchar_t>
4160
4161numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4162 : numpunct<wchar_t>(refs)
4163{
4164 __init(nm);
4165}
4166
4167numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4168 : numpunct<wchar_t>(refs)
4169{
4170 __init(nm.c_str());
4171}
4172
4173numpunct_byname<wchar_t>::~numpunct_byname()
4174{
4175}
4176
4177void
4178numpunct_byname<wchar_t>::__init(const char* nm)
4179{
4180 if (strcmp(nm, "C") != 0)
4181 {
Sean Huntf3907e62011-07-15 05:40:33 +00004182 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004183#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004184 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004185 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4186 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004187#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004188#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004189 lconv* lc = localeconv_l(loc.get());
4190#else
4191 lconv* lc = __localeconv_l(loc.get());
4192#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004193 if (*lc->decimal_point)
4194 __decimal_point_ = *lc->decimal_point;
4195 if (*lc->thousands_sep)
4196 __thousands_sep_ = *lc->thousands_sep;
4197 __grouping_ = lc->grouping;
4198 // locallization for truename and falsename is not available
4199 }
4200}
4201
4202// num_get helpers
4203
4204int
4205__num_get_base::__get_base(ios_base& iob)
4206{
4207 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4208 if (__basefield == ios_base::oct)
4209 return 8;
4210 else if (__basefield == ios_base::hex)
4211 return 16;
4212 else if (__basefield == 0)
4213 return 0;
4214 return 10;
4215}
4216
4217const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4218
4219void
4220__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4221 ios_base::iostate& __err)
4222{
4223 if (__grouping.size() != 0)
4224 {
4225 reverse(__g, __g_end);
4226 const char* __ig = __grouping.data();
4227 const char* __eg = __ig + __grouping.size();
4228 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4229 {
4230 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4231 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004232 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004233 {
4234 __err = ios_base::failbit;
4235 return;
4236 }
4237 }
4238 if (__eg - __ig > 1)
4239 ++__ig;
4240 }
4241 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4242 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004243 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004244 __err = ios_base::failbit;
4245 }
4246 }
4247}
4248
4249void
4250__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4251 ios_base::fmtflags __flags)
4252{
4253 if (__flags & ios_base::showpos)
4254 *__fmtp++ = '+';
4255 if (__flags & ios_base::showbase)
4256 *__fmtp++ = '#';
4257 while(*__len)
4258 *__fmtp++ = *__len++;
4259 if ((__flags & ios_base::basefield) == ios_base::oct)
4260 *__fmtp = 'o';
4261 else if ((__flags & ios_base::basefield) == ios_base::hex)
4262 {
4263 if (__flags & ios_base::uppercase)
4264 *__fmtp = 'X';
4265 else
4266 *__fmtp = 'x';
4267 }
4268 else if (__signd)
4269 *__fmtp = 'd';
4270 else
4271 *__fmtp = 'u';
4272}
4273
4274bool
4275__num_put_base::__format_float(char* __fmtp, const char* __len,
4276 ios_base::fmtflags __flags)
4277{
4278 bool specify_precision = true;
4279 if (__flags & ios_base::showpos)
4280 *__fmtp++ = '+';
4281 if (__flags & ios_base::showpoint)
4282 *__fmtp++ = '#';
4283 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4284 bool uppercase = __flags & ios_base::uppercase;
4285 if (floatfield == (ios_base::fixed | ios_base::scientific))
4286 specify_precision = false;
4287 else
4288 {
4289 *__fmtp++ = '.';
4290 *__fmtp++ = '*';
4291 }
4292 while(*__len)
4293 *__fmtp++ = *__len++;
4294 if (floatfield == ios_base::fixed)
4295 {
4296 if (uppercase)
4297 *__fmtp = 'F';
4298 else
4299 *__fmtp = 'f';
4300 }
4301 else if (floatfield == ios_base::scientific)
4302 {
4303 if (uppercase)
4304 *__fmtp = 'E';
4305 else
4306 *__fmtp = 'e';
4307 }
4308 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4309 {
4310 if (uppercase)
4311 *__fmtp = 'A';
4312 else
4313 *__fmtp = 'a';
4314 }
4315 else
4316 {
4317 if (uppercase)
4318 *__fmtp = 'G';
4319 else
4320 *__fmtp = 'g';
4321 }
4322 return specify_precision;
4323}
4324
4325char*
4326__num_put_base::__identify_padding(char* __nb, char* __ne,
4327 const ios_base& __iob)
4328{
4329 switch (__iob.flags() & ios_base::adjustfield)
4330 {
4331 case ios_base::internal:
4332 if (__nb[0] == '-' || __nb[0] == '+')
4333 return __nb+1;
4334 if (__ne - __nb >= 2 && __nb[0] == '0'
4335 && (__nb[1] == 'x' || __nb[1] == 'X'))
4336 return __nb+2;
4337 break;
4338 case ios_base::left:
4339 return __ne;
4340 case ios_base::right:
4341 default:
4342 break;
4343 }
4344 return __nb;
4345}
4346
4347// time_get
4348
4349static
4350string*
4351init_weeks()
4352{
4353 static string weeks[14];
4354 weeks[0] = "Sunday";
4355 weeks[1] = "Monday";
4356 weeks[2] = "Tuesday";
4357 weeks[3] = "Wednesday";
4358 weeks[4] = "Thursday";
4359 weeks[5] = "Friday";
4360 weeks[6] = "Saturday";
4361 weeks[7] = "Sun";
4362 weeks[8] = "Mon";
4363 weeks[9] = "Tue";
4364 weeks[10] = "Wed";
4365 weeks[11] = "Thu";
4366 weeks[12] = "Fri";
4367 weeks[13] = "Sat";
4368 return weeks;
4369}
4370
4371static
4372wstring*
4373init_wweeks()
4374{
4375 static wstring weeks[14];
4376 weeks[0] = L"Sunday";
4377 weeks[1] = L"Monday";
4378 weeks[2] = L"Tuesday";
4379 weeks[3] = L"Wednesday";
4380 weeks[4] = L"Thursday";
4381 weeks[5] = L"Friday";
4382 weeks[6] = L"Saturday";
4383 weeks[7] = L"Sun";
4384 weeks[8] = L"Mon";
4385 weeks[9] = L"Tue";
4386 weeks[10] = L"Wed";
4387 weeks[11] = L"Thu";
4388 weeks[12] = L"Fri";
4389 weeks[13] = L"Sat";
4390 return weeks;
4391}
4392
4393template <>
4394const string*
4395__time_get_c_storage<char>::__weeks() const
4396{
4397 static const string* weeks = init_weeks();
4398 return weeks;
4399}
4400
4401template <>
4402const wstring*
4403__time_get_c_storage<wchar_t>::__weeks() const
4404{
4405 static const wstring* weeks = init_wweeks();
4406 return weeks;
4407}
4408
4409static
4410string*
4411init_months()
4412{
4413 static string months[24];
4414 months[0] = "January";
4415 months[1] = "February";
4416 months[2] = "March";
4417 months[3] = "April";
4418 months[4] = "May";
4419 months[5] = "June";
4420 months[6] = "July";
4421 months[7] = "August";
4422 months[8] = "September";
4423 months[9] = "October";
4424 months[10] = "November";
4425 months[11] = "December";
4426 months[12] = "Jan";
4427 months[13] = "Feb";
4428 months[14] = "Mar";
4429 months[15] = "Apr";
4430 months[16] = "May";
4431 months[17] = "Jun";
4432 months[18] = "Jul";
4433 months[19] = "Aug";
4434 months[20] = "Sep";
4435 months[21] = "Oct";
4436 months[22] = "Nov";
4437 months[23] = "Dec";
4438 return months;
4439}
4440
4441static
4442wstring*
4443init_wmonths()
4444{
4445 static wstring months[24];
4446 months[0] = L"January";
4447 months[1] = L"February";
4448 months[2] = L"March";
4449 months[3] = L"April";
4450 months[4] = L"May";
4451 months[5] = L"June";
4452 months[6] = L"July";
4453 months[7] = L"August";
4454 months[8] = L"September";
4455 months[9] = L"October";
4456 months[10] = L"November";
4457 months[11] = L"December";
4458 months[12] = L"Jan";
4459 months[13] = L"Feb";
4460 months[14] = L"Mar";
4461 months[15] = L"Apr";
4462 months[16] = L"May";
4463 months[17] = L"Jun";
4464 months[18] = L"Jul";
4465 months[19] = L"Aug";
4466 months[20] = L"Sep";
4467 months[21] = L"Oct";
4468 months[22] = L"Nov";
4469 months[23] = L"Dec";
4470 return months;
4471}
4472
4473template <>
4474const string*
4475__time_get_c_storage<char>::__months() const
4476{
4477 static const string* months = init_months();
4478 return months;
4479}
4480
4481template <>
4482const wstring*
4483__time_get_c_storage<wchar_t>::__months() const
4484{
4485 static const wstring* months = init_wmonths();
4486 return months;
4487}
4488
4489static
4490string*
4491init_am_pm()
4492{
4493 static string am_pm[24];
4494 am_pm[0] = "AM";
4495 am_pm[1] = "PM";
4496 return am_pm;
4497}
4498
4499static
4500wstring*
4501init_wam_pm()
4502{
4503 static wstring am_pm[24];
4504 am_pm[0] = L"AM";
4505 am_pm[1] = L"PM";
4506 return am_pm;
4507}
4508
4509template <>
4510const string*
4511__time_get_c_storage<char>::__am_pm() const
4512{
4513 static const string* am_pm = init_am_pm();
4514 return am_pm;
4515}
4516
4517template <>
4518const wstring*
4519__time_get_c_storage<wchar_t>::__am_pm() const
4520{
4521 static const wstring* am_pm = init_wam_pm();
4522 return am_pm;
4523}
4524
4525template <>
4526const string&
4527__time_get_c_storage<char>::__x() const
4528{
4529 static string s("%m/%d/%y");
4530 return s;
4531}
4532
4533template <>
4534const wstring&
4535__time_get_c_storage<wchar_t>::__x() const
4536{
4537 static wstring s(L"%m/%d/%y");
4538 return s;
4539}
4540
4541template <>
4542const string&
4543__time_get_c_storage<char>::__X() const
4544{
4545 static string s("%H:%M:%S");
4546 return s;
4547}
4548
4549template <>
4550const wstring&
4551__time_get_c_storage<wchar_t>::__X() const
4552{
4553 static wstring s(L"%H:%M:%S");
4554 return s;
4555}
4556
4557template <>
4558const string&
4559__time_get_c_storage<char>::__c() const
4560{
4561 static string s("%a %b %d %H:%M:%S %Y");
4562 return s;
4563}
4564
4565template <>
4566const wstring&
4567__time_get_c_storage<wchar_t>::__c() const
4568{
4569 static wstring s(L"%a %b %d %H:%M:%S %Y");
4570 return s;
4571}
4572
4573template <>
4574const string&
4575__time_get_c_storage<char>::__r() const
4576{
4577 static string s("%I:%M:%S %p");
4578 return s;
4579}
4580
4581template <>
4582const wstring&
4583__time_get_c_storage<wchar_t>::__r() const
4584{
4585 static wstring s(L"%I:%M:%S %p");
4586 return s;
4587}
4588
4589// time_get_byname
4590
4591__time_get::__time_get(const char* nm)
4592 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4593{
Howard Hinnantd4444702010-08-11 17:04:31 +00004594#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004595 if (__loc_ == 0)
4596 throw runtime_error("time_get_byname"
4597 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004598#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004599}
4600
4601__time_get::__time_get(const string& nm)
4602 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4603{
Howard Hinnantd4444702010-08-11 17:04:31 +00004604#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004605 if (__loc_ == 0)
4606 throw runtime_error("time_get_byname"
4607 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004608#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004609}
4610
4611__time_get::~__time_get()
4612{
4613 freelocale(__loc_);
4614}
4615
Howard Hinnant335b1512012-02-20 16:51:43 +00004616#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant21772ec2012-12-28 18:15:01 +00004617#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant335b1512012-02-20 16:51:43 +00004618
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004619template <>
4620string
4621__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4622{
Howard Hinnant3074a052012-02-19 14:55:32 +00004623 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004624 t.tm_sec = 59;
4625 t.tm_min = 55;
4626 t.tm_hour = 23;
4627 t.tm_mday = 31;
4628 t.tm_mon = 11;
4629 t.tm_year = 161;
4630 t.tm_wday = 6;
4631 t.tm_yday = 364;
4632 t.tm_isdst = -1;
4633 char buf[100];
4634 char f[3] = {0};
4635 f[0] = '%';
4636 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004637 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004638 char* bb = buf;
4639 char* be = buf + n;
4640 string result;
4641 while (bb != be)
4642 {
4643 if (ct.is(ctype_base::space, *bb))
4644 {
4645 result.push_back(' ');
4646 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4647 ;
4648 continue;
4649 }
4650 char* w = bb;
4651 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004652 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004653 ct, err, false)
4654 - this->__weeks_;
4655 if (i < 14)
4656 {
4657 result.push_back('%');
4658 if (i < 7)
4659 result.push_back('A');
4660 else
4661 result.push_back('a');
4662 bb = w;
4663 continue;
4664 }
4665 w = bb;
4666 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4667 ct, err, false)
4668 - this->__months_;
4669 if (i < 24)
4670 {
4671 result.push_back('%');
4672 if (i < 12)
4673 result.push_back('B');
4674 else
4675 result.push_back('b');
4676 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4677 result.back() = 'm';
4678 bb = w;
4679 continue;
4680 }
4681 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4682 {
4683 w = bb;
4684 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4685 ct, err, false) - this->__am_pm_;
4686 if (i < 2)
4687 {
4688 result.push_back('%');
4689 result.push_back('p');
4690 bb = w;
4691 continue;
4692 }
4693 }
4694 w = bb;
4695 if (ct.is(ctype_base::digit, *bb))
4696 {
4697 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4698 {
4699 case 6:
4700 result.push_back('%');
4701 result.push_back('w');
4702 break;
4703 case 7:
4704 result.push_back('%');
4705 result.push_back('u');
4706 break;
4707 case 11:
4708 result.push_back('%');
4709 result.push_back('I');
4710 break;
4711 case 12:
4712 result.push_back('%');
4713 result.push_back('m');
4714 break;
4715 case 23:
4716 result.push_back('%');
4717 result.push_back('H');
4718 break;
4719 case 31:
4720 result.push_back('%');
4721 result.push_back('d');
4722 break;
4723 case 55:
4724 result.push_back('%');
4725 result.push_back('M');
4726 break;
4727 case 59:
4728 result.push_back('%');
4729 result.push_back('S');
4730 break;
4731 case 61:
4732 result.push_back('%');
4733 result.push_back('y');
4734 break;
4735 case 364:
4736 result.push_back('%');
4737 result.push_back('j');
4738 break;
4739 case 2061:
4740 result.push_back('%');
4741 result.push_back('Y');
4742 break;
4743 default:
4744 for (; w != bb; ++w)
4745 result.push_back(*w);
4746 break;
4747 }
4748 continue;
4749 }
4750 if (*bb == '%')
4751 {
4752 result.push_back('%');
4753 result.push_back('%');
4754 ++bb;
4755 continue;
4756 }
4757 result.push_back(*bb);
4758 ++bb;
4759 }
4760 return result;
4761}
4762
Howard Hinnantec3773c2011-12-01 20:21:04 +00004763#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004764
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004765template <>
4766wstring
4767__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4768{
Howard Hinnant3074a052012-02-19 14:55:32 +00004769 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004770 t.tm_sec = 59;
4771 t.tm_min = 55;
4772 t.tm_hour = 23;
4773 t.tm_mday = 31;
4774 t.tm_mon = 11;
4775 t.tm_year = 161;
4776 t.tm_wday = 6;
4777 t.tm_yday = 364;
4778 t.tm_isdst = -1;
4779 char buf[100];
4780 char f[3] = {0};
4781 f[0] = '%';
4782 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004783 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004784 wchar_t wbuf[100];
4785 wchar_t* wbb = wbuf;
4786 mbstate_t mb = {0};
4787 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004788#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004789 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004790#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004791 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004792#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004793 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004794 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004795 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004796 wstring result;
4797 while (wbb != wbe)
4798 {
4799 if (ct.is(ctype_base::space, *wbb))
4800 {
4801 result.push_back(L' ');
4802 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4803 ;
4804 continue;
4805 }
4806 wchar_t* w = wbb;
4807 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004808 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004809 ct, err, false)
4810 - this->__weeks_;
4811 if (i < 14)
4812 {
4813 result.push_back(L'%');
4814 if (i < 7)
4815 result.push_back(L'A');
4816 else
4817 result.push_back(L'a');
4818 wbb = w;
4819 continue;
4820 }
4821 w = wbb;
4822 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4823 ct, err, false)
4824 - this->__months_;
4825 if (i < 24)
4826 {
4827 result.push_back(L'%');
4828 if (i < 12)
4829 result.push_back(L'B');
4830 else
4831 result.push_back(L'b');
4832 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4833 result.back() = L'm';
4834 wbb = w;
4835 continue;
4836 }
4837 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4838 {
4839 w = wbb;
4840 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4841 ct, err, false) - this->__am_pm_;
4842 if (i < 2)
4843 {
4844 result.push_back(L'%');
4845 result.push_back(L'p');
4846 wbb = w;
4847 continue;
4848 }
4849 }
4850 w = wbb;
4851 if (ct.is(ctype_base::digit, *wbb))
4852 {
4853 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4854 {
4855 case 6:
4856 result.push_back(L'%');
4857 result.push_back(L'w');
4858 break;
4859 case 7:
4860 result.push_back(L'%');
4861 result.push_back(L'u');
4862 break;
4863 case 11:
4864 result.push_back(L'%');
4865 result.push_back(L'I');
4866 break;
4867 case 12:
4868 result.push_back(L'%');
4869 result.push_back(L'm');
4870 break;
4871 case 23:
4872 result.push_back(L'%');
4873 result.push_back(L'H');
4874 break;
4875 case 31:
4876 result.push_back(L'%');
4877 result.push_back(L'd');
4878 break;
4879 case 55:
4880 result.push_back(L'%');
4881 result.push_back(L'M');
4882 break;
4883 case 59:
4884 result.push_back(L'%');
4885 result.push_back(L'S');
4886 break;
4887 case 61:
4888 result.push_back(L'%');
4889 result.push_back(L'y');
4890 break;
4891 case 364:
4892 result.push_back(L'%');
4893 result.push_back(L'j');
4894 break;
4895 case 2061:
4896 result.push_back(L'%');
4897 result.push_back(L'Y');
4898 break;
4899 default:
4900 for (; w != wbb; ++w)
4901 result.push_back(*w);
4902 break;
4903 }
4904 continue;
4905 }
4906 if (ct.narrow(*wbb, 0) == '%')
4907 {
4908 result.push_back(L'%');
4909 result.push_back(L'%');
4910 ++wbb;
4911 continue;
4912 }
4913 result.push_back(*wbb);
4914 ++wbb;
4915 }
4916 return result;
4917}
4918
4919template <>
4920void
4921__time_get_storage<char>::init(const ctype<char>& ct)
4922{
Howard Hinnantcd992362012-08-02 18:44:17 +00004923 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004924 char buf[100];
4925 // __weeks_
4926 for (int i = 0; i < 7; ++i)
4927 {
4928 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004929 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004930 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004931 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004932 __weeks_[i+7] = buf;
4933 }
4934 // __months_
4935 for (int i = 0; i < 12; ++i)
4936 {
4937 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004938 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004939 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004940 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004941 __months_[i+12] = buf;
4942 }
4943 // __am_pm_
4944 t.tm_hour = 1;
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_[0] = buf;
4947 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004948 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004949 __am_pm_[1] = buf;
4950 __c_ = __analyze('c', ct);
4951 __r_ = __analyze('r', ct);
4952 __x_ = __analyze('x', ct);
4953 __X_ = __analyze('X', ct);
4954}
4955
4956template <>
4957void
4958__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4959{
4960 tm t = {0};
4961 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004962 wchar_t wbuf[100];
4963 wchar_t* wbe;
4964 mbstate_t mb = {0};
4965 // __weeks_
4966 for (int i = 0; i < 7; ++i)
4967 {
4968 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004969 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004970 mb = mbstate_t();
4971 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004972#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004973 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004974#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004975 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004976#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004977 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004978 __throw_runtime_error("locale not supported");
4979 wbe = wbuf + j;
4980 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004981 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004982 mb = mbstate_t();
4983 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004984#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004985 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004986#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004987 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004988#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004989 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004990 __throw_runtime_error("locale not supported");
4991 wbe = wbuf + j;
4992 __weeks_[i+7].assign(wbuf, wbe);
4993 }
4994 // __months_
4995 for (int i = 0; i < 12; ++i)
4996 {
4997 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004998 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004999 mb = mbstate_t();
5000 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005001#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005002 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005003#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005004 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005005#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005006 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005007 __throw_runtime_error("locale not supported");
5008 wbe = wbuf + j;
5009 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005010 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005011 mb = mbstate_t();
5012 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005013#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005014 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005015#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005016 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005017#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005018 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005019 __throw_runtime_error("locale not supported");
5020 wbe = wbuf + j;
5021 __months_[i+12].assign(wbuf, wbe);
5022 }
5023 // __am_pm_
5024 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005025 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005026 mb = mbstate_t();
5027 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005028#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005029 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005030#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005031 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005032#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005033 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005034 __throw_runtime_error("locale not supported");
5035 wbe = wbuf + j;
5036 __am_pm_[0].assign(wbuf, wbe);
5037 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005038 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005039 mb = mbstate_t();
5040 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005041#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005042 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005043#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005044 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005045#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005046 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005047 __throw_runtime_error("locale not supported");
5048 wbe = wbuf + j;
5049 __am_pm_[1].assign(wbuf, wbe);
5050 __c_ = __analyze('c', ct);
5051 __r_ = __analyze('r', ct);
5052 __x_ = __analyze('x', ct);
5053 __X_ = __analyze('X', ct);
5054}
5055
5056template <class CharT>
5057struct _LIBCPP_HIDDEN __time_get_temp
5058 : public ctype_byname<CharT>
5059{
5060 explicit __time_get_temp(const char* nm)
5061 : ctype_byname<CharT>(nm, 1) {}
5062 explicit __time_get_temp(const string& nm)
5063 : ctype_byname<CharT>(nm, 1) {}
5064};
5065
5066template <>
5067__time_get_storage<char>::__time_get_storage(const char* __nm)
5068 : __time_get(__nm)
5069{
5070 const __time_get_temp<char> ct(__nm);
5071 init(ct);
5072}
5073
5074template <>
5075__time_get_storage<char>::__time_get_storage(const string& __nm)
5076 : __time_get(__nm)
5077{
5078 const __time_get_temp<char> ct(__nm);
5079 init(ct);
5080}
5081
5082template <>
5083__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5084 : __time_get(__nm)
5085{
5086 const __time_get_temp<wchar_t> ct(__nm);
5087 init(ct);
5088}
5089
5090template <>
5091__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5092 : __time_get(__nm)
5093{
5094 const __time_get_temp<wchar_t> ct(__nm);
5095 init(ct);
5096}
5097
5098template <>
5099time_base::dateorder
5100__time_get_storage<char>::__do_date_order() const
5101{
5102 unsigned i;
5103 for (i = 0; i < __x_.size(); ++i)
5104 if (__x_[i] == '%')
5105 break;
5106 ++i;
5107 switch (__x_[i])
5108 {
5109 case 'y':
5110 case 'Y':
5111 for (++i; i < __x_.size(); ++i)
5112 if (__x_[i] == '%')
5113 break;
5114 if (i == __x_.size())
5115 break;
5116 ++i;
5117 switch (__x_[i])
5118 {
5119 case 'm':
5120 for (++i; i < __x_.size(); ++i)
5121 if (__x_[i] == '%')
5122 break;
5123 if (i == __x_.size())
5124 break;
5125 ++i;
5126 if (__x_[i] == 'd')
5127 return time_base::ymd;
5128 break;
5129 case 'd':
5130 for (++i; i < __x_.size(); ++i)
5131 if (__x_[i] == '%')
5132 break;
5133 if (i == __x_.size())
5134 break;
5135 ++i;
5136 if (__x_[i] == 'm')
5137 return time_base::ydm;
5138 break;
5139 }
5140 break;
5141 case 'm':
5142 for (++i; i < __x_.size(); ++i)
5143 if (__x_[i] == '%')
5144 break;
5145 if (i == __x_.size())
5146 break;
5147 ++i;
5148 if (__x_[i] == 'd')
5149 {
5150 for (++i; i < __x_.size(); ++i)
5151 if (__x_[i] == '%')
5152 break;
5153 if (i == __x_.size())
5154 break;
5155 ++i;
5156 if (__x_[i] == 'y' || __x_[i] == 'Y')
5157 return time_base::mdy;
5158 break;
5159 }
5160 break;
5161 case 'd':
5162 for (++i; i < __x_.size(); ++i)
5163 if (__x_[i] == '%')
5164 break;
5165 if (i == __x_.size())
5166 break;
5167 ++i;
5168 if (__x_[i] == 'm')
5169 {
5170 for (++i; i < __x_.size(); ++i)
5171 if (__x_[i] == '%')
5172 break;
5173 if (i == __x_.size())
5174 break;
5175 ++i;
5176 if (__x_[i] == 'y' || __x_[i] == 'Y')
5177 return time_base::dmy;
5178 break;
5179 }
5180 break;
5181 }
5182 return time_base::no_order;
5183}
5184
5185template <>
5186time_base::dateorder
5187__time_get_storage<wchar_t>::__do_date_order() const
5188{
5189 unsigned i;
5190 for (i = 0; i < __x_.size(); ++i)
5191 if (__x_[i] == L'%')
5192 break;
5193 ++i;
5194 switch (__x_[i])
5195 {
5196 case L'y':
5197 case L'Y':
5198 for (++i; i < __x_.size(); ++i)
5199 if (__x_[i] == L'%')
5200 break;
5201 if (i == __x_.size())
5202 break;
5203 ++i;
5204 switch (__x_[i])
5205 {
5206 case L'm':
5207 for (++i; i < __x_.size(); ++i)
5208 if (__x_[i] == L'%')
5209 break;
5210 if (i == __x_.size())
5211 break;
5212 ++i;
5213 if (__x_[i] == L'd')
5214 return time_base::ymd;
5215 break;
5216 case L'd':
5217 for (++i; i < __x_.size(); ++i)
5218 if (__x_[i] == L'%')
5219 break;
5220 if (i == __x_.size())
5221 break;
5222 ++i;
5223 if (__x_[i] == L'm')
5224 return time_base::ydm;
5225 break;
5226 }
5227 break;
5228 case L'm':
5229 for (++i; i < __x_.size(); ++i)
5230 if (__x_[i] == L'%')
5231 break;
5232 if (i == __x_.size())
5233 break;
5234 ++i;
5235 if (__x_[i] == L'd')
5236 {
5237 for (++i; i < __x_.size(); ++i)
5238 if (__x_[i] == L'%')
5239 break;
5240 if (i == __x_.size())
5241 break;
5242 ++i;
5243 if (__x_[i] == L'y' || __x_[i] == L'Y')
5244 return time_base::mdy;
5245 break;
5246 }
5247 break;
5248 case L'd':
5249 for (++i; i < __x_.size(); ++i)
5250 if (__x_[i] == L'%')
5251 break;
5252 if (i == __x_.size())
5253 break;
5254 ++i;
5255 if (__x_[i] == L'm')
5256 {
5257 for (++i; i < __x_.size(); ++i)
5258 if (__x_[i] == L'%')
5259 break;
5260 if (i == __x_.size())
5261 break;
5262 ++i;
5263 if (__x_[i] == L'y' || __x_[i] == L'Y')
5264 return time_base::dmy;
5265 break;
5266 }
5267 break;
5268 }
5269 return time_base::no_order;
5270}
5271
5272// time_put
5273
5274__time_put::__time_put(const char* nm)
5275 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5276{
Howard Hinnantd4444702010-08-11 17:04:31 +00005277#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005278 if (__loc_ == 0)
5279 throw runtime_error("time_put_byname"
5280 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005281#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005282}
5283
5284__time_put::__time_put(const string& nm)
5285 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5286{
Howard Hinnantd4444702010-08-11 17:04:31 +00005287#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005288 if (__loc_ == 0)
5289 throw runtime_error("time_put_byname"
5290 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005291#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005292}
5293
5294__time_put::~__time_put()
5295{
5296 if (__loc_)
5297 freelocale(__loc_);
5298}
5299
5300void
5301__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5302 char __fmt, char __mod) const
5303{
5304 char fmt[] = {'%', __fmt, __mod, 0};
5305 if (__mod != 0)
5306 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005307 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005308 __ne = __nb + n;
5309}
5310
5311void
5312__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5313 char __fmt, char __mod) const
5314{
5315 char __nar[100];
5316 char* __ne = __nar + 100;
5317 __do_put(__nar, __ne, __tm, __fmt, __mod);
5318 mbstate_t mb = {0};
5319 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005320#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005321 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005322#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005323 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005324#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005325 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005326 __throw_runtime_error("locale not supported");
5327 __we = __wb + j;
5328}
5329
5330// moneypunct_byname
5331
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005332template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005333static
5334void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005335__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5336 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5337 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005338{
5339 const char sign = static_cast<char>(money_base::sign);
5340 const char space = static_cast<char>(money_base::space);
5341 const char none = static_cast<char>(money_base::none);
5342 const char symbol = static_cast<char>(money_base::symbol);
5343 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005344 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5345
5346 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5347 // function'. "Space between sign and symbol or value" means that
5348 // if the sign is adjacent to the symbol, there's a space between
5349 // them, and otherwise there's a space between the sign and value.
5350 //
5351 // C11's localeconv specifies that the fourth character of an
5352 // international curr_symbol is used to separate the sign and
5353 // value when sep_by_space says to do so. C++ can't represent
5354 // that, so we just use a space. When sep_by_space says to
5355 // separate the symbol and value-or-sign with a space, we rearrange the
5356 // curr_symbol to put its spacing character on the correct side of
5357 // the symbol.
5358 //
5359 // We also need to avoid adding an extra space between the sign
5360 // and value when the currency symbol is suppressed (by not
5361 // setting showbase). We match glibc's strfmon by interpreting
5362 // sep_by_space==1 as "omit the space when the currency symbol is
5363 // absent".
5364 //
5365 // Users who want to get this right should use ICU instead.
5366
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005367 switch (cs_precedes)
5368 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005369 case 0: // value before curr_symbol
5370 if (symbol_contains_sep) {
5371 // Move the separator to before the symbol, to place it
5372 // between the value and symbol.
5373 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5374 __curr_symbol_.end());
5375 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005376 switch (sign_posn)
5377 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005378 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005379 pat.field[0] = sign;
5380 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005381 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005382 pat.field[3] = symbol;
5383 switch (sep_by_space)
5384 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005385 case 0: // No space separates the currency symbol and value.
5386 // This case may have changed between C99 and C11;
5387 // assume the currency symbol matches the intention.
5388 case 2: // Space between sign and currency or value.
5389 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005390 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005391 case 1: // Space between currency-and-sign or currency and value.
5392 if (!symbol_contains_sep) {
5393 // We insert the space into the symbol instead of
5394 // setting pat.field[2]=space so that when
5395 // showbase is not set, the space goes away too.
5396 __curr_symbol_.insert(0, 1, space_char);
5397 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005398 return;
5399 default:
5400 break;
5401 }
5402 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005403 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005404 pat.field[0] = sign;
5405 pat.field[3] = symbol;
5406 switch (sep_by_space)
5407 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005408 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005409 pat.field[1] = value;
5410 pat.field[2] = none;
5411 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005412 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005413 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005414 pat.field[2] = none;
5415 if (!symbol_contains_sep) {
5416 // We insert the space into the symbol instead of
5417 // setting pat.field[2]=space so that when
5418 // showbase is not set, the space goes away too.
5419 __curr_symbol_.insert(0, 1, space_char);
5420 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005421 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005422 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005423 pat.field[1] = space;
5424 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005425 if (symbol_contains_sep) {
5426 // Remove the separator from the symbol, since it
5427 // has already appeared after the sign.
5428 __curr_symbol_.erase(__curr_symbol_.begin());
5429 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005430 return;
5431 default:
5432 break;
5433 }
5434 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005435 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005436 pat.field[0] = value;
5437 pat.field[3] = sign;
5438 switch (sep_by_space)
5439 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005440 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005441 pat.field[1] = none;
5442 pat.field[2] = symbol;
5443 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005444 case 1: // Space between currency-and-sign or currency and value.
5445 if (!symbol_contains_sep) {
5446 // We insert the space into the symbol instead of
5447 // setting pat.field[1]=space so that when
5448 // showbase is not set, the space goes away too.
5449 __curr_symbol_.insert(0, 1, space_char);
5450 }
5451 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005452 pat.field[2] = symbol;
5453 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005454 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005455 pat.field[1] = symbol;
5456 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005457 if (symbol_contains_sep) {
5458 // Remove the separator from the symbol, since it
5459 // should not be removed if showbase is absent.
5460 __curr_symbol_.erase(__curr_symbol_.begin());
5461 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005462 return;
5463 default:
5464 break;
5465 }
5466 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005467 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005468 pat.field[0] = value;
5469 pat.field[3] = symbol;
5470 switch (sep_by_space)
5471 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005472 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005473 pat.field[1] = none;
5474 pat.field[2] = sign;
5475 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005476 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005477 pat.field[1] = space;
5478 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005479 if (symbol_contains_sep) {
5480 // Remove the separator from the symbol, since it
5481 // has already appeared before the sign.
5482 __curr_symbol_.erase(__curr_symbol_.begin());
5483 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005484 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005485 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005486 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005487 pat.field[2] = none;
5488 if (!symbol_contains_sep) {
5489 // We insert the space into the symbol instead of
5490 // setting pat.field[2]=space so that when
5491 // showbase is not set, the space goes away too.
5492 __curr_symbol_.insert(0, 1, space_char);
5493 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005494 return;
5495 default:
5496 break;
5497 }
5498 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005499 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005500 pat.field[0] = value;
5501 pat.field[3] = sign;
5502 switch (sep_by_space)
5503 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005504 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005505 pat.field[1] = none;
5506 pat.field[2] = symbol;
5507 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005508 case 1: // Space between currency-and-sign or currency and value.
5509 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005510 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005511 if (!symbol_contains_sep) {
5512 // We insert the space into the symbol instead of
5513 // setting pat.field[1]=space so that when
5514 // showbase is not set, the space goes away too.
5515 __curr_symbol_.insert(0, 1, space_char);
5516 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005517 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005518 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005519 pat.field[1] = symbol;
5520 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005521 if (symbol_contains_sep) {
5522 // Remove the separator from the symbol, since it
5523 // should not disappear when showbase is absent.
5524 __curr_symbol_.erase(__curr_symbol_.begin());
5525 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005526 return;
5527 default:
5528 break;
5529 }
5530 break;
5531 default:
5532 break;
5533 }
5534 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005535 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005536 switch (sign_posn)
5537 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005538 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005539 pat.field[0] = sign;
5540 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005541 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005542 pat.field[3] = value;
5543 switch (sep_by_space)
5544 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005545 case 0: // No space separates the currency symbol and value.
5546 // This case may have changed between C99 and C11;
5547 // assume the currency symbol matches the intention.
5548 case 2: // Space between sign and currency or value.
5549 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005550 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005551 case 1: // Space between currency-and-sign or currency and value.
5552 if (!symbol_contains_sep) {
5553 // We insert the space into the symbol instead of
5554 // setting pat.field[2]=space so that when
5555 // showbase is not set, the space goes away too.
5556 __curr_symbol_.insert(0, 1, space_char);
5557 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005558 return;
5559 default:
5560 break;
5561 }
5562 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005563 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005564 pat.field[0] = sign;
5565 pat.field[3] = value;
5566 switch (sep_by_space)
5567 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005568 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005569 pat.field[1] = symbol;
5570 pat.field[2] = none;
5571 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005572 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005573 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005574 pat.field[2] = none;
5575 if (!symbol_contains_sep) {
5576 // We insert the space into the symbol instead of
5577 // setting pat.field[2]=space so that when
5578 // showbase is not set, the space goes away too.
5579 __curr_symbol_.push_back(space_char);
5580 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005581 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005582 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005583 pat.field[1] = space;
5584 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005585 if (symbol_contains_sep) {
5586 // Remove the separator from the symbol, since it
5587 // has already appeared after the sign.
5588 __curr_symbol_.pop_back();
5589 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005590 return;
5591 default:
5592 break;
5593 }
5594 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005595 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005596 pat.field[0] = symbol;
5597 pat.field[3] = sign;
5598 switch (sep_by_space)
5599 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005600 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005601 pat.field[1] = none;
5602 pat.field[2] = value;
5603 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005604 case 1: // Space between currency-and-sign or currency and value.
5605 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005606 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005607 if (!symbol_contains_sep) {
5608 // We insert the space into the symbol instead of
5609 // setting pat.field[1]=space so that when
5610 // showbase is not set, the space goes away too.
5611 __curr_symbol_.push_back(space_char);
5612 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005613 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005614 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005615 pat.field[1] = value;
5616 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005617 if (symbol_contains_sep) {
5618 // Remove the separator from the symbol, since it
5619 // will appear before the sign.
5620 __curr_symbol_.pop_back();
5621 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005622 return;
5623 default:
5624 break;
5625 }
5626 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005627 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005628 pat.field[0] = sign;
5629 pat.field[3] = value;
5630 switch (sep_by_space)
5631 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005632 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005633 pat.field[1] = symbol;
5634 pat.field[2] = none;
5635 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005636 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005637 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005638 pat.field[2] = none;
5639 if (!symbol_contains_sep) {
5640 // We insert the space into the symbol instead of
5641 // setting pat.field[2]=space so that when
5642 // showbase is not set, the space goes away too.
5643 __curr_symbol_.push_back(space_char);
5644 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005645 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005646 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005647 pat.field[1] = space;
5648 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005649 if (symbol_contains_sep) {
5650 // Remove the separator from the symbol, since it
5651 // has already appeared after the sign.
5652 __curr_symbol_.pop_back();
5653 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005654 return;
5655 default:
5656 break;
5657 }
5658 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005659 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005660 pat.field[0] = symbol;
5661 pat.field[3] = value;
5662 switch (sep_by_space)
5663 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005664 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005665 pat.field[1] = sign;
5666 pat.field[2] = none;
5667 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005668 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005669 pat.field[1] = sign;
5670 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005671 if (symbol_contains_sep) {
5672 // Remove the separator from the symbol, since it
5673 // should not disappear when showbase is absent.
5674 __curr_symbol_.pop_back();
5675 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005676 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005677 case 2: // Space between sign and currency or value.
5678 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005679 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005680 if (!symbol_contains_sep) {
5681 // We insert the space into the symbol instead of
5682 // setting pat.field[1]=space so that when
5683 // showbase is not set, the space goes away too.
5684 __curr_symbol_.push_back(space_char);
5685 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005686 return;
5687 default:
5688 break;
5689 }
5690 break;
5691 default:
5692 break;
5693 }
5694 break;
5695 default:
5696 break;
5697 }
5698 pat.field[0] = symbol;
5699 pat.field[1] = sign;
5700 pat.field[2] = none;
5701 pat.field[3] = value;
5702}
5703
5704template<>
5705void
5706moneypunct_byname<char, false>::init(const char* nm)
5707{
5708 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005709 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005710#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005711 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005712 throw runtime_error("moneypunct_byname"
5713 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005714#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005715#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005716 lconv* lc = localeconv_l(loc.get());
5717#else
5718 lconv* lc = __localeconv_l(loc.get());
5719#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005720 if (*lc->mon_decimal_point)
5721 __decimal_point_ = *lc->mon_decimal_point;
5722 else
5723 __decimal_point_ = base::do_decimal_point();
5724 if (*lc->mon_thousands_sep)
5725 __thousands_sep_ = *lc->mon_thousands_sep;
5726 else
5727 __thousands_sep_ = base::do_thousands_sep();
5728 __grouping_ = lc->mon_grouping;
5729 __curr_symbol_ = lc->currency_symbol;
5730 if (lc->frac_digits != CHAR_MAX)
5731 __frac_digits_ = lc->frac_digits;
5732 else
5733 __frac_digits_ = base::do_frac_digits();
5734 if (lc->p_sign_posn == 0)
5735 __positive_sign_ = "()";
5736 else
5737 __positive_sign_ = lc->positive_sign;
5738 if (lc->n_sign_posn == 0)
5739 __negative_sign_ = "()";
5740 else
5741 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005742 // Assume the positive and negative formats will want spaces in
5743 // the same places in curr_symbol since there's no way to
5744 // represent anything else.
5745 string_type __dummy_curr_symbol = __curr_symbol_;
5746 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5747 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5748 __init_pat(__neg_format_, __curr_symbol_, false,
5749 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005750}
5751
5752template<>
5753void
5754moneypunct_byname<char, true>::init(const char* nm)
5755{
5756 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005757 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005758#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005759 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005760 throw runtime_error("moneypunct_byname"
5761 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005762#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005763#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005764 lconv* lc = localeconv_l(loc.get());
5765#else
5766 lconv* lc = __localeconv_l(loc.get());
5767#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005768 if (*lc->mon_decimal_point)
5769 __decimal_point_ = *lc->mon_decimal_point;
5770 else
5771 __decimal_point_ = base::do_decimal_point();
5772 if (*lc->mon_thousands_sep)
5773 __thousands_sep_ = *lc->mon_thousands_sep;
5774 else
5775 __thousands_sep_ = base::do_thousands_sep();
5776 __grouping_ = lc->mon_grouping;
5777 __curr_symbol_ = lc->int_curr_symbol;
5778 if (lc->int_frac_digits != CHAR_MAX)
5779 __frac_digits_ = lc->int_frac_digits;
5780 else
5781 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005782#if _WIN32
5783 if (lc->p_sign_posn == 0)
5784#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005785 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005786#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005787 __positive_sign_ = "()";
5788 else
5789 __positive_sign_ = lc->positive_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005790#if _WIN32
5791 if(lc->n_sign_posn == 0)
5792#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005793 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005794#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005795 __negative_sign_ = "()";
5796 else
5797 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005798 // Assume the positive and negative formats will want spaces in
5799 // the same places in curr_symbol since there's no way to
5800 // represent anything else.
5801 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005802#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005803 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5804 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5805 __init_pat(__neg_format_, __curr_symbol_, true,
5806 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005807#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005808 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5809 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5810 lc->int_p_sign_posn, ' ');
5811 __init_pat(__neg_format_, __curr_symbol_, true,
5812 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5813 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005814#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005815}
5816
5817template<>
5818void
5819moneypunct_byname<wchar_t, false>::init(const char* nm)
5820{
5821 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005822 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005823#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005824 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005825 throw runtime_error("moneypunct_byname"
5826 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005827#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005828#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005829 lconv* lc = localeconv_l(loc.get());
5830#else
5831 lconv* lc = __localeconv_l(loc.get());
5832#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005833 if (*lc->mon_decimal_point)
5834 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5835 else
5836 __decimal_point_ = base::do_decimal_point();
5837 if (*lc->mon_thousands_sep)
5838 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5839 else
5840 __thousands_sep_ = base::do_thousands_sep();
5841 __grouping_ = lc->mon_grouping;
5842 wchar_t wbuf[100];
5843 mbstate_t mb = {0};
5844 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005845#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005846 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005847#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005848 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005849#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005850 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005851 __throw_runtime_error("locale not supported");
5852 wchar_t* wbe = wbuf + j;
5853 __curr_symbol_.assign(wbuf, wbe);
5854 if (lc->frac_digits != CHAR_MAX)
5855 __frac_digits_ = lc->frac_digits;
5856 else
5857 __frac_digits_ = base::do_frac_digits();
5858 if (lc->p_sign_posn == 0)
5859 __positive_sign_ = L"()";
5860 else
5861 {
5862 mb = mbstate_t();
5863 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005864#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005865 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005866#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005867 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005868#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005869 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005870 __throw_runtime_error("locale not supported");
5871 wbe = wbuf + j;
5872 __positive_sign_.assign(wbuf, wbe);
5873 }
5874 if (lc->n_sign_posn == 0)
5875 __negative_sign_ = L"()";
5876 else
5877 {
5878 mb = mbstate_t();
5879 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005880#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005881 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005882#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005883 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005884#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005885 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005886 __throw_runtime_error("locale not supported");
5887 wbe = wbuf + j;
5888 __negative_sign_.assign(wbuf, wbe);
5889 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005890 // Assume the positive and negative formats will want spaces in
5891 // the same places in curr_symbol since there's no way to
5892 // represent anything else.
5893 string_type __dummy_curr_symbol = __curr_symbol_;
5894 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5895 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5896 __init_pat(__neg_format_, __curr_symbol_, false,
5897 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005898}
5899
5900template<>
5901void
5902moneypunct_byname<wchar_t, true>::init(const char* nm)
5903{
5904 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005905 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005906#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005907 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005908 throw runtime_error("moneypunct_byname"
5909 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005910#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005911#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005912 lconv* lc = localeconv_l(loc.get());
5913#else
5914 lconv* lc = __localeconv_l(loc.get());
5915#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005916 if (*lc->mon_decimal_point)
5917 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5918 else
5919 __decimal_point_ = base::do_decimal_point();
5920 if (*lc->mon_thousands_sep)
5921 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5922 else
5923 __thousands_sep_ = base::do_thousands_sep();
5924 __grouping_ = lc->mon_grouping;
5925 wchar_t wbuf[100];
5926 mbstate_t mb = {0};
5927 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005928#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005929 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005930#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005931 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005932#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005933 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005934 __throw_runtime_error("locale not supported");
5935 wchar_t* wbe = wbuf + j;
5936 __curr_symbol_.assign(wbuf, wbe);
5937 if (lc->int_frac_digits != CHAR_MAX)
5938 __frac_digits_ = lc->int_frac_digits;
5939 else
5940 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005941#if _WIN32
5942 if (lc->p_sign_posn == 0)
5943#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005944 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005945#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005946 __positive_sign_ = L"()";
5947 else
5948 {
5949 mb = mbstate_t();
5950 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005951#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005952 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005953#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005954 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005955#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005956 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005957 __throw_runtime_error("locale not supported");
5958 wbe = wbuf + j;
5959 __positive_sign_.assign(wbuf, wbe);
5960 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005961#if _WIN32
5962 if (lc->n_sign_posn == 0)
5963#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005964 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005965#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005966 __negative_sign_ = L"()";
5967 else
5968 {
5969 mb = mbstate_t();
5970 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005971#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005972 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005973#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005974 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005975#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005976 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005977 __throw_runtime_error("locale not supported");
5978 wbe = wbuf + j;
5979 __negative_sign_.assign(wbuf, wbe);
5980 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005981 // Assume the positive and negative formats will want spaces in
5982 // the same places in curr_symbol since there's no way to
5983 // represent anything else.
5984 string_type __dummy_curr_symbol = __curr_symbol_;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005985#if _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005986 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5987 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5988 __init_pat(__neg_format_, __curr_symbol_, true,
5989 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005990#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005991 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5992 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5993 lc->int_p_sign_posn, L' ');
5994 __init_pat(__neg_format_, __curr_symbol_, true,
5995 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5996 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005997#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005998}
5999
6000void __do_nothing(void*) {}
6001
6002void __throw_runtime_error(const char* msg)
6003{
Howard Hinnantd4444702010-08-11 17:04:31 +00006004#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006005 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00006006#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006007}
6008
6009template class collate<char>;
6010template class collate<wchar_t>;
6011
6012template class num_get<char>;
6013template class num_get<wchar_t>;
6014
Howard Hinnantec3773c2011-12-01 20:21:04 +00006015template struct __num_get<char>;
6016template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006017
6018template class num_put<char>;
6019template class num_put<wchar_t>;
6020
Howard Hinnantec3773c2011-12-01 20:21:04 +00006021template struct __num_put<char>;
6022template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006023
6024template class time_get<char>;
6025template class time_get<wchar_t>;
6026
6027template class time_get_byname<char>;
6028template class time_get_byname<wchar_t>;
6029
6030template class time_put<char>;
6031template class time_put<wchar_t>;
6032
6033template class time_put_byname<char>;
6034template class time_put_byname<wchar_t>;
6035
6036template class moneypunct<char, false>;
6037template class moneypunct<char, true>;
6038template class moneypunct<wchar_t, false>;
6039template class moneypunct<wchar_t, true>;
6040
6041template class moneypunct_byname<char, false>;
6042template class moneypunct_byname<char, true>;
6043template class moneypunct_byname<wchar_t, false>;
6044template class moneypunct_byname<wchar_t, true>;
6045
6046template class money_get<char>;
6047template class money_get<wchar_t>;
6048
6049template class __money_get<char>;
6050template class __money_get<wchar_t>;
6051
6052template class money_put<char>;
6053template class money_put<wchar_t>;
6054
6055template class __money_put<char>;
6056template class __money_put<wchar_t>;
6057
6058template class messages<char>;
6059template class messages<wchar_t>;
6060
6061template class messages_byname<char>;
6062template class messages_byname<wchar_t>;
6063
6064template class codecvt_byname<char, char, mbstate_t>;
6065template class codecvt_byname<wchar_t, char, mbstate_t>;
6066template class codecvt_byname<char16_t, char, mbstate_t>;
6067template class codecvt_byname<char32_t, char, mbstate_t>;
6068
6069template class __vector_base_common<true>;
6070
6071_LIBCPP_END_NAMESPACE_STD