blob: c459bede0986d6e28dcea4aa14f0b6c463f42dc1 [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"
Marshall Clowa22d2ad2013-03-18 17:04:29 +000028#ifdef _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;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000789#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
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;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000802#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
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;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000816#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
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;
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000829#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
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 Hinnantfc2f0212013-03-29 18:27:28 +0000896#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
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 Hinnantfc2f0212013-03-29 18:27:28 +0000911#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
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 Hinnantfc2f0212013-03-29 18:27:28 +0000926#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
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 Hinnantfc2f0212013-03-29 18:27:28 +0000940#elif defined(__GLIBC__) || defined(EMSCRIPTEN)
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
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000981#ifdef EMSCRIPTEN
982extern "C" const unsigned short ** __ctype_b_loc();
983extern "C" const int ** __ctype_tolower_loc();
984extern "C" const int ** __ctype_toupper_loc();
985#endif
986
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000987const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000988ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000989{
David Chisnallc512df12011-09-21 08:39:44 +0000990#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000991 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000992#elif defined(__GLIBC__)
993 return __cloc()->__ctype_b;
David Chisnall997e4542012-02-29 13:05:08 +0000994#elif __sun__
995 return __ctype_mask;
Marshall Clowa22d2ad2013-03-18 17:04:29 +0000996#elif defined(_WIN32)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000997 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +0000998// This is assumed to be safe, which is a nonsense assumption because we're
999// going to end up dereferencing it later...
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001000#elif defined(EMSCRIPTEN)
1001 return *__ctype_b_loc();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001002#else
David Chisnall997e4542012-02-29 13:05:08 +00001003 // Platform not supported: abort so the person doing the port knows what to
1004 // fix
Howard Hinnantfcbaf482012-02-29 16:08:57 +00001005# warning ctype<char>::classic_table() is not implemented
David Chisnall997e4542012-02-29 13:05:08 +00001006 abort();
Sean Hunt62a6ac32011-07-09 00:56:23 +00001007 return NULL;
1008#endif
1009}
1010
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001011#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +00001012const int*
1013ctype<char>::__classic_lower_table() _NOEXCEPT
1014{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001015 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +00001016}
1017
1018const int*
1019ctype<char>::__classic_upper_table() _NOEXCEPT
1020{
Sean Hunt62a6ac32011-07-09 00:56:23 +00001021 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001022}
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001023#endif // __GLIBC__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001024
Howard Hinnantfc2f0212013-03-29 18:27:28 +00001025#if defined(EMSCRIPTEN)
1026const int*
1027ctype<char>::__classic_lower_table() _NOEXCEPT
1028{
1029 return *__ctype_tolower_loc();
1030}
1031
1032const int*
1033ctype<char>::__classic_upper_table() _NOEXCEPT
1034{
1035 return *__ctype_toupper_loc();
1036}
1037#endif // EMSCRIPTEN
1038
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001039// template <> class ctype_byname<char>
1040
1041ctype_byname<char>::ctype_byname(const char* name, size_t refs)
1042 : ctype<char>(0, false, refs),
1043 __l(newlocale(LC_ALL_MASK, name, 0))
1044{
Howard Hinnantd4444702010-08-11 17:04:31 +00001045#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001046 if (__l == 0)
1047 throw runtime_error("ctype_byname<char>::ctype_byname"
1048 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001049#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001050}
1051
1052ctype_byname<char>::ctype_byname(const string& name, size_t refs)
1053 : ctype<char>(0, false, refs),
1054 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1055{
Howard Hinnantd4444702010-08-11 17:04:31 +00001056#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001057 if (__l == 0)
1058 throw runtime_error("ctype_byname<char>::ctype_byname"
1059 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001060#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001061}
1062
1063ctype_byname<char>::~ctype_byname()
1064{
1065 freelocale(__l);
1066}
1067
1068char
1069ctype_byname<char>::do_toupper(char_type c) const
1070{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001071 return static_cast<char>(toupper_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001072}
1073
1074const char*
1075ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
1076{
1077 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001078 *low = static_cast<char>(toupper_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001079 return low;
1080}
1081
1082char
1083ctype_byname<char>::do_tolower(char_type c) const
1084{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001085 return static_cast<char>(tolower_l(c, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001086}
1087
1088const char*
1089ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
1090{
1091 for (; low != high; ++low)
Howard Hinnantec3773c2011-12-01 20:21:04 +00001092 *low = static_cast<char>(tolower_l(*low, __l));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001093 return low;
1094}
1095
1096// template <> class ctype_byname<wchar_t>
1097
1098ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1099 : ctype<wchar_t>(refs),
1100 __l(newlocale(LC_ALL_MASK, name, 0))
1101{
Howard Hinnantd4444702010-08-11 17:04:31 +00001102#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001103 if (__l == 0)
1104 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1105 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001106#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001107}
1108
1109ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1110 : ctype<wchar_t>(refs),
1111 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1112{
Howard Hinnantd4444702010-08-11 17:04:31 +00001113#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001114 if (__l == 0)
1115 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1116 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001117#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001118}
1119
1120ctype_byname<wchar_t>::~ctype_byname()
1121{
1122 freelocale(__l);
1123}
1124
1125bool
1126ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1127{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001128#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001129 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001130#else
Howard Hinnantef793f22012-08-02 18:35:07 +00001131 bool result = false;
Marshall Clow88c31902013-02-07 14:22:51 +00001132 wint_t ch = static_cast<wint_t>(c);
1133 if (m & space) result |= (iswspace_l(ch, __l) != 0);
1134 if (m & print) result |= (iswprint_l(ch, __l) != 0);
1135 if (m & cntrl) result |= (iswcntrl_l(ch, __l) != 0);
1136 if (m & upper) result |= (iswupper_l(ch, __l) != 0);
1137 if (m & lower) result |= (iswlower_l(ch, __l) != 0);
1138 if (m & alpha) result |= (iswalpha_l(ch, __l) != 0);
1139 if (m & digit) result |= (iswdigit_l(ch, __l) != 0);
1140 if (m & punct) result |= (iswpunct_l(ch, __l) != 0);
1141 if (m & xdigit) result |= (iswxdigit_l(ch, __l) != 0);
1142 if (m & blank) result |= (iswblank_l(ch, __l) != 0);
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001143 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001144#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001145}
1146
1147const wchar_t*
1148ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1149{
1150 for (; low != high; ++low, ++vec)
1151 {
1152 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001153 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001154 else
1155 {
1156 *vec = 0;
Marshall Clow88c31902013-02-07 14:22:51 +00001157 wint_t ch = static_cast<wint_t>(*low);
1158 if (iswspace_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001159 *vec |= space;
Marshall Clow88c31902013-02-07 14:22:51 +00001160 if (iswprint_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001161 *vec |= print;
Marshall Clow88c31902013-02-07 14:22:51 +00001162 if (iswcntrl_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001163 *vec |= cntrl;
Marshall Clow88c31902013-02-07 14:22:51 +00001164 if (iswupper_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001165 *vec |= upper;
Marshall Clow88c31902013-02-07 14:22:51 +00001166 if (iswlower_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001167 *vec |= lower;
Marshall Clow88c31902013-02-07 14:22:51 +00001168 if (iswalpha_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001169 *vec |= alpha;
Marshall Clow88c31902013-02-07 14:22:51 +00001170 if (iswdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001171 *vec |= digit;
Marshall Clow88c31902013-02-07 14:22:51 +00001172 if (iswpunct_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001173 *vec |= punct;
Marshall Clow88c31902013-02-07 14:22:51 +00001174 if (iswxdigit_l(ch, __l))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001175 *vec |= xdigit;
1176 }
1177 }
1178 return low;
1179}
1180
1181const wchar_t*
1182ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1183{
1184 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001185 {
1186#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001187 if (iswctype_l(*low, m, __l))
1188 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001189#else
Marshall Clow88c31902013-02-07 14:22:51 +00001190 wint_t ch = static_cast<wint_t>(*low);
1191 if (m & space && iswspace_l(ch, __l)) break;
1192 if (m & print && iswprint_l(ch, __l)) break;
1193 if (m & cntrl && iswcntrl_l(ch, __l)) break;
1194 if (m & upper && iswupper_l(ch, __l)) break;
1195 if (m & lower && iswlower_l(ch, __l)) break;
1196 if (m & alpha && iswalpha_l(ch, __l)) break;
1197 if (m & digit && iswdigit_l(ch, __l)) break;
1198 if (m & punct && iswpunct_l(ch, __l)) break;
1199 if (m & xdigit && iswxdigit_l(ch, __l)) break;
1200 if (m & blank && iswblank_l(ch, __l)) break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001201#endif
1202 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001203 return low;
1204}
1205
1206const wchar_t*
1207ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1208{
1209 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001210 {
1211#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001212 if (!iswctype_l(*low, m, __l))
1213 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001214#else
Marshall Clow88c31902013-02-07 14:22:51 +00001215 wint_t ch = static_cast<wint_t>(*low);
1216 if (m & space && iswspace_l(ch, __l)) continue;
1217 if (m & print && iswprint_l(ch, __l)) continue;
1218 if (m & cntrl && iswcntrl_l(ch, __l)) continue;
1219 if (m & upper && iswupper_l(ch, __l)) continue;
1220 if (m & lower && iswlower_l(ch, __l)) continue;
1221 if (m & alpha && iswalpha_l(ch, __l)) continue;
1222 if (m & digit && iswdigit_l(ch, __l)) continue;
1223 if (m & punct && iswpunct_l(ch, __l)) continue;
1224 if (m & xdigit && iswxdigit_l(ch, __l)) continue;
1225 if (m & blank && iswblank_l(ch, __l)) continue;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001226 break;
1227#endif
1228 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001229 return low;
1230}
1231
1232wchar_t
1233ctype_byname<wchar_t>::do_toupper(char_type c) const
1234{
1235 return towupper_l(c, __l);
1236}
1237
1238const wchar_t*
1239ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1240{
1241 for (; low != high; ++low)
1242 *low = towupper_l(*low, __l);
1243 return low;
1244}
1245
1246wchar_t
1247ctype_byname<wchar_t>::do_tolower(char_type c) const
1248{
1249 return towlower_l(c, __l);
1250}
1251
1252const wchar_t*
1253ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1254{
1255 for (; low != high; ++low)
1256 *low = towlower_l(*low, __l);
1257 return low;
1258}
1259
1260wchar_t
1261ctype_byname<wchar_t>::do_widen(char c) const
1262{
Howard Hinnant866569b2011-09-28 23:39:33 +00001263#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001264 return btowc_l(c, __l);
1265#else
1266 return __btowc_l(c, __l);
1267#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001268}
1269
1270const char*
1271ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1272{
1273 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001274#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001275 *dest = btowc_l(*low, __l);
1276#else
1277 *dest = __btowc_l(*low, __l);
1278#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001279 return low;
1280}
1281
1282char
1283ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1284{
Howard Hinnant866569b2011-09-28 23:39:33 +00001285#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001286 int r = wctob_l(c, __l);
1287#else
1288 int r = __wctob_l(c, __l);
1289#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001290 return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001291}
1292
1293const wchar_t*
1294ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1295{
1296 for (; low != high; ++low, ++dest)
1297 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001298#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001299 int r = wctob_l(*low, __l);
1300#else
1301 int r = __wctob_l(*low, __l);
1302#endif
Howard Hinnantc6e54b92012-12-27 18:46:00 +00001303 *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001304 }
1305 return low;
1306}
1307
1308// template <> class codecvt<char, char, mbstate_t>
1309
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001310locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001311
1312codecvt<char, char, mbstate_t>::~codecvt()
1313{
1314}
1315
1316codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001317codecvt<char, char, mbstate_t>::do_out(state_type&,
1318 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001319 extern_type* to, extern_type*, extern_type*& to_nxt) const
1320{
1321 frm_nxt = frm;
1322 to_nxt = to;
1323 return noconv;
1324}
1325
1326codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001327codecvt<char, char, mbstate_t>::do_in(state_type&,
1328 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001329 intern_type* to, intern_type*, intern_type*& to_nxt) const
1330{
1331 frm_nxt = frm;
1332 to_nxt = to;
1333 return noconv;
1334}
1335
1336codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001337codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001338 extern_type* to, extern_type*, extern_type*& to_nxt) const
1339{
1340 to_nxt = to;
1341 return noconv;
1342}
1343
1344int
Howard Hinnantc9834542011-05-31 15:34:58 +00001345codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001346{
1347 return 1;
1348}
1349
1350bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001351codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001352{
1353 return true;
1354}
1355
1356int
1357codecvt<char, char, mbstate_t>::do_length(state_type&,
1358 const extern_type* frm, const extern_type* end, size_t mx) const
1359{
Howard Hinnantec3773c2011-12-01 20:21:04 +00001360 return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001361}
1362
1363int
Howard Hinnantc9834542011-05-31 15:34:58 +00001364codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001365{
1366 return 1;
1367}
1368
1369// template <> class codecvt<wchar_t, char, mbstate_t>
1370
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001371locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001372
1373codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1374 : locale::facet(refs),
1375 __l(0)
1376{
1377}
1378
1379codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1380 : locale::facet(refs),
1381 __l(newlocale(LC_ALL_MASK, nm, 0))
1382{
Howard Hinnantd4444702010-08-11 17:04:31 +00001383#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001384 if (__l == 0)
1385 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1386 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001387#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001388}
1389
1390codecvt<wchar_t, char, mbstate_t>::~codecvt()
1391{
1392 if (__l != 0)
1393 freelocale(__l);
1394}
1395
1396codecvt<wchar_t, char, mbstate_t>::result
1397codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001398 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001399 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1400{
1401 // look for first internal null in frm
1402 const intern_type* fend = frm;
1403 for (; fend != frm_end; ++fend)
1404 if (*fend == 0)
1405 break;
1406 // loop over all null-terminated sequences in frm
1407 to_nxt = to;
1408 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1409 {
1410 // save state in case needed to reover to_nxt on error
1411 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001412#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001413 size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1414 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001415#else
1416 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1417#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001418 if (n == size_t(-1))
1419 {
1420 // need to recover to_nxt
1421 for (to_nxt = to; frm != frm_nxt; ++frm)
1422 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001423#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001424 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1425#else
1426 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1427#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001428 if (n == size_t(-1))
1429 break;
1430 to_nxt += n;
1431 }
1432 frm_nxt = frm;
1433 return error;
1434 }
1435 if (n == 0)
1436 return partial;
1437 to_nxt += n;
1438 if (to_nxt == to_end)
1439 break;
1440 if (fend != frm_end) // set up next null terminated sequence
1441 {
1442 // Try to write the terminating null
1443 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001444#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001445 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1446#else
1447 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1448#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001449 if (n == size_t(-1)) // on error
1450 return error;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001451 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001452 return partial;
1453 for (extern_type* p = tmp; n; --n) // write it
1454 *to_nxt++ = *p++;
1455 ++frm_nxt;
1456 // look for next null in frm
1457 for (fend = frm_nxt; fend != frm_end; ++fend)
1458 if (*fend == 0)
1459 break;
1460 }
1461 }
1462 return frm_nxt == frm_end ? ok : partial;
1463}
1464
1465codecvt<wchar_t, char, mbstate_t>::result
1466codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001467 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001468 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1469{
1470 // look for first internal null in frm
1471 const extern_type* fend = frm;
1472 for (; fend != frm_end; ++fend)
1473 if (*fend == 0)
1474 break;
1475 // loop over all null-terminated sequences in frm
1476 to_nxt = to;
1477 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1478 {
1479 // save state in case needed to reover to_nxt on error
1480 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001481#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001482 size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm),
1483 static_cast<size_t>(to_end-to), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001484#else
1485 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1486#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001487 if (n == size_t(-1))
1488 {
1489 // need to recover to_nxt
1490 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1491 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001492#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001493 n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm),
1494 &save_state, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001495#else
1496 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1497#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001498 switch (n)
1499 {
1500 case 0:
1501 ++frm;
1502 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001503 case size_t(-1):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001504 frm_nxt = frm;
1505 return error;
Howard Hinnant982331b2012-02-08 19:15:06 +00001506 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001507 frm_nxt = frm;
1508 return partial;
1509 default:
1510 frm += n;
1511 break;
1512 }
1513 }
1514 frm_nxt = frm;
1515 return frm_nxt == frm_end ? ok : partial;
1516 }
1517 if (n == 0)
1518 return error;
1519 to_nxt += n;
1520 if (to_nxt == to_end)
1521 break;
1522 if (fend != frm_end) // set up next null terminated sequence
1523 {
1524 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001525#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001526 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1527#else
1528 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1529#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001530 if (n != 0) // on error
1531 return error;
1532 ++to_nxt;
1533 ++frm_nxt;
1534 // look for next null in frm
1535 for (fend = frm_nxt; fend != frm_end; ++fend)
1536 if (*fend == 0)
1537 break;
1538 }
1539 }
1540 return frm_nxt == frm_end ? ok : partial;
1541}
1542
1543codecvt<wchar_t, char, mbstate_t>::result
1544codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1545 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1546{
1547 to_nxt = to;
1548 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001549#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001550 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1551#else
1552 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1553#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001554 if (n == size_t(-1) || n == 0) // on error
1555 return error;
1556 --n;
Howard Hinnantec3773c2011-12-01 20:21:04 +00001557 if (n > static_cast<size_t>(to_end-to_nxt)) // is there room?
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001558 return partial;
1559 for (extern_type* p = tmp; n; --n) // write it
1560 *to_nxt++ = *p++;
1561 return ok;
1562}
1563
1564int
Howard Hinnantc9834542011-05-31 15:34:58 +00001565codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001566{
Howard Hinnant866569b2011-09-28 23:39:33 +00001567#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001568 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1569#else
1570 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1571#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001572 {
1573 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001574#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001575 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1576#else
1577 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1578#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001579 return 1; // which take more than 1 char to form a wchar_t
1580 return 0;
1581 }
1582 return -1;
1583}
1584
1585bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001586codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001587{
1588 return false;
1589}
1590
1591int
1592codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1593 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1594{
1595 int nbytes = 0;
1596 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1597 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001598#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantec3773c2011-12-01 20:21:04 +00001599 size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l);
Sean Huntf3907e62011-07-15 05:40:33 +00001600#else
1601 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1602#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001603 switch (n)
1604 {
1605 case 0:
1606 ++nbytes;
1607 ++frm;
1608 break;
Howard Hinnant982331b2012-02-08 19:15:06 +00001609 case size_t(-1):
1610 case size_t(-2):
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001611 return nbytes;
1612 default:
1613 nbytes += n;
1614 frm += n;
1615 break;
1616 }
1617 }
1618 return nbytes;
1619}
1620
1621int
Howard Hinnantc9834542011-05-31 15:34:58 +00001622codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001623{
Howard Hinnant866569b2011-09-28 23:39:33 +00001624#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Marshall Clow9ae96d02013-02-07 17:20:56 +00001625 return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001626#else
Marshall Clow9ae96d02013-02-07 17:20:56 +00001627 return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l));
Sean Huntf3907e62011-07-15 05:40:33 +00001628#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001629}
1630
1631// Valid UTF ranges
1632// UTF-32 UTF-16 UTF-8 # of code points
1633// first second first second third fourth
1634// 000000 - 00007F 0000 - 007F 00 - 7F 127
1635// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1636// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1637// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1638// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1639// 00D800 - 00DFFF invalid
1640// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1641// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1642// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1643// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1644
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001645static
1646codecvt_base::result
1647utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1648 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1649 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1650{
1651 frm_nxt = frm;
1652 to_nxt = to;
1653 if (mode & generate_header)
1654 {
1655 if (to_end-to_nxt < 3)
1656 return codecvt_base::partial;
1657 *to_nxt++ = static_cast<uint8_t>(0xEF);
1658 *to_nxt++ = static_cast<uint8_t>(0xBB);
1659 *to_nxt++ = static_cast<uint8_t>(0xBF);
1660 }
1661 for (; frm_nxt < frm_end; ++frm_nxt)
1662 {
1663 uint16_t wc1 = *frm_nxt;
1664 if (wc1 > Maxcode)
1665 return codecvt_base::error;
1666 if (wc1 < 0x0080)
1667 {
1668 if (to_end-to_nxt < 1)
1669 return codecvt_base::partial;
1670 *to_nxt++ = static_cast<uint8_t>(wc1);
1671 }
1672 else if (wc1 < 0x0800)
1673 {
1674 if (to_end-to_nxt < 2)
1675 return codecvt_base::partial;
1676 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1677 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1678 }
1679 else if (wc1 < 0xD800)
1680 {
1681 if (to_end-to_nxt < 3)
1682 return codecvt_base::partial;
1683 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1684 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1685 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1686 }
1687 else if (wc1 < 0xDC00)
1688 {
1689 if (frm_end-frm_nxt < 2)
1690 return codecvt_base::partial;
1691 uint16_t wc2 = frm_nxt[1];
1692 if ((wc2 & 0xFC00) != 0xDC00)
1693 return codecvt_base::error;
1694 if (to_end-to_nxt < 4)
1695 return codecvt_base::partial;
1696 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1697 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1698 return codecvt_base::error;
1699 ++frm_nxt;
1700 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1701 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1702 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1703 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1704 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1705 }
1706 else if (wc1 < 0xE000)
1707 {
1708 return codecvt_base::error;
1709 }
1710 else
1711 {
1712 if (to_end-to_nxt < 3)
1713 return codecvt_base::partial;
1714 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1715 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1716 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1717 }
1718 }
1719 return codecvt_base::ok;
1720}
1721
1722static
1723codecvt_base::result
1724utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1725 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1726 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1727{
1728 frm_nxt = frm;
1729 to_nxt = to;
1730 if (mode & generate_header)
1731 {
1732 if (to_end-to_nxt < 3)
1733 return codecvt_base::partial;
1734 *to_nxt++ = static_cast<uint8_t>(0xEF);
1735 *to_nxt++ = static_cast<uint8_t>(0xBB);
1736 *to_nxt++ = static_cast<uint8_t>(0xBF);
1737 }
1738 for (; frm_nxt < frm_end; ++frm_nxt)
1739 {
1740 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1741 if (wc1 > Maxcode)
1742 return codecvt_base::error;
1743 if (wc1 < 0x0080)
1744 {
1745 if (to_end-to_nxt < 1)
1746 return codecvt_base::partial;
1747 *to_nxt++ = static_cast<uint8_t>(wc1);
1748 }
1749 else if (wc1 < 0x0800)
1750 {
1751 if (to_end-to_nxt < 2)
1752 return codecvt_base::partial;
1753 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1754 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1755 }
1756 else if (wc1 < 0xD800)
1757 {
1758 if (to_end-to_nxt < 3)
1759 return codecvt_base::partial;
1760 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1761 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1762 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1763 }
1764 else if (wc1 < 0xDC00)
1765 {
1766 if (frm_end-frm_nxt < 2)
1767 return codecvt_base::partial;
1768 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1769 if ((wc2 & 0xFC00) != 0xDC00)
1770 return codecvt_base::error;
1771 if (to_end-to_nxt < 4)
1772 return codecvt_base::partial;
1773 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1774 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1775 return codecvt_base::error;
1776 ++frm_nxt;
1777 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1778 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1779 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1780 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1781 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1782 }
1783 else if (wc1 < 0xE000)
1784 {
1785 return codecvt_base::error;
1786 }
1787 else
1788 {
1789 if (to_end-to_nxt < 3)
1790 return codecvt_base::partial;
1791 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1792 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1793 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1794 }
1795 }
1796 return codecvt_base::ok;
1797}
1798
1799static
1800codecvt_base::result
1801utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1802 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1803 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1804{
1805 frm_nxt = frm;
1806 to_nxt = to;
1807 if (mode & consume_header)
1808 {
1809 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1810 frm_nxt[2] == 0xBF)
1811 frm_nxt += 3;
1812 }
1813 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1814 {
1815 uint8_t c1 = *frm_nxt;
1816 if (c1 > Maxcode)
1817 return codecvt_base::error;
1818 if (c1 < 0x80)
1819 {
1820 *to_nxt = static_cast<uint16_t>(c1);
1821 ++frm_nxt;
1822 }
1823 else if (c1 < 0xC2)
1824 {
1825 return codecvt_base::error;
1826 }
1827 else if (c1 < 0xE0)
1828 {
1829 if (frm_end-frm_nxt < 2)
1830 return codecvt_base::partial;
1831 uint8_t c2 = frm_nxt[1];
1832 if ((c2 & 0xC0) != 0x80)
1833 return codecvt_base::error;
1834 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1835 if (t > Maxcode)
1836 return codecvt_base::error;
1837 *to_nxt = t;
1838 frm_nxt += 2;
1839 }
1840 else if (c1 < 0xF0)
1841 {
1842 if (frm_end-frm_nxt < 3)
1843 return codecvt_base::partial;
1844 uint8_t c2 = frm_nxt[1];
1845 uint8_t c3 = frm_nxt[2];
1846 switch (c1)
1847 {
1848 case 0xE0:
1849 if ((c2 & 0xE0) != 0xA0)
1850 return codecvt_base::error;
1851 break;
1852 case 0xED:
1853 if ((c2 & 0xE0) != 0x80)
1854 return codecvt_base::error;
1855 break;
1856 default:
1857 if ((c2 & 0xC0) != 0x80)
1858 return codecvt_base::error;
1859 break;
1860 }
1861 if ((c3 & 0xC0) != 0x80)
1862 return codecvt_base::error;
1863 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1864 | ((c2 & 0x3F) << 6)
1865 | (c3 & 0x3F));
1866 if (t > Maxcode)
1867 return codecvt_base::error;
1868 *to_nxt = t;
1869 frm_nxt += 3;
1870 }
1871 else if (c1 < 0xF5)
1872 {
1873 if (frm_end-frm_nxt < 4)
1874 return codecvt_base::partial;
1875 uint8_t c2 = frm_nxt[1];
1876 uint8_t c3 = frm_nxt[2];
1877 uint8_t c4 = frm_nxt[3];
1878 switch (c1)
1879 {
1880 case 0xF0:
1881 if (!(0x90 <= c2 && c2 <= 0xBF))
1882 return codecvt_base::error;
1883 break;
1884 case 0xF4:
1885 if ((c2 & 0xF0) != 0x80)
1886 return codecvt_base::error;
1887 break;
1888 default:
1889 if ((c2 & 0xC0) != 0x80)
1890 return codecvt_base::error;
1891 break;
1892 }
1893 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1894 return codecvt_base::error;
1895 if (to_end-to_nxt < 2)
1896 return codecvt_base::partial;
1897 if (((((unsigned long)c1 & 7) << 18) +
1898 (((unsigned long)c2 & 0x3F) << 12) +
1899 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1900 return codecvt_base::error;
1901 *to_nxt = static_cast<uint16_t>(
1902 0xD800
1903 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1904 | ((c2 & 0x0F) << 2)
1905 | ((c3 & 0x30) >> 4));
1906 *++to_nxt = static_cast<uint16_t>(
1907 0xDC00
1908 | ((c3 & 0x0F) << 6)
1909 | (c4 & 0x3F));
1910 frm_nxt += 4;
1911 }
1912 else
1913 {
1914 return codecvt_base::error;
1915 }
1916 }
1917 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1918}
1919
1920static
1921codecvt_base::result
1922utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1923 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1924 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1925{
1926 frm_nxt = frm;
1927 to_nxt = to;
1928 if (mode & consume_header)
1929 {
1930 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1931 frm_nxt[2] == 0xBF)
1932 frm_nxt += 3;
1933 }
1934 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1935 {
1936 uint8_t c1 = *frm_nxt;
1937 if (c1 > Maxcode)
1938 return codecvt_base::error;
1939 if (c1 < 0x80)
1940 {
1941 *to_nxt = static_cast<uint32_t>(c1);
1942 ++frm_nxt;
1943 }
1944 else if (c1 < 0xC2)
1945 {
1946 return codecvt_base::error;
1947 }
1948 else if (c1 < 0xE0)
1949 {
1950 if (frm_end-frm_nxt < 2)
1951 return codecvt_base::partial;
1952 uint8_t c2 = frm_nxt[1];
1953 if ((c2 & 0xC0) != 0x80)
1954 return codecvt_base::error;
1955 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1956 if (t > Maxcode)
1957 return codecvt_base::error;
1958 *to_nxt = static_cast<uint32_t>(t);
1959 frm_nxt += 2;
1960 }
1961 else if (c1 < 0xF0)
1962 {
1963 if (frm_end-frm_nxt < 3)
1964 return codecvt_base::partial;
1965 uint8_t c2 = frm_nxt[1];
1966 uint8_t c3 = frm_nxt[2];
1967 switch (c1)
1968 {
1969 case 0xE0:
1970 if ((c2 & 0xE0) != 0xA0)
1971 return codecvt_base::error;
1972 break;
1973 case 0xED:
1974 if ((c2 & 0xE0) != 0x80)
1975 return codecvt_base::error;
1976 break;
1977 default:
1978 if ((c2 & 0xC0) != 0x80)
1979 return codecvt_base::error;
1980 break;
1981 }
1982 if ((c3 & 0xC0) != 0x80)
1983 return codecvt_base::error;
1984 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1985 | ((c2 & 0x3F) << 6)
1986 | (c3 & 0x3F));
1987 if (t > Maxcode)
1988 return codecvt_base::error;
1989 *to_nxt = static_cast<uint32_t>(t);
1990 frm_nxt += 3;
1991 }
1992 else if (c1 < 0xF5)
1993 {
1994 if (frm_end-frm_nxt < 4)
1995 return codecvt_base::partial;
1996 uint8_t c2 = frm_nxt[1];
1997 uint8_t c3 = frm_nxt[2];
1998 uint8_t c4 = frm_nxt[3];
1999 switch (c1)
2000 {
2001 case 0xF0:
2002 if (!(0x90 <= c2 && c2 <= 0xBF))
2003 return codecvt_base::error;
2004 break;
2005 case 0xF4:
2006 if ((c2 & 0xF0) != 0x80)
2007 return codecvt_base::error;
2008 break;
2009 default:
2010 if ((c2 & 0xC0) != 0x80)
2011 return codecvt_base::error;
2012 break;
2013 }
2014 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2015 return codecvt_base::error;
2016 if (to_end-to_nxt < 2)
2017 return codecvt_base::partial;
2018 if (((((unsigned long)c1 & 7) << 18) +
2019 (((unsigned long)c2 & 0x3F) << 12) +
2020 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2021 return codecvt_base::error;
2022 *to_nxt = static_cast<uint32_t>(
2023 0xD800
2024 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
2025 | ((c2 & 0x0F) << 2)
2026 | ((c3 & 0x30) >> 4));
2027 *++to_nxt = static_cast<uint32_t>(
2028 0xDC00
2029 | ((c3 & 0x0F) << 6)
2030 | (c4 & 0x3F));
2031 frm_nxt += 4;
2032 }
2033 else
2034 {
2035 return codecvt_base::error;
2036 }
2037 }
2038 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2039}
2040
2041static
2042int
2043utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
2044 size_t mx, unsigned long Maxcode = 0x10FFFF,
2045 codecvt_mode mode = codecvt_mode(0))
2046{
2047 const uint8_t* frm_nxt = frm;
2048 if (mode & consume_header)
2049 {
2050 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2051 frm_nxt[2] == 0xBF)
2052 frm_nxt += 3;
2053 }
2054 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
2055 {
2056 uint8_t c1 = *frm_nxt;
2057 if (c1 > Maxcode)
2058 break;
2059 if (c1 < 0x80)
2060 {
2061 ++frm_nxt;
2062 }
2063 else if (c1 < 0xC2)
2064 {
2065 break;
2066 }
2067 else if (c1 < 0xE0)
2068 {
2069 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
2070 break;
2071 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
2072 if (t > Maxcode)
2073 break;
2074 frm_nxt += 2;
2075 }
2076 else if (c1 < 0xF0)
2077 {
2078 if (frm_end-frm_nxt < 3)
2079 break;
2080 uint8_t c2 = frm_nxt[1];
2081 uint8_t c3 = frm_nxt[2];
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002082 switch (c1)
2083 {
2084 case 0xE0:
2085 if ((c2 & 0xE0) != 0xA0)
2086 return static_cast<int>(frm_nxt - frm);
2087 break;
2088 case 0xED:
2089 if ((c2 & 0xE0) != 0x80)
2090 return static_cast<int>(frm_nxt - frm);
2091 break;
2092 default:
2093 if ((c2 & 0xC0) != 0x80)
2094 return static_cast<int>(frm_nxt - frm);
2095 break;
2096 }
2097 if ((c3 & 0xC0) != 0x80)
2098 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002099 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002100 break;
2101 frm_nxt += 3;
2102 }
2103 else if (c1 < 0xF5)
2104 {
2105 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2106 break;
2107 uint8_t c2 = frm_nxt[1];
2108 uint8_t c3 = frm_nxt[2];
2109 uint8_t c4 = frm_nxt[3];
2110 switch (c1)
2111 {
2112 case 0xF0:
2113 if (!(0x90 <= c2 && c2 <= 0xBF))
2114 return static_cast<int>(frm_nxt - frm);
2115 break;
2116 case 0xF4:
2117 if ((c2 & 0xF0) != 0x80)
2118 return static_cast<int>(frm_nxt - frm);
2119 break;
2120 default:
2121 if ((c2 & 0xC0) != 0x80)
2122 return static_cast<int>(frm_nxt - frm);
2123 break;
2124 }
2125 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2126 break;
2127 if (((((unsigned long)c1 & 7) << 18) +
2128 (((unsigned long)c2 & 0x3F) << 12) +
2129 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2130 break;
2131 ++nchar16_t;
2132 frm_nxt += 4;
2133 }
2134 else
2135 {
2136 break;
2137 }
2138 }
2139 return static_cast<int>(frm_nxt - frm);
2140}
2141
2142static
2143codecvt_base::result
2144ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2145 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2146 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2147{
2148 frm_nxt = frm;
2149 to_nxt = to;
2150 if (mode & generate_header)
2151 {
2152 if (to_end-to_nxt < 3)
2153 return codecvt_base::partial;
2154 *to_nxt++ = static_cast<uint8_t>(0xEF);
2155 *to_nxt++ = static_cast<uint8_t>(0xBB);
2156 *to_nxt++ = static_cast<uint8_t>(0xBF);
2157 }
2158 for (; frm_nxt < frm_end; ++frm_nxt)
2159 {
2160 uint32_t wc = *frm_nxt;
2161 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2162 return codecvt_base::error;
2163 if (wc < 0x000080)
2164 {
2165 if (to_end-to_nxt < 1)
2166 return codecvt_base::partial;
2167 *to_nxt++ = static_cast<uint8_t>(wc);
2168 }
2169 else if (wc < 0x000800)
2170 {
2171 if (to_end-to_nxt < 2)
2172 return codecvt_base::partial;
2173 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2174 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2175 }
2176 else if (wc < 0x010000)
2177 {
2178 if (to_end-to_nxt < 3)
2179 return codecvt_base::partial;
2180 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2181 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2182 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2183 }
2184 else // if (wc < 0x110000)
2185 {
2186 if (to_end-to_nxt < 4)
2187 return codecvt_base::partial;
2188 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2189 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2190 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2191 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2192 }
2193 }
2194 return codecvt_base::ok;
2195}
2196
2197static
2198codecvt_base::result
2199utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2200 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2201 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2202{
2203 frm_nxt = frm;
2204 to_nxt = to;
2205 if (mode & consume_header)
2206 {
2207 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2208 frm_nxt[2] == 0xBF)
2209 frm_nxt += 3;
2210 }
2211 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2212 {
2213 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2214 if (c1 < 0x80)
2215 {
2216 if (c1 > Maxcode)
2217 return codecvt_base::error;
2218 *to_nxt = static_cast<uint32_t>(c1);
2219 ++frm_nxt;
2220 }
2221 else if (c1 < 0xC2)
2222 {
2223 return codecvt_base::error;
2224 }
2225 else if (c1 < 0xE0)
2226 {
2227 if (frm_end-frm_nxt < 2)
2228 return codecvt_base::partial;
2229 uint8_t c2 = frm_nxt[1];
2230 if ((c2 & 0xC0) != 0x80)
2231 return codecvt_base::error;
2232 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2233 | (c2 & 0x3F));
2234 if (t > Maxcode)
2235 return codecvt_base::error;
2236 *to_nxt = t;
2237 frm_nxt += 2;
2238 }
2239 else if (c1 < 0xF0)
2240 {
2241 if (frm_end-frm_nxt < 3)
2242 return codecvt_base::partial;
2243 uint8_t c2 = frm_nxt[1];
2244 uint8_t c3 = frm_nxt[2];
2245 switch (c1)
2246 {
2247 case 0xE0:
2248 if ((c2 & 0xE0) != 0xA0)
2249 return codecvt_base::error;
2250 break;
2251 case 0xED:
2252 if ((c2 & 0xE0) != 0x80)
2253 return codecvt_base::error;
2254 break;
2255 default:
2256 if ((c2 & 0xC0) != 0x80)
2257 return codecvt_base::error;
2258 break;
2259 }
2260 if ((c3 & 0xC0) != 0x80)
2261 return codecvt_base::error;
2262 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2263 | ((c2 & 0x3F) << 6)
2264 | (c3 & 0x3F));
2265 if (t > Maxcode)
2266 return codecvt_base::error;
2267 *to_nxt = t;
2268 frm_nxt += 3;
2269 }
2270 else if (c1 < 0xF5)
2271 {
2272 if (frm_end-frm_nxt < 4)
2273 return codecvt_base::partial;
2274 uint8_t c2 = frm_nxt[1];
2275 uint8_t c3 = frm_nxt[2];
2276 uint8_t c4 = frm_nxt[3];
2277 switch (c1)
2278 {
2279 case 0xF0:
2280 if (!(0x90 <= c2 && c2 <= 0xBF))
2281 return codecvt_base::error;
2282 break;
2283 case 0xF4:
2284 if ((c2 & 0xF0) != 0x80)
2285 return codecvt_base::error;
2286 break;
2287 default:
2288 if ((c2 & 0xC0) != 0x80)
2289 return codecvt_base::error;
2290 break;
2291 }
2292 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2293 return codecvt_base::error;
2294 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2295 | ((c2 & 0x3F) << 12)
2296 | ((c3 & 0x3F) << 6)
2297 | (c4 & 0x3F));
2298 if (t > Maxcode)
2299 return codecvt_base::error;
2300 *to_nxt = t;
2301 frm_nxt += 4;
2302 }
2303 else
2304 {
2305 return codecvt_base::error;
2306 }
2307 }
2308 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2309}
2310
2311static
2312int
2313utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2314 size_t mx, unsigned long Maxcode = 0x10FFFF,
2315 codecvt_mode mode = codecvt_mode(0))
2316{
2317 const uint8_t* frm_nxt = frm;
2318 if (mode & consume_header)
2319 {
2320 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2321 frm_nxt[2] == 0xBF)
2322 frm_nxt += 3;
2323 }
2324 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2325 {
2326 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2327 if (c1 < 0x80)
2328 {
2329 if (c1 > Maxcode)
2330 break;
2331 ++frm_nxt;
2332 }
2333 else if (c1 < 0xC2)
2334 {
2335 break;
2336 }
2337 else if (c1 < 0xE0)
2338 {
2339 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2340 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002341 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002342 break;
2343 frm_nxt += 2;
2344 }
2345 else if (c1 < 0xF0)
2346 {
2347 if (frm_end-frm_nxt < 3)
2348 break;
2349 uint8_t c2 = frm_nxt[1];
2350 uint8_t c3 = frm_nxt[2];
2351 switch (c1)
2352 {
2353 case 0xE0:
2354 if ((c2 & 0xE0) != 0xA0)
2355 return static_cast<int>(frm_nxt - frm);
2356 break;
2357 case 0xED:
2358 if ((c2 & 0xE0) != 0x80)
2359 return static_cast<int>(frm_nxt - frm);
2360 break;
2361 default:
2362 if ((c2 & 0xC0) != 0x80)
2363 return static_cast<int>(frm_nxt - frm);
2364 break;
2365 }
2366 if ((c3 & 0xC0) != 0x80)
2367 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002368 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002369 break;
2370 frm_nxt += 3;
2371 }
2372 else if (c1 < 0xF5)
2373 {
2374 if (frm_end-frm_nxt < 4)
2375 break;
2376 uint8_t c2 = frm_nxt[1];
2377 uint8_t c3 = frm_nxt[2];
2378 uint8_t c4 = frm_nxt[3];
2379 switch (c1)
2380 {
2381 case 0xF0:
2382 if (!(0x90 <= c2 && c2 <= 0xBF))
2383 return static_cast<int>(frm_nxt - frm);
2384 break;
2385 case 0xF4:
2386 if ((c2 & 0xF0) != 0x80)
2387 return static_cast<int>(frm_nxt - frm);
2388 break;
2389 default:
2390 if ((c2 & 0xC0) != 0x80)
2391 return static_cast<int>(frm_nxt - frm);
2392 break;
2393 }
2394 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2395 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002396 if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) |
2397 ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002398 break;
2399 frm_nxt += 4;
2400 }
2401 else
2402 {
2403 break;
2404 }
2405 }
2406 return static_cast<int>(frm_nxt - frm);
2407}
2408
2409static
2410codecvt_base::result
2411ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2412 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2413 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2414{
2415 frm_nxt = frm;
2416 to_nxt = to;
2417 if (mode & generate_header)
2418 {
2419 if (to_end-to_nxt < 3)
2420 return codecvt_base::partial;
2421 *to_nxt++ = static_cast<uint8_t>(0xEF);
2422 *to_nxt++ = static_cast<uint8_t>(0xBB);
2423 *to_nxt++ = static_cast<uint8_t>(0xBF);
2424 }
2425 for (; frm_nxt < frm_end; ++frm_nxt)
2426 {
2427 uint16_t wc = *frm_nxt;
2428 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2429 return codecvt_base::error;
2430 if (wc < 0x0080)
2431 {
2432 if (to_end-to_nxt < 1)
2433 return codecvt_base::partial;
2434 *to_nxt++ = static_cast<uint8_t>(wc);
2435 }
2436 else if (wc < 0x0800)
2437 {
2438 if (to_end-to_nxt < 2)
2439 return codecvt_base::partial;
2440 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2441 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2442 }
2443 else // if (wc <= 0xFFFF)
2444 {
2445 if (to_end-to_nxt < 3)
2446 return codecvt_base::partial;
2447 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2448 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2449 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2450 }
2451 }
2452 return codecvt_base::ok;
2453}
2454
2455static
2456codecvt_base::result
2457utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2458 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2459 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2460{
2461 frm_nxt = frm;
2462 to_nxt = to;
2463 if (mode & consume_header)
2464 {
2465 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2466 frm_nxt[2] == 0xBF)
2467 frm_nxt += 3;
2468 }
2469 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2470 {
2471 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2472 if (c1 < 0x80)
2473 {
2474 if (c1 > Maxcode)
2475 return codecvt_base::error;
2476 *to_nxt = static_cast<uint16_t>(c1);
2477 ++frm_nxt;
2478 }
2479 else if (c1 < 0xC2)
2480 {
2481 return codecvt_base::error;
2482 }
2483 else if (c1 < 0xE0)
2484 {
2485 if (frm_end-frm_nxt < 2)
2486 return codecvt_base::partial;
2487 uint8_t c2 = frm_nxt[1];
2488 if ((c2 & 0xC0) != 0x80)
2489 return codecvt_base::error;
2490 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2491 | (c2 & 0x3F));
2492 if (t > Maxcode)
2493 return codecvt_base::error;
2494 *to_nxt = t;
2495 frm_nxt += 2;
2496 }
2497 else if (c1 < 0xF0)
2498 {
2499 if (frm_end-frm_nxt < 3)
2500 return codecvt_base::partial;
2501 uint8_t c2 = frm_nxt[1];
2502 uint8_t c3 = frm_nxt[2];
2503 switch (c1)
2504 {
2505 case 0xE0:
2506 if ((c2 & 0xE0) != 0xA0)
2507 return codecvt_base::error;
2508 break;
2509 case 0xED:
2510 if ((c2 & 0xE0) != 0x80)
2511 return codecvt_base::error;
2512 break;
2513 default:
2514 if ((c2 & 0xC0) != 0x80)
2515 return codecvt_base::error;
2516 break;
2517 }
2518 if ((c3 & 0xC0) != 0x80)
2519 return codecvt_base::error;
2520 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2521 | ((c2 & 0x3F) << 6)
2522 | (c3 & 0x3F));
2523 if (t > Maxcode)
2524 return codecvt_base::error;
2525 *to_nxt = t;
2526 frm_nxt += 3;
2527 }
2528 else
2529 {
2530 return codecvt_base::error;
2531 }
2532 }
2533 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2534}
2535
2536static
2537int
2538utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2539 size_t mx, unsigned long Maxcode = 0x10FFFF,
2540 codecvt_mode mode = codecvt_mode(0))
2541{
2542 const uint8_t* frm_nxt = frm;
2543 if (mode & consume_header)
2544 {
2545 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2546 frm_nxt[2] == 0xBF)
2547 frm_nxt += 3;
2548 }
2549 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2550 {
2551 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2552 if (c1 < 0x80)
2553 {
2554 if (c1 > Maxcode)
2555 break;
2556 ++frm_nxt;
2557 }
2558 else if (c1 < 0xC2)
2559 {
2560 break;
2561 }
2562 else if (c1 < 0xE0)
2563 {
2564 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2565 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002566 if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002567 break;
2568 frm_nxt += 2;
2569 }
2570 else if (c1 < 0xF0)
2571 {
2572 if (frm_end-frm_nxt < 3)
2573 break;
2574 uint8_t c2 = frm_nxt[1];
2575 uint8_t c3 = frm_nxt[2];
2576 switch (c1)
2577 {
2578 case 0xE0:
2579 if ((c2 & 0xE0) != 0xA0)
2580 return static_cast<int>(frm_nxt - frm);
2581 break;
2582 case 0xED:
2583 if ((c2 & 0xE0) != 0x80)
2584 return static_cast<int>(frm_nxt - frm);
2585 break;
2586 default:
2587 if ((c2 & 0xC0) != 0x80)
2588 return static_cast<int>(frm_nxt - frm);
2589 break;
2590 }
2591 if ((c3 & 0xC0) != 0x80)
2592 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002593 if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode)
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002594 break;
2595 frm_nxt += 3;
2596 }
2597 else
2598 {
2599 break;
2600 }
2601 }
2602 return static_cast<int>(frm_nxt - frm);
2603}
2604
2605static
2606codecvt_base::result
2607ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2608 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2609 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2610{
2611 frm_nxt = frm;
2612 to_nxt = to;
2613 if (mode & generate_header)
2614 {
2615 if (to_end-to_nxt < 2)
2616 return codecvt_base::partial;
2617 *to_nxt++ = static_cast<uint8_t>(0xFE);
2618 *to_nxt++ = static_cast<uint8_t>(0xFF);
2619 }
2620 for (; frm_nxt < frm_end; ++frm_nxt)
2621 {
2622 uint32_t wc = *frm_nxt;
2623 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2624 return codecvt_base::error;
2625 if (wc < 0x010000)
2626 {
2627 if (to_end-to_nxt < 2)
2628 return codecvt_base::partial;
2629 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2630 *to_nxt++ = static_cast<uint8_t>(wc);
2631 }
2632 else
2633 {
2634 if (to_end-to_nxt < 4)
2635 return codecvt_base::partial;
2636 uint16_t t = static_cast<uint16_t>(
2637 0xD800
2638 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2639 | ((wc & 0x00FC00) >> 10));
2640 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2641 *to_nxt++ = static_cast<uint8_t>(t);
2642 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2643 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2644 *to_nxt++ = static_cast<uint8_t>(t);
2645 }
2646 }
2647 return codecvt_base::ok;
2648}
2649
2650static
2651codecvt_base::result
2652utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2653 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2654 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2655{
2656 frm_nxt = frm;
2657 to_nxt = to;
2658 if (mode & consume_header)
2659 {
2660 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2661 frm_nxt += 2;
2662 }
2663 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2664 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002665 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002666 if ((c1 & 0xFC00) == 0xDC00)
2667 return codecvt_base::error;
2668 if ((c1 & 0xFC00) != 0xD800)
2669 {
2670 if (c1 > Maxcode)
2671 return codecvt_base::error;
2672 *to_nxt = static_cast<uint32_t>(c1);
2673 frm_nxt += 2;
2674 }
2675 else
2676 {
2677 if (frm_end-frm_nxt < 4)
2678 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002679 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002680 if ((c2 & 0xFC00) != 0xDC00)
2681 return codecvt_base::error;
2682 uint32_t t = static_cast<uint32_t>(
2683 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2684 | ((c1 & 0x003F) << 10)
2685 | (c2 & 0x03FF));
2686 if (t > Maxcode)
2687 return codecvt_base::error;
2688 *to_nxt = t;
2689 frm_nxt += 4;
2690 }
2691 }
2692 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2693}
2694
2695static
2696int
2697utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2698 size_t mx, unsigned long Maxcode = 0x10FFFF,
2699 codecvt_mode mode = codecvt_mode(0))
2700{
2701 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002702 if (mode & consume_header)
2703 {
2704 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2705 frm_nxt += 2;
2706 }
2707 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2708 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002709 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002710 if ((c1 & 0xFC00) == 0xDC00)
2711 break;
2712 if ((c1 & 0xFC00) != 0xD800)
2713 {
2714 if (c1 > Maxcode)
2715 break;
2716 frm_nxt += 2;
2717 }
2718 else
2719 {
2720 if (frm_end-frm_nxt < 4)
2721 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002722 uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002723 if ((c2 & 0xFC00) != 0xDC00)
2724 break;
2725 uint32_t t = static_cast<uint32_t>(
2726 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2727 | ((c1 & 0x003F) << 10)
2728 | (c2 & 0x03FF));
2729 if (t > Maxcode)
2730 break;
2731 frm_nxt += 4;
2732 }
2733 }
2734 return static_cast<int>(frm_nxt - frm);
2735}
2736
2737static
2738codecvt_base::result
2739ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2740 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2741 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2742{
2743 frm_nxt = frm;
2744 to_nxt = to;
2745 if (mode & generate_header)
2746 {
2747 if (to_end-to_nxt < 2)
2748 return codecvt_base::partial;
2749 *to_nxt++ = static_cast<uint8_t>(0xFF);
2750 *to_nxt++ = static_cast<uint8_t>(0xFE);
2751 }
2752 for (; frm_nxt < frm_end; ++frm_nxt)
2753 {
2754 uint32_t wc = *frm_nxt;
2755 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2756 return codecvt_base::error;
2757 if (wc < 0x010000)
2758 {
2759 if (to_end-to_nxt < 2)
2760 return codecvt_base::partial;
2761 *to_nxt++ = static_cast<uint8_t>(wc);
2762 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2763 }
2764 else
2765 {
2766 if (to_end-to_nxt < 4)
2767 return codecvt_base::partial;
2768 uint16_t t = static_cast<uint16_t>(
2769 0xD800
2770 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2771 | ((wc & 0x00FC00) >> 10));
2772 *to_nxt++ = static_cast<uint8_t>(t);
2773 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2774 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2775 *to_nxt++ = static_cast<uint8_t>(t);
2776 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2777 }
2778 }
2779 return codecvt_base::ok;
2780}
2781
2782static
2783codecvt_base::result
2784utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2785 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2786 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2787{
2788 frm_nxt = frm;
2789 to_nxt = to;
2790 if (mode & consume_header)
2791 {
2792 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2793 frm_nxt += 2;
2794 }
2795 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2796 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002797 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002798 if ((c1 & 0xFC00) == 0xDC00)
2799 return codecvt_base::error;
2800 if ((c1 & 0xFC00) != 0xD800)
2801 {
2802 if (c1 > Maxcode)
2803 return codecvt_base::error;
2804 *to_nxt = static_cast<uint32_t>(c1);
2805 frm_nxt += 2;
2806 }
2807 else
2808 {
2809 if (frm_end-frm_nxt < 4)
2810 return codecvt_base::partial;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002811 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002812 if ((c2 & 0xFC00) != 0xDC00)
2813 return codecvt_base::error;
2814 uint32_t t = static_cast<uint32_t>(
2815 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2816 | ((c1 & 0x003F) << 10)
2817 | (c2 & 0x03FF));
2818 if (t > Maxcode)
2819 return codecvt_base::error;
2820 *to_nxt = t;
2821 frm_nxt += 4;
2822 }
2823 }
2824 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2825}
2826
2827static
2828int
2829utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2830 size_t mx, unsigned long Maxcode = 0x10FFFF,
2831 codecvt_mode mode = codecvt_mode(0))
2832{
2833 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002834 if (mode & consume_header)
2835 {
2836 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2837 frm_nxt += 2;
2838 }
2839 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2840 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002841 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002842 if ((c1 & 0xFC00) == 0xDC00)
2843 break;
2844 if ((c1 & 0xFC00) != 0xD800)
2845 {
2846 if (c1 > Maxcode)
2847 break;
2848 frm_nxt += 2;
2849 }
2850 else
2851 {
2852 if (frm_end-frm_nxt < 4)
2853 break;
Howard Hinnantec3773c2011-12-01 20:21:04 +00002854 uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002855 if ((c2 & 0xFC00) != 0xDC00)
2856 break;
2857 uint32_t t = static_cast<uint32_t>(
2858 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2859 | ((c1 & 0x003F) << 10)
2860 | (c2 & 0x03FF));
2861 if (t > Maxcode)
2862 break;
2863 frm_nxt += 4;
2864 }
2865 }
2866 return static_cast<int>(frm_nxt - frm);
2867}
2868
2869static
2870codecvt_base::result
2871ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2872 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2873 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2874{
2875 frm_nxt = frm;
2876 to_nxt = to;
2877 if (mode & generate_header)
2878 {
2879 if (to_end-to_nxt < 2)
2880 return codecvt_base::partial;
2881 *to_nxt++ = static_cast<uint8_t>(0xFE);
2882 *to_nxt++ = static_cast<uint8_t>(0xFF);
2883 }
2884 for (; frm_nxt < frm_end; ++frm_nxt)
2885 {
2886 uint16_t wc = *frm_nxt;
2887 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2888 return codecvt_base::error;
2889 if (to_end-to_nxt < 2)
2890 return codecvt_base::partial;
2891 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2892 *to_nxt++ = static_cast<uint8_t>(wc);
2893 }
2894 return codecvt_base::ok;
2895}
2896
2897static
2898codecvt_base::result
2899utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2900 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2901 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2902{
2903 frm_nxt = frm;
2904 to_nxt = to;
2905 if (mode & consume_header)
2906 {
2907 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2908 frm_nxt += 2;
2909 }
2910 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2911 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002912 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002913 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2914 return codecvt_base::error;
2915 *to_nxt = c1;
2916 frm_nxt += 2;
2917 }
2918 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2919}
2920
2921static
2922int
2923utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2924 size_t mx, unsigned long Maxcode = 0x10FFFF,
2925 codecvt_mode mode = codecvt_mode(0))
2926{
2927 const uint8_t* frm_nxt = frm;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002928 if (mode & consume_header)
2929 {
2930 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2931 frm_nxt += 2;
2932 }
2933 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2934 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002935 uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002936 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2937 break;
2938 frm_nxt += 2;
2939 }
2940 return static_cast<int>(frm_nxt - frm);
2941}
2942
2943static
2944codecvt_base::result
2945ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2946 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2947 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2948{
2949 frm_nxt = frm;
2950 to_nxt = to;
2951 if (mode & generate_header)
2952 {
2953 if (to_end-to_nxt < 2)
2954 return codecvt_base::partial;
2955 *to_nxt++ = static_cast<uint8_t>(0xFF);
2956 *to_nxt++ = static_cast<uint8_t>(0xFE);
2957 }
2958 for (; frm_nxt < frm_end; ++frm_nxt)
2959 {
2960 uint16_t wc = *frm_nxt;
2961 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2962 return codecvt_base::error;
2963 if (to_end-to_nxt < 2)
2964 return codecvt_base::partial;
2965 *to_nxt++ = static_cast<uint8_t>(wc);
2966 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2967 }
2968 return codecvt_base::ok;
2969}
2970
2971static
2972codecvt_base::result
2973utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2974 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2975 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2976{
2977 frm_nxt = frm;
2978 to_nxt = to;
2979 if (mode & consume_header)
2980 {
2981 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2982 frm_nxt += 2;
2983 }
2984 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2985 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00002986 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002987 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2988 return codecvt_base::error;
2989 *to_nxt = c1;
2990 frm_nxt += 2;
2991 }
2992 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2993}
2994
2995static
2996int
2997utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2998 size_t mx, unsigned long Maxcode = 0x10FFFF,
2999 codecvt_mode mode = codecvt_mode(0))
3000{
3001 const uint8_t* frm_nxt = frm;
3002 frm_nxt = frm;
3003 if (mode & consume_header)
3004 {
3005 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
3006 frm_nxt += 2;
3007 }
3008 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
3009 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00003010 uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]);
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003011 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
3012 break;
3013 frm_nxt += 2;
3014 }
3015 return static_cast<int>(frm_nxt - frm);
3016}
3017
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003018// template <> class codecvt<char16_t, char, mbstate_t>
3019
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003020locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003021
3022codecvt<char16_t, char, mbstate_t>::~codecvt()
3023{
3024}
3025
3026codecvt<char16_t, char, mbstate_t>::result
3027codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003028 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003029 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3030{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003031 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3032 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3033 const uint16_t* _frm_nxt = _frm;
3034 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3035 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3036 uint8_t* _to_nxt = _to;
3037 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3038 frm_nxt = frm + (_frm_nxt - _frm);
3039 to_nxt = to + (_to_nxt - _to);
3040 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003041}
3042
3043codecvt<char16_t, char, mbstate_t>::result
3044codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003045 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003046 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3047{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003048 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3049 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3050 const uint8_t* _frm_nxt = _frm;
3051 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3052 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3053 uint16_t* _to_nxt = _to;
3054 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3055 frm_nxt = frm + (_frm_nxt - _frm);
3056 to_nxt = to + (_to_nxt - _to);
3057 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003058}
3059
3060codecvt<char16_t, char, mbstate_t>::result
3061codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
3062 extern_type* to, extern_type*, extern_type*& to_nxt) const
3063{
3064 to_nxt = to;
3065 return noconv;
3066}
3067
3068int
Howard Hinnantc9834542011-05-31 15:34:58 +00003069codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003070{
3071 return 0;
3072}
3073
3074bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003075codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003076{
3077 return false;
3078}
3079
3080int
3081codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
3082 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3083{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003084 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3085 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3086 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003087}
3088
3089int
Howard Hinnantc9834542011-05-31 15:34:58 +00003090codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003091{
3092 return 4;
3093}
3094
3095// template <> class codecvt<char32_t, char, mbstate_t>
3096
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003097locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003098
3099codecvt<char32_t, char, mbstate_t>::~codecvt()
3100{
3101}
3102
3103codecvt<char32_t, char, mbstate_t>::result
3104codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003105 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003106 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3107{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003108 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3109 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3110 const uint32_t* _frm_nxt = _frm;
3111 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3112 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3113 uint8_t* _to_nxt = _to;
3114 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3115 frm_nxt = frm + (_frm_nxt - _frm);
3116 to_nxt = to + (_to_nxt - _to);
3117 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003118}
3119
3120codecvt<char32_t, char, mbstate_t>::result
3121codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003122 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003123 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3124{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003125 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3126 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3127 const uint8_t* _frm_nxt = _frm;
3128 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3129 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3130 uint32_t* _to_nxt = _to;
3131 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3132 frm_nxt = frm + (_frm_nxt - _frm);
3133 to_nxt = to + (_to_nxt - _to);
3134 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003135}
3136
3137codecvt<char32_t, char, mbstate_t>::result
3138codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3139 extern_type* to, extern_type*, extern_type*& to_nxt) const
3140{
3141 to_nxt = to;
3142 return noconv;
3143}
3144
3145int
Howard Hinnantc9834542011-05-31 15:34:58 +00003146codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003147{
3148 return 0;
3149}
3150
3151bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003152codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003153{
3154 return false;
3155}
3156
3157int
3158codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3159 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3160{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003161 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3162 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3163 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003164}
3165
3166int
Howard Hinnantc9834542011-05-31 15:34:58 +00003167codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003168{
3169 return 4;
3170}
3171
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003172// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003173
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003174__codecvt_utf8<wchar_t>::result
3175__codecvt_utf8<wchar_t>::do_out(state_type&,
3176 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003177 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3178{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003179 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3180 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3181 const uint32_t* _frm_nxt = _frm;
3182 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3183 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3184 uint8_t* _to_nxt = _to;
3185 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3186 _Maxcode_, _Mode_);
3187 frm_nxt = frm + (_frm_nxt - _frm);
3188 to_nxt = to + (_to_nxt - _to);
3189 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003190}
3191
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003192__codecvt_utf8<wchar_t>::result
3193__codecvt_utf8<wchar_t>::do_in(state_type&,
3194 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003195 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3196{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003197 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3198 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3199 const uint8_t* _frm_nxt = _frm;
3200 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3201 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3202 uint32_t* _to_nxt = _to;
3203 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3204 _Maxcode_, _Mode_);
3205 frm_nxt = frm + (_frm_nxt - _frm);
3206 to_nxt = to + (_to_nxt - _to);
3207 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003208}
3209
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003210__codecvt_utf8<wchar_t>::result
3211__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003212 extern_type* to, extern_type*, extern_type*& to_nxt) const
3213{
3214 to_nxt = to;
3215 return noconv;
3216}
3217
3218int
Howard Hinnantc9834542011-05-31 15:34:58 +00003219__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003220{
3221 return 0;
3222}
3223
3224bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003225__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003226{
3227 return false;
3228}
3229
3230int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003231__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003232 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3233{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003234 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3235 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3236 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003237}
3238
3239int
Howard Hinnantc9834542011-05-31 15:34:58 +00003240__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003241{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003242 if (_Mode_ & consume_header)
3243 return 7;
3244 return 4;
3245}
3246
3247// __codecvt_utf8<char16_t>
3248
3249__codecvt_utf8<char16_t>::result
3250__codecvt_utf8<char16_t>::do_out(state_type&,
3251 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3252 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3253{
3254 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3255 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3256 const uint16_t* _frm_nxt = _frm;
3257 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3258 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3259 uint8_t* _to_nxt = _to;
3260 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3261 _Maxcode_, _Mode_);
3262 frm_nxt = frm + (_frm_nxt - _frm);
3263 to_nxt = to + (_to_nxt - _to);
3264 return r;
3265}
3266
3267__codecvt_utf8<char16_t>::result
3268__codecvt_utf8<char16_t>::do_in(state_type&,
3269 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3270 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3271{
3272 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3273 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3274 const uint8_t* _frm_nxt = _frm;
3275 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3276 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3277 uint16_t* _to_nxt = _to;
3278 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3279 _Maxcode_, _Mode_);
3280 frm_nxt = frm + (_frm_nxt - _frm);
3281 to_nxt = to + (_to_nxt - _to);
3282 return r;
3283}
3284
3285__codecvt_utf8<char16_t>::result
3286__codecvt_utf8<char16_t>::do_unshift(state_type&,
3287 extern_type* to, extern_type*, extern_type*& to_nxt) const
3288{
3289 to_nxt = to;
3290 return noconv;
3291}
3292
3293int
Howard Hinnantc9834542011-05-31 15:34:58 +00003294__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003295{
3296 return 0;
3297}
3298
3299bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003300__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003301{
3302 return false;
3303}
3304
3305int
3306__codecvt_utf8<char16_t>::do_length(state_type&,
3307 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3308{
3309 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3310 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3311 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3312}
3313
3314int
Howard Hinnantc9834542011-05-31 15:34:58 +00003315__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003316{
3317 if (_Mode_ & consume_header)
3318 return 6;
3319 return 3;
3320}
3321
3322// __codecvt_utf8<char32_t>
3323
3324__codecvt_utf8<char32_t>::result
3325__codecvt_utf8<char32_t>::do_out(state_type&,
3326 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3327 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3328{
3329 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3330 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3331 const uint32_t* _frm_nxt = _frm;
3332 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3333 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3334 uint8_t* _to_nxt = _to;
3335 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3336 _Maxcode_, _Mode_);
3337 frm_nxt = frm + (_frm_nxt - _frm);
3338 to_nxt = to + (_to_nxt - _to);
3339 return r;
3340}
3341
3342__codecvt_utf8<char32_t>::result
3343__codecvt_utf8<char32_t>::do_in(state_type&,
3344 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3345 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3346{
3347 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3348 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3349 const uint8_t* _frm_nxt = _frm;
3350 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3351 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3352 uint32_t* _to_nxt = _to;
3353 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3354 _Maxcode_, _Mode_);
3355 frm_nxt = frm + (_frm_nxt - _frm);
3356 to_nxt = to + (_to_nxt - _to);
3357 return r;
3358}
3359
3360__codecvt_utf8<char32_t>::result
3361__codecvt_utf8<char32_t>::do_unshift(state_type&,
3362 extern_type* to, extern_type*, extern_type*& to_nxt) const
3363{
3364 to_nxt = to;
3365 return noconv;
3366}
3367
3368int
Howard Hinnantc9834542011-05-31 15:34:58 +00003369__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003370{
3371 return 0;
3372}
3373
3374bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003375__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003376{
3377 return false;
3378}
3379
3380int
3381__codecvt_utf8<char32_t>::do_length(state_type&,
3382 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3383{
3384 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3385 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3386 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3387}
3388
3389int
Howard Hinnantc9834542011-05-31 15:34:58 +00003390__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003391{
3392 if (_Mode_ & consume_header)
3393 return 7;
3394 return 4;
3395}
3396
3397// __codecvt_utf16<wchar_t, false>
3398
3399__codecvt_utf16<wchar_t, false>::result
3400__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3401 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3402 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3403{
3404 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3405 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3406 const uint32_t* _frm_nxt = _frm;
3407 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3408 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3409 uint8_t* _to_nxt = _to;
3410 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3411 _Maxcode_, _Mode_);
3412 frm_nxt = frm + (_frm_nxt - _frm);
3413 to_nxt = to + (_to_nxt - _to);
3414 return r;
3415}
3416
3417__codecvt_utf16<wchar_t, false>::result
3418__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3419 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3420 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3421{
3422 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3423 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3424 const uint8_t* _frm_nxt = _frm;
3425 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3426 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3427 uint32_t* _to_nxt = _to;
3428 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3429 _Maxcode_, _Mode_);
3430 frm_nxt = frm + (_frm_nxt - _frm);
3431 to_nxt = to + (_to_nxt - _to);
3432 return r;
3433}
3434
3435__codecvt_utf16<wchar_t, false>::result
3436__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3437 extern_type* to, extern_type*, extern_type*& to_nxt) const
3438{
3439 to_nxt = to;
3440 return noconv;
3441}
3442
3443int
Howard Hinnantc9834542011-05-31 15:34:58 +00003444__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003445{
3446 return 0;
3447}
3448
3449bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003450__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003451{
3452 return false;
3453}
3454
3455int
3456__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3457 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3458{
3459 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3460 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3461 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3462}
3463
3464int
Howard Hinnantc9834542011-05-31 15:34:58 +00003465__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003466{
3467 if (_Mode_ & consume_header)
3468 return 6;
3469 return 4;
3470}
3471
3472// __codecvt_utf16<wchar_t, true>
3473
3474__codecvt_utf16<wchar_t, true>::result
3475__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3476 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3477 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3478{
3479 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3480 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3481 const uint32_t* _frm_nxt = _frm;
3482 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3483 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3484 uint8_t* _to_nxt = _to;
3485 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3486 _Maxcode_, _Mode_);
3487 frm_nxt = frm + (_frm_nxt - _frm);
3488 to_nxt = to + (_to_nxt - _to);
3489 return r;
3490}
3491
3492__codecvt_utf16<wchar_t, true>::result
3493__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3494 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3495 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3496{
3497 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3498 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3499 const uint8_t* _frm_nxt = _frm;
3500 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3501 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3502 uint32_t* _to_nxt = _to;
3503 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3504 _Maxcode_, _Mode_);
3505 frm_nxt = frm + (_frm_nxt - _frm);
3506 to_nxt = to + (_to_nxt - _to);
3507 return r;
3508}
3509
3510__codecvt_utf16<wchar_t, true>::result
3511__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3512 extern_type* to, extern_type*, extern_type*& to_nxt) const
3513{
3514 to_nxt = to;
3515 return noconv;
3516}
3517
3518int
Howard Hinnantc9834542011-05-31 15:34:58 +00003519__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003520{
3521 return 0;
3522}
3523
3524bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003525__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003526{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003527 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003528}
3529
3530int
3531__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3532 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3533{
3534 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3535 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3536 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3537}
3538
3539int
Howard Hinnantc9834542011-05-31 15:34:58 +00003540__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003541{
3542 if (_Mode_ & consume_header)
3543 return 6;
3544 return 4;
3545}
3546
3547// __codecvt_utf16<char16_t, false>
3548
3549__codecvt_utf16<char16_t, false>::result
3550__codecvt_utf16<char16_t, false>::do_out(state_type&,
3551 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3552 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3553{
3554 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3555 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3556 const uint16_t* _frm_nxt = _frm;
3557 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3558 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3559 uint8_t* _to_nxt = _to;
3560 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3561 _Maxcode_, _Mode_);
3562 frm_nxt = frm + (_frm_nxt - _frm);
3563 to_nxt = to + (_to_nxt - _to);
3564 return r;
3565}
3566
3567__codecvt_utf16<char16_t, false>::result
3568__codecvt_utf16<char16_t, false>::do_in(state_type&,
3569 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3570 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3571{
3572 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3573 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3574 const uint8_t* _frm_nxt = _frm;
3575 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3576 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3577 uint16_t* _to_nxt = _to;
3578 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3579 _Maxcode_, _Mode_);
3580 frm_nxt = frm + (_frm_nxt - _frm);
3581 to_nxt = to + (_to_nxt - _to);
3582 return r;
3583}
3584
3585__codecvt_utf16<char16_t, false>::result
3586__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3587 extern_type* to, extern_type*, extern_type*& to_nxt) const
3588{
3589 to_nxt = to;
3590 return noconv;
3591}
3592
3593int
Howard Hinnantc9834542011-05-31 15:34:58 +00003594__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003595{
3596 return 0;
3597}
3598
3599bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003600__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003601{
3602 return false;
3603}
3604
3605int
3606__codecvt_utf16<char16_t, false>::do_length(state_type&,
3607 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3608{
3609 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3610 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3611 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3612}
3613
3614int
Howard Hinnantc9834542011-05-31 15:34:58 +00003615__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003616{
3617 if (_Mode_ & consume_header)
3618 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003619 return 2;
3620}
3621
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003622// __codecvt_utf16<char16_t, true>
3623
3624__codecvt_utf16<char16_t, true>::result
3625__codecvt_utf16<char16_t, true>::do_out(state_type&,
3626 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3627 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3628{
3629 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3630 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3631 const uint16_t* _frm_nxt = _frm;
3632 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3633 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3634 uint8_t* _to_nxt = _to;
3635 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3636 _Maxcode_, _Mode_);
3637 frm_nxt = frm + (_frm_nxt - _frm);
3638 to_nxt = to + (_to_nxt - _to);
3639 return r;
3640}
3641
3642__codecvt_utf16<char16_t, true>::result
3643__codecvt_utf16<char16_t, true>::do_in(state_type&,
3644 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3645 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3646{
3647 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3648 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3649 const uint8_t* _frm_nxt = _frm;
3650 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3651 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3652 uint16_t* _to_nxt = _to;
3653 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3654 _Maxcode_, _Mode_);
3655 frm_nxt = frm + (_frm_nxt - _frm);
3656 to_nxt = to + (_to_nxt - _to);
3657 return r;
3658}
3659
3660__codecvt_utf16<char16_t, true>::result
3661__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3662 extern_type* to, extern_type*, extern_type*& to_nxt) const
3663{
3664 to_nxt = to;
3665 return noconv;
3666}
3667
3668int
Howard Hinnantc9834542011-05-31 15:34:58 +00003669__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003670{
3671 return 0;
3672}
3673
3674bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003675__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003676{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003677 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003678}
3679
3680int
3681__codecvt_utf16<char16_t, true>::do_length(state_type&,
3682 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3683{
3684 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3685 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3686 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3687}
3688
3689int
Howard Hinnantc9834542011-05-31 15:34:58 +00003690__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003691{
3692 if (_Mode_ & consume_header)
3693 return 4;
3694 return 2;
3695}
3696
3697// __codecvt_utf16<char32_t, false>
3698
3699__codecvt_utf16<char32_t, false>::result
3700__codecvt_utf16<char32_t, false>::do_out(state_type&,
3701 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3702 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3703{
3704 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3705 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3706 const uint32_t* _frm_nxt = _frm;
3707 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3708 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3709 uint8_t* _to_nxt = _to;
3710 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3711 _Maxcode_, _Mode_);
3712 frm_nxt = frm + (_frm_nxt - _frm);
3713 to_nxt = to + (_to_nxt - _to);
3714 return r;
3715}
3716
3717__codecvt_utf16<char32_t, false>::result
3718__codecvt_utf16<char32_t, false>::do_in(state_type&,
3719 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3720 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3721{
3722 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3723 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3724 const uint8_t* _frm_nxt = _frm;
3725 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3726 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3727 uint32_t* _to_nxt = _to;
3728 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3729 _Maxcode_, _Mode_);
3730 frm_nxt = frm + (_frm_nxt - _frm);
3731 to_nxt = to + (_to_nxt - _to);
3732 return r;
3733}
3734
3735__codecvt_utf16<char32_t, false>::result
3736__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3737 extern_type* to, extern_type*, extern_type*& to_nxt) const
3738{
3739 to_nxt = to;
3740 return noconv;
3741}
3742
3743int
Howard Hinnantc9834542011-05-31 15:34:58 +00003744__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003745{
3746 return 0;
3747}
3748
3749bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003750__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003751{
3752 return false;
3753}
3754
3755int
3756__codecvt_utf16<char32_t, false>::do_length(state_type&,
3757 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3758{
3759 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3760 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3761 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3762}
3763
3764int
Howard Hinnantc9834542011-05-31 15:34:58 +00003765__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003766{
3767 if (_Mode_ & consume_header)
3768 return 6;
3769 return 4;
3770}
3771
3772// __codecvt_utf16<char32_t, true>
3773
3774__codecvt_utf16<char32_t, true>::result
3775__codecvt_utf16<char32_t, true>::do_out(state_type&,
3776 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3777 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3778{
3779 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3780 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3781 const uint32_t* _frm_nxt = _frm;
3782 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3783 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3784 uint8_t* _to_nxt = _to;
3785 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3786 _Maxcode_, _Mode_);
3787 frm_nxt = frm + (_frm_nxt - _frm);
3788 to_nxt = to + (_to_nxt - _to);
3789 return r;
3790}
3791
3792__codecvt_utf16<char32_t, true>::result
3793__codecvt_utf16<char32_t, true>::do_in(state_type&,
3794 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3795 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3796{
3797 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3798 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3799 const uint8_t* _frm_nxt = _frm;
3800 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3801 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3802 uint32_t* _to_nxt = _to;
3803 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3804 _Maxcode_, _Mode_);
3805 frm_nxt = frm + (_frm_nxt - _frm);
3806 to_nxt = to + (_to_nxt - _to);
3807 return r;
3808}
3809
3810__codecvt_utf16<char32_t, true>::result
3811__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3812 extern_type* to, extern_type*, extern_type*& to_nxt) const
3813{
3814 to_nxt = to;
3815 return noconv;
3816}
3817
3818int
Howard Hinnantc9834542011-05-31 15:34:58 +00003819__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003820{
3821 return 0;
3822}
3823
3824bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003825__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003826{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003827 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003828}
3829
3830int
3831__codecvt_utf16<char32_t, true>::do_length(state_type&,
3832 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3833{
3834 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3835 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3836 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3837}
3838
3839int
Howard Hinnantc9834542011-05-31 15:34:58 +00003840__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003841{
3842 if (_Mode_ & consume_header)
3843 return 6;
3844 return 4;
3845}
3846
3847// __codecvt_utf8_utf16<wchar_t>
3848
3849__codecvt_utf8_utf16<wchar_t>::result
3850__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3851 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3852 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3853{
3854 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3855 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3856 const uint32_t* _frm_nxt = _frm;
3857 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3858 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3859 uint8_t* _to_nxt = _to;
3860 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3861 _Maxcode_, _Mode_);
3862 frm_nxt = frm + (_frm_nxt - _frm);
3863 to_nxt = to + (_to_nxt - _to);
3864 return r;
3865}
3866
3867__codecvt_utf8_utf16<wchar_t>::result
3868__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3869 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3870 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3871{
3872 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3873 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3874 const uint8_t* _frm_nxt = _frm;
3875 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3876 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3877 uint32_t* _to_nxt = _to;
3878 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3879 _Maxcode_, _Mode_);
3880 frm_nxt = frm + (_frm_nxt - _frm);
3881 to_nxt = to + (_to_nxt - _to);
3882 return r;
3883}
3884
3885__codecvt_utf8_utf16<wchar_t>::result
3886__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3887 extern_type* to, extern_type*, extern_type*& to_nxt) const
3888{
3889 to_nxt = to;
3890 return noconv;
3891}
3892
3893int
Howard Hinnantc9834542011-05-31 15:34:58 +00003894__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003895{
3896 return 0;
3897}
3898
3899bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003900__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003901{
3902 return false;
3903}
3904
3905int
3906__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3907 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3908{
3909 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3910 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3911 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3912}
3913
3914int
Howard Hinnantc9834542011-05-31 15:34:58 +00003915__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003916{
3917 if (_Mode_ & consume_header)
3918 return 7;
3919 return 4;
3920}
3921
3922// __codecvt_utf8_utf16<char16_t>
3923
3924__codecvt_utf8_utf16<char16_t>::result
3925__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3926 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3927 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3928{
3929 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3930 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3931 const uint16_t* _frm_nxt = _frm;
3932 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3933 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3934 uint8_t* _to_nxt = _to;
3935 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3936 _Maxcode_, _Mode_);
3937 frm_nxt = frm + (_frm_nxt - _frm);
3938 to_nxt = to + (_to_nxt - _to);
3939 return r;
3940}
3941
3942__codecvt_utf8_utf16<char16_t>::result
3943__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3944 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3945 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3946{
3947 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3948 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3949 const uint8_t* _frm_nxt = _frm;
3950 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3951 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3952 uint16_t* _to_nxt = _to;
3953 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3954 _Maxcode_, _Mode_);
3955 frm_nxt = frm + (_frm_nxt - _frm);
3956 to_nxt = to + (_to_nxt - _to);
3957 return r;
3958}
3959
3960__codecvt_utf8_utf16<char16_t>::result
3961__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3962 extern_type* to, extern_type*, extern_type*& to_nxt) const
3963{
3964 to_nxt = to;
3965 return noconv;
3966}
3967
3968int
Howard Hinnantc9834542011-05-31 15:34:58 +00003969__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003970{
3971 return 0;
3972}
3973
3974bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003975__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003976{
3977 return false;
3978}
3979
3980int
3981__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3982 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3983{
3984 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3985 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3986 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3987}
3988
3989int
Howard Hinnantc9834542011-05-31 15:34:58 +00003990__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003991{
3992 if (_Mode_ & consume_header)
3993 return 7;
3994 return 4;
3995}
3996
3997// __codecvt_utf8_utf16<char32_t>
3998
3999__codecvt_utf8_utf16<char32_t>::result
4000__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
4001 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
4002 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
4003{
4004 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
4005 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
4006 const uint32_t* _frm_nxt = _frm;
4007 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
4008 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
4009 uint8_t* _to_nxt = _to;
4010 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4011 _Maxcode_, _Mode_);
4012 frm_nxt = frm + (_frm_nxt - _frm);
4013 to_nxt = to + (_to_nxt - _to);
4014 return r;
4015}
4016
4017__codecvt_utf8_utf16<char32_t>::result
4018__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
4019 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
4020 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
4021{
4022 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4023 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4024 const uint8_t* _frm_nxt = _frm;
4025 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
4026 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
4027 uint32_t* _to_nxt = _to;
4028 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
4029 _Maxcode_, _Mode_);
4030 frm_nxt = frm + (_frm_nxt - _frm);
4031 to_nxt = to + (_to_nxt - _to);
4032 return r;
4033}
4034
4035__codecvt_utf8_utf16<char32_t>::result
4036__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
4037 extern_type* to, extern_type*, extern_type*& to_nxt) const
4038{
4039 to_nxt = to;
4040 return noconv;
4041}
4042
4043int
Howard Hinnantc9834542011-05-31 15:34:58 +00004044__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004045{
4046 return 0;
4047}
4048
4049bool
Howard Hinnantc9834542011-05-31 15:34:58 +00004050__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004051{
4052 return false;
4053}
4054
4055int
4056__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
4057 const extern_type* frm, const extern_type* frm_end, size_t mx) const
4058{
4059 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
4060 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
4061 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
4062}
4063
4064int
Howard Hinnantc9834542011-05-31 15:34:58 +00004065__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00004066{
4067 if (_Mode_ & consume_header)
4068 return 7;
4069 return 4;
4070}
4071
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004072// __narrow_to_utf8<16>
4073
4074__narrow_to_utf8<16>::~__narrow_to_utf8()
4075{
4076}
4077
4078// __narrow_to_utf8<32>
4079
4080__narrow_to_utf8<32>::~__narrow_to_utf8()
4081{
4082}
4083
4084// __widen_from_utf8<16>
4085
4086__widen_from_utf8<16>::~__widen_from_utf8()
4087{
4088}
4089
4090// __widen_from_utf8<32>
4091
4092__widen_from_utf8<32>::~__widen_from_utf8()
4093{
4094}
4095
4096// numpunct<char> && numpunct<wchar_t>
4097
4098locale::id numpunct< char >::id;
4099locale::id numpunct<wchar_t>::id;
4100
4101numpunct<char>::numpunct(size_t refs)
4102 : locale::facet(refs),
4103 __decimal_point_('.'),
4104 __thousands_sep_(',')
4105{
4106}
4107
4108numpunct<wchar_t>::numpunct(size_t refs)
4109 : locale::facet(refs),
4110 __decimal_point_(L'.'),
4111 __thousands_sep_(L',')
4112{
4113}
4114
4115numpunct<char>::~numpunct()
4116{
4117}
4118
4119numpunct<wchar_t>::~numpunct()
4120{
4121}
4122
4123 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4124wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4125
4126 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4127wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4128
4129string numpunct< char >::do_grouping() const {return __grouping_;}
4130string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4131
4132 string numpunct< char >::do_truename() const {return "true";}
4133wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4134
4135 string numpunct< char >::do_falsename() const {return "false";}
4136wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4137
4138// numpunct_byname<char>
4139
4140numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4141 : numpunct<char>(refs)
4142{
4143 __init(nm);
4144}
4145
4146numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4147 : numpunct<char>(refs)
4148{
4149 __init(nm.c_str());
4150}
4151
4152numpunct_byname<char>::~numpunct_byname()
4153{
4154}
4155
4156void
4157numpunct_byname<char>::__init(const char* nm)
4158{
4159 if (strcmp(nm, "C") != 0)
4160 {
Sean Huntf3907e62011-07-15 05:40:33 +00004161 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004162#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004163 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004164 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4165 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004166#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004167#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004168 lconv* lc = localeconv_l(loc.get());
4169#else
4170 lconv* lc = __localeconv_l(loc.get());
4171#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004172 if (*lc->decimal_point)
4173 __decimal_point_ = *lc->decimal_point;
4174 if (*lc->thousands_sep)
4175 __thousands_sep_ = *lc->thousands_sep;
4176 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004177 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004178 }
4179}
4180
4181// numpunct_byname<wchar_t>
4182
4183numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4184 : numpunct<wchar_t>(refs)
4185{
4186 __init(nm);
4187}
4188
4189numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4190 : numpunct<wchar_t>(refs)
4191{
4192 __init(nm.c_str());
4193}
4194
4195numpunct_byname<wchar_t>::~numpunct_byname()
4196{
4197}
4198
4199void
4200numpunct_byname<wchar_t>::__init(const char* nm)
4201{
4202 if (strcmp(nm, "C") != 0)
4203 {
Sean Huntf3907e62011-07-15 05:40:33 +00004204 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004205#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00004206 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004207 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4208 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004209#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004210#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004211 lconv* lc = localeconv_l(loc.get());
4212#else
4213 lconv* lc = __localeconv_l(loc.get());
4214#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004215 if (*lc->decimal_point)
4216 __decimal_point_ = *lc->decimal_point;
4217 if (*lc->thousands_sep)
4218 __thousands_sep_ = *lc->thousands_sep;
4219 __grouping_ = lc->grouping;
4220 // locallization for truename and falsename is not available
4221 }
4222}
4223
4224// num_get helpers
4225
4226int
4227__num_get_base::__get_base(ios_base& iob)
4228{
4229 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4230 if (__basefield == ios_base::oct)
4231 return 8;
4232 else if (__basefield == ios_base::hex)
4233 return 16;
4234 else if (__basefield == 0)
4235 return 0;
4236 return 10;
4237}
4238
4239const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4240
4241void
4242__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4243 ios_base::iostate& __err)
4244{
4245 if (__grouping.size() != 0)
4246 {
4247 reverse(__g, __g_end);
4248 const char* __ig = __grouping.data();
4249 const char* __eg = __ig + __grouping.size();
4250 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4251 {
4252 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4253 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004254 if (static_cast<unsigned>(*__ig) != *__r)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004255 {
4256 __err = ios_base::failbit;
4257 return;
4258 }
4259 }
4260 if (__eg - __ig > 1)
4261 ++__ig;
4262 }
4263 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4264 {
Howard Hinnantec3773c2011-12-01 20:21:04 +00004265 if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004266 __err = ios_base::failbit;
4267 }
4268 }
4269}
4270
4271void
4272__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4273 ios_base::fmtflags __flags)
4274{
4275 if (__flags & ios_base::showpos)
4276 *__fmtp++ = '+';
4277 if (__flags & ios_base::showbase)
4278 *__fmtp++ = '#';
4279 while(*__len)
4280 *__fmtp++ = *__len++;
4281 if ((__flags & ios_base::basefield) == ios_base::oct)
4282 *__fmtp = 'o';
4283 else if ((__flags & ios_base::basefield) == ios_base::hex)
4284 {
4285 if (__flags & ios_base::uppercase)
4286 *__fmtp = 'X';
4287 else
4288 *__fmtp = 'x';
4289 }
4290 else if (__signd)
4291 *__fmtp = 'd';
4292 else
4293 *__fmtp = 'u';
4294}
4295
4296bool
4297__num_put_base::__format_float(char* __fmtp, const char* __len,
4298 ios_base::fmtflags __flags)
4299{
4300 bool specify_precision = true;
4301 if (__flags & ios_base::showpos)
4302 *__fmtp++ = '+';
4303 if (__flags & ios_base::showpoint)
4304 *__fmtp++ = '#';
4305 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4306 bool uppercase = __flags & ios_base::uppercase;
4307 if (floatfield == (ios_base::fixed | ios_base::scientific))
4308 specify_precision = false;
4309 else
4310 {
4311 *__fmtp++ = '.';
4312 *__fmtp++ = '*';
4313 }
4314 while(*__len)
4315 *__fmtp++ = *__len++;
4316 if (floatfield == ios_base::fixed)
4317 {
4318 if (uppercase)
4319 *__fmtp = 'F';
4320 else
4321 *__fmtp = 'f';
4322 }
4323 else if (floatfield == ios_base::scientific)
4324 {
4325 if (uppercase)
4326 *__fmtp = 'E';
4327 else
4328 *__fmtp = 'e';
4329 }
4330 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4331 {
4332 if (uppercase)
4333 *__fmtp = 'A';
4334 else
4335 *__fmtp = 'a';
4336 }
4337 else
4338 {
4339 if (uppercase)
4340 *__fmtp = 'G';
4341 else
4342 *__fmtp = 'g';
4343 }
4344 return specify_precision;
4345}
4346
4347char*
4348__num_put_base::__identify_padding(char* __nb, char* __ne,
4349 const ios_base& __iob)
4350{
4351 switch (__iob.flags() & ios_base::adjustfield)
4352 {
4353 case ios_base::internal:
4354 if (__nb[0] == '-' || __nb[0] == '+')
4355 return __nb+1;
4356 if (__ne - __nb >= 2 && __nb[0] == '0'
4357 && (__nb[1] == 'x' || __nb[1] == 'X'))
4358 return __nb+2;
4359 break;
4360 case ios_base::left:
4361 return __ne;
4362 case ios_base::right:
4363 default:
4364 break;
4365 }
4366 return __nb;
4367}
4368
4369// time_get
4370
4371static
4372string*
4373init_weeks()
4374{
4375 static string weeks[14];
4376 weeks[0] = "Sunday";
4377 weeks[1] = "Monday";
4378 weeks[2] = "Tuesday";
4379 weeks[3] = "Wednesday";
4380 weeks[4] = "Thursday";
4381 weeks[5] = "Friday";
4382 weeks[6] = "Saturday";
4383 weeks[7] = "Sun";
4384 weeks[8] = "Mon";
4385 weeks[9] = "Tue";
4386 weeks[10] = "Wed";
4387 weeks[11] = "Thu";
4388 weeks[12] = "Fri";
4389 weeks[13] = "Sat";
4390 return weeks;
4391}
4392
4393static
4394wstring*
4395init_wweeks()
4396{
4397 static wstring weeks[14];
4398 weeks[0] = L"Sunday";
4399 weeks[1] = L"Monday";
4400 weeks[2] = L"Tuesday";
4401 weeks[3] = L"Wednesday";
4402 weeks[4] = L"Thursday";
4403 weeks[5] = L"Friday";
4404 weeks[6] = L"Saturday";
4405 weeks[7] = L"Sun";
4406 weeks[8] = L"Mon";
4407 weeks[9] = L"Tue";
4408 weeks[10] = L"Wed";
4409 weeks[11] = L"Thu";
4410 weeks[12] = L"Fri";
4411 weeks[13] = L"Sat";
4412 return weeks;
4413}
4414
4415template <>
4416const string*
4417__time_get_c_storage<char>::__weeks() const
4418{
4419 static const string* weeks = init_weeks();
4420 return weeks;
4421}
4422
4423template <>
4424const wstring*
4425__time_get_c_storage<wchar_t>::__weeks() const
4426{
4427 static const wstring* weeks = init_wweeks();
4428 return weeks;
4429}
4430
4431static
4432string*
4433init_months()
4434{
4435 static string months[24];
4436 months[0] = "January";
4437 months[1] = "February";
4438 months[2] = "March";
4439 months[3] = "April";
4440 months[4] = "May";
4441 months[5] = "June";
4442 months[6] = "July";
4443 months[7] = "August";
4444 months[8] = "September";
4445 months[9] = "October";
4446 months[10] = "November";
4447 months[11] = "December";
4448 months[12] = "Jan";
4449 months[13] = "Feb";
4450 months[14] = "Mar";
4451 months[15] = "Apr";
4452 months[16] = "May";
4453 months[17] = "Jun";
4454 months[18] = "Jul";
4455 months[19] = "Aug";
4456 months[20] = "Sep";
4457 months[21] = "Oct";
4458 months[22] = "Nov";
4459 months[23] = "Dec";
4460 return months;
4461}
4462
4463static
4464wstring*
4465init_wmonths()
4466{
4467 static wstring months[24];
4468 months[0] = L"January";
4469 months[1] = L"February";
4470 months[2] = L"March";
4471 months[3] = L"April";
4472 months[4] = L"May";
4473 months[5] = L"June";
4474 months[6] = L"July";
4475 months[7] = L"August";
4476 months[8] = L"September";
4477 months[9] = L"October";
4478 months[10] = L"November";
4479 months[11] = L"December";
4480 months[12] = L"Jan";
4481 months[13] = L"Feb";
4482 months[14] = L"Mar";
4483 months[15] = L"Apr";
4484 months[16] = L"May";
4485 months[17] = L"Jun";
4486 months[18] = L"Jul";
4487 months[19] = L"Aug";
4488 months[20] = L"Sep";
4489 months[21] = L"Oct";
4490 months[22] = L"Nov";
4491 months[23] = L"Dec";
4492 return months;
4493}
4494
4495template <>
4496const string*
4497__time_get_c_storage<char>::__months() const
4498{
4499 static const string* months = init_months();
4500 return months;
4501}
4502
4503template <>
4504const wstring*
4505__time_get_c_storage<wchar_t>::__months() const
4506{
4507 static const wstring* months = init_wmonths();
4508 return months;
4509}
4510
4511static
4512string*
4513init_am_pm()
4514{
4515 static string am_pm[24];
4516 am_pm[0] = "AM";
4517 am_pm[1] = "PM";
4518 return am_pm;
4519}
4520
4521static
4522wstring*
4523init_wam_pm()
4524{
4525 static wstring am_pm[24];
4526 am_pm[0] = L"AM";
4527 am_pm[1] = L"PM";
4528 return am_pm;
4529}
4530
4531template <>
4532const string*
4533__time_get_c_storage<char>::__am_pm() const
4534{
4535 static const string* am_pm = init_am_pm();
4536 return am_pm;
4537}
4538
4539template <>
4540const wstring*
4541__time_get_c_storage<wchar_t>::__am_pm() const
4542{
4543 static const wstring* am_pm = init_wam_pm();
4544 return am_pm;
4545}
4546
4547template <>
4548const string&
4549__time_get_c_storage<char>::__x() const
4550{
4551 static string s("%m/%d/%y");
4552 return s;
4553}
4554
4555template <>
4556const wstring&
4557__time_get_c_storage<wchar_t>::__x() const
4558{
4559 static wstring s(L"%m/%d/%y");
4560 return s;
4561}
4562
4563template <>
4564const string&
4565__time_get_c_storage<char>::__X() const
4566{
4567 static string s("%H:%M:%S");
4568 return s;
4569}
4570
4571template <>
4572const wstring&
4573__time_get_c_storage<wchar_t>::__X() const
4574{
4575 static wstring s(L"%H:%M:%S");
4576 return s;
4577}
4578
4579template <>
4580const string&
4581__time_get_c_storage<char>::__c() const
4582{
4583 static string s("%a %b %d %H:%M:%S %Y");
4584 return s;
4585}
4586
4587template <>
4588const wstring&
4589__time_get_c_storage<wchar_t>::__c() const
4590{
4591 static wstring s(L"%a %b %d %H:%M:%S %Y");
4592 return s;
4593}
4594
4595template <>
4596const string&
4597__time_get_c_storage<char>::__r() const
4598{
4599 static string s("%I:%M:%S %p");
4600 return s;
4601}
4602
4603template <>
4604const wstring&
4605__time_get_c_storage<wchar_t>::__r() const
4606{
4607 static wstring s(L"%I:%M:%S %p");
4608 return s;
4609}
4610
4611// time_get_byname
4612
4613__time_get::__time_get(const char* nm)
4614 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4615{
Howard Hinnantd4444702010-08-11 17:04:31 +00004616#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004617 if (__loc_ == 0)
4618 throw runtime_error("time_get_byname"
4619 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004620#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004621}
4622
4623__time_get::__time_get(const string& nm)
4624 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4625{
Howard Hinnantd4444702010-08-11 17:04:31 +00004626#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004627 if (__loc_ == 0)
4628 throw runtime_error("time_get_byname"
4629 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004630#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004631}
4632
4633__time_get::~__time_get()
4634{
4635 freelocale(__loc_);
4636}
4637
Howard Hinnant335b1512012-02-20 16:51:43 +00004638#pragma clang diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant21772ec2012-12-28 18:15:01 +00004639#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
Howard Hinnant335b1512012-02-20 16:51:43 +00004640
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004641template <>
4642string
4643__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4644{
Howard Hinnant3074a052012-02-19 14:55:32 +00004645 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004646 t.tm_sec = 59;
4647 t.tm_min = 55;
4648 t.tm_hour = 23;
4649 t.tm_mday = 31;
4650 t.tm_mon = 11;
4651 t.tm_year = 161;
4652 t.tm_wday = 6;
4653 t.tm_yday = 364;
4654 t.tm_isdst = -1;
4655 char buf[100];
4656 char f[3] = {0};
4657 f[0] = '%';
4658 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004659 size_t n = strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004660 char* bb = buf;
4661 char* be = buf + n;
4662 string result;
4663 while (bb != be)
4664 {
4665 if (ct.is(ctype_base::space, *bb))
4666 {
4667 result.push_back(' ');
4668 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4669 ;
4670 continue;
4671 }
4672 char* w = bb;
4673 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004674 ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004675 ct, err, false)
4676 - this->__weeks_;
4677 if (i < 14)
4678 {
4679 result.push_back('%');
4680 if (i < 7)
4681 result.push_back('A');
4682 else
4683 result.push_back('a');
4684 bb = w;
4685 continue;
4686 }
4687 w = bb;
4688 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4689 ct, err, false)
4690 - this->__months_;
4691 if (i < 24)
4692 {
4693 result.push_back('%');
4694 if (i < 12)
4695 result.push_back('B');
4696 else
4697 result.push_back('b');
4698 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4699 result.back() = 'm';
4700 bb = w;
4701 continue;
4702 }
4703 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4704 {
4705 w = bb;
4706 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4707 ct, err, false) - this->__am_pm_;
4708 if (i < 2)
4709 {
4710 result.push_back('%');
4711 result.push_back('p');
4712 bb = w;
4713 continue;
4714 }
4715 }
4716 w = bb;
4717 if (ct.is(ctype_base::digit, *bb))
4718 {
4719 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4720 {
4721 case 6:
4722 result.push_back('%');
4723 result.push_back('w');
4724 break;
4725 case 7:
4726 result.push_back('%');
4727 result.push_back('u');
4728 break;
4729 case 11:
4730 result.push_back('%');
4731 result.push_back('I');
4732 break;
4733 case 12:
4734 result.push_back('%');
4735 result.push_back('m');
4736 break;
4737 case 23:
4738 result.push_back('%');
4739 result.push_back('H');
4740 break;
4741 case 31:
4742 result.push_back('%');
4743 result.push_back('d');
4744 break;
4745 case 55:
4746 result.push_back('%');
4747 result.push_back('M');
4748 break;
4749 case 59:
4750 result.push_back('%');
4751 result.push_back('S');
4752 break;
4753 case 61:
4754 result.push_back('%');
4755 result.push_back('y');
4756 break;
4757 case 364:
4758 result.push_back('%');
4759 result.push_back('j');
4760 break;
4761 case 2061:
4762 result.push_back('%');
4763 result.push_back('Y');
4764 break;
4765 default:
4766 for (; w != bb; ++w)
4767 result.push_back(*w);
4768 break;
4769 }
4770 continue;
4771 }
4772 if (*bb == '%')
4773 {
4774 result.push_back('%');
4775 result.push_back('%');
4776 ++bb;
4777 continue;
4778 }
4779 result.push_back(*bb);
4780 ++bb;
4781 }
4782 return result;
4783}
4784
Howard Hinnantec3773c2011-12-01 20:21:04 +00004785#pragma clang diagnostic ignored "-Wmissing-braces"
Howard Hinnantec3773c2011-12-01 20:21:04 +00004786
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004787template <>
4788wstring
4789__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4790{
Howard Hinnant3074a052012-02-19 14:55:32 +00004791 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004792 t.tm_sec = 59;
4793 t.tm_min = 55;
4794 t.tm_hour = 23;
4795 t.tm_mday = 31;
4796 t.tm_mon = 11;
4797 t.tm_year = 161;
4798 t.tm_wday = 6;
4799 t.tm_yday = 364;
4800 t.tm_isdst = -1;
4801 char buf[100];
4802 char f[3] = {0};
4803 f[0] = '%';
4804 f[1] = fmt;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004805 strftime_l(buf, countof(buf), f, &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004806 wchar_t wbuf[100];
4807 wchar_t* wbb = wbuf;
4808 mbstate_t mb = {0};
4809 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004810#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004811 size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004812#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004813 size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004814#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004815 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004816 __throw_runtime_error("locale not supported");
Howard Hinnantec3773c2011-12-01 20:21:04 +00004817 wchar_t* wbe = wbb + j;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004818 wstring result;
4819 while (wbb != wbe)
4820 {
4821 if (ct.is(ctype_base::space, *wbb))
4822 {
4823 result.push_back(L' ');
4824 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4825 ;
4826 continue;
4827 }
4828 wchar_t* w = wbb;
4829 ios_base::iostate err = ios_base::goodbit;
Howard Hinnantec3773c2011-12-01 20:21:04 +00004830 ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004831 ct, err, false)
4832 - this->__weeks_;
4833 if (i < 14)
4834 {
4835 result.push_back(L'%');
4836 if (i < 7)
4837 result.push_back(L'A');
4838 else
4839 result.push_back(L'a');
4840 wbb = w;
4841 continue;
4842 }
4843 w = wbb;
4844 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4845 ct, err, false)
4846 - this->__months_;
4847 if (i < 24)
4848 {
4849 result.push_back(L'%');
4850 if (i < 12)
4851 result.push_back(L'B');
4852 else
4853 result.push_back(L'b');
4854 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4855 result.back() = L'm';
4856 wbb = w;
4857 continue;
4858 }
4859 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4860 {
4861 w = wbb;
4862 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4863 ct, err, false) - this->__am_pm_;
4864 if (i < 2)
4865 {
4866 result.push_back(L'%');
4867 result.push_back(L'p');
4868 wbb = w;
4869 continue;
4870 }
4871 }
4872 w = wbb;
4873 if (ct.is(ctype_base::digit, *wbb))
4874 {
4875 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4876 {
4877 case 6:
4878 result.push_back(L'%');
4879 result.push_back(L'w');
4880 break;
4881 case 7:
4882 result.push_back(L'%');
4883 result.push_back(L'u');
4884 break;
4885 case 11:
4886 result.push_back(L'%');
4887 result.push_back(L'I');
4888 break;
4889 case 12:
4890 result.push_back(L'%');
4891 result.push_back(L'm');
4892 break;
4893 case 23:
4894 result.push_back(L'%');
4895 result.push_back(L'H');
4896 break;
4897 case 31:
4898 result.push_back(L'%');
4899 result.push_back(L'd');
4900 break;
4901 case 55:
4902 result.push_back(L'%');
4903 result.push_back(L'M');
4904 break;
4905 case 59:
4906 result.push_back(L'%');
4907 result.push_back(L'S');
4908 break;
4909 case 61:
4910 result.push_back(L'%');
4911 result.push_back(L'y');
4912 break;
4913 case 364:
4914 result.push_back(L'%');
4915 result.push_back(L'j');
4916 break;
4917 case 2061:
4918 result.push_back(L'%');
4919 result.push_back(L'Y');
4920 break;
4921 default:
4922 for (; w != wbb; ++w)
4923 result.push_back(*w);
4924 break;
4925 }
4926 continue;
4927 }
4928 if (ct.narrow(*wbb, 0) == '%')
4929 {
4930 result.push_back(L'%');
4931 result.push_back(L'%');
4932 ++wbb;
4933 continue;
4934 }
4935 result.push_back(*wbb);
4936 ++wbb;
4937 }
4938 return result;
4939}
4940
4941template <>
4942void
4943__time_get_storage<char>::init(const ctype<char>& ct)
4944{
Howard Hinnantcd992362012-08-02 18:44:17 +00004945 tm t = {0};
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004946 char buf[100];
4947 // __weeks_
4948 for (int i = 0; i < 7; ++i)
4949 {
4950 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004951 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004952 __weeks_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004953 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004954 __weeks_[i+7] = buf;
4955 }
4956 // __months_
4957 for (int i = 0; i < 12; ++i)
4958 {
4959 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004960 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004961 __months_[i] = buf;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004962 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004963 __months_[i+12] = buf;
4964 }
4965 // __am_pm_
4966 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004967 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004968 __am_pm_[0] = buf;
4969 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004970 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004971 __am_pm_[1] = buf;
4972 __c_ = __analyze('c', ct);
4973 __r_ = __analyze('r', ct);
4974 __x_ = __analyze('x', ct);
4975 __X_ = __analyze('X', ct);
4976}
4977
4978template <>
4979void
4980__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4981{
4982 tm t = {0};
4983 char buf[100];
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004984 wchar_t wbuf[100];
4985 wchar_t* wbe;
4986 mbstate_t mb = {0};
4987 // __weeks_
4988 for (int i = 0; i < 7; ++i)
4989 {
4990 t.tm_wday = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004991 strftime_l(buf, countof(buf), "%A", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004992 mb = mbstate_t();
4993 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004994#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004995 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004996#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00004997 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00004998#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00004999 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005000 __throw_runtime_error("locale not supported");
5001 wbe = wbuf + j;
5002 __weeks_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005003 strftime_l(buf, countof(buf), "%a", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005004 mb = mbstate_t();
5005 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005006#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005007 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005008#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005009 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005010#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005011 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005012 __throw_runtime_error("locale not supported");
5013 wbe = wbuf + j;
5014 __weeks_[i+7].assign(wbuf, wbe);
5015 }
5016 // __months_
5017 for (int i = 0; i < 12; ++i)
5018 {
5019 t.tm_mon = i;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005020 strftime_l(buf, countof(buf), "%B", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005021 mb = mbstate_t();
5022 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005023#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005024 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005025#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005026 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005027#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005028 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005029 __throw_runtime_error("locale not supported");
5030 wbe = wbuf + j;
5031 __months_[i].assign(wbuf, wbe);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005032 strftime_l(buf, countof(buf), "%b", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005033 mb = mbstate_t();
5034 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005035#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005036 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005037#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005038 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005039#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005040 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005041 __throw_runtime_error("locale not supported");
5042 wbe = wbuf + j;
5043 __months_[i+12].assign(wbuf, wbe);
5044 }
5045 // __am_pm_
5046 t.tm_hour = 1;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005047 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005048 mb = mbstate_t();
5049 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005050#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005051 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005052#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005053 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005054#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005055 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005056 __throw_runtime_error("locale not supported");
5057 wbe = wbuf + j;
5058 __am_pm_[0].assign(wbuf, wbe);
5059 t.tm_hour = 13;
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005060 strftime_l(buf, countof(buf), "%p", &t, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005061 mb = mbstate_t();
5062 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00005063#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005064 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005065#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005066 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005067#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005068 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005069 __throw_runtime_error("locale not supported");
5070 wbe = wbuf + j;
5071 __am_pm_[1].assign(wbuf, wbe);
5072 __c_ = __analyze('c', ct);
5073 __r_ = __analyze('r', ct);
5074 __x_ = __analyze('x', ct);
5075 __X_ = __analyze('X', ct);
5076}
5077
5078template <class CharT>
5079struct _LIBCPP_HIDDEN __time_get_temp
5080 : public ctype_byname<CharT>
5081{
5082 explicit __time_get_temp(const char* nm)
5083 : ctype_byname<CharT>(nm, 1) {}
5084 explicit __time_get_temp(const string& nm)
5085 : ctype_byname<CharT>(nm, 1) {}
5086};
5087
5088template <>
5089__time_get_storage<char>::__time_get_storage(const char* __nm)
5090 : __time_get(__nm)
5091{
5092 const __time_get_temp<char> ct(__nm);
5093 init(ct);
5094}
5095
5096template <>
5097__time_get_storage<char>::__time_get_storage(const string& __nm)
5098 : __time_get(__nm)
5099{
5100 const __time_get_temp<char> ct(__nm);
5101 init(ct);
5102}
5103
5104template <>
5105__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5106 : __time_get(__nm)
5107{
5108 const __time_get_temp<wchar_t> ct(__nm);
5109 init(ct);
5110}
5111
5112template <>
5113__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5114 : __time_get(__nm)
5115{
5116 const __time_get_temp<wchar_t> ct(__nm);
5117 init(ct);
5118}
5119
5120template <>
5121time_base::dateorder
5122__time_get_storage<char>::__do_date_order() const
5123{
5124 unsigned i;
5125 for (i = 0; i < __x_.size(); ++i)
5126 if (__x_[i] == '%')
5127 break;
5128 ++i;
5129 switch (__x_[i])
5130 {
5131 case 'y':
5132 case 'Y':
5133 for (++i; i < __x_.size(); ++i)
5134 if (__x_[i] == '%')
5135 break;
5136 if (i == __x_.size())
5137 break;
5138 ++i;
5139 switch (__x_[i])
5140 {
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 return time_base::ymd;
5150 break;
5151 case 'd':
5152 for (++i; i < __x_.size(); ++i)
5153 if (__x_[i] == '%')
5154 break;
5155 if (i == __x_.size())
5156 break;
5157 ++i;
5158 if (__x_[i] == 'm')
5159 return time_base::ydm;
5160 break;
5161 }
5162 break;
5163 case 'm':
5164 for (++i; i < __x_.size(); ++i)
5165 if (__x_[i] == '%')
5166 break;
5167 if (i == __x_.size())
5168 break;
5169 ++i;
5170 if (__x_[i] == 'd')
5171 {
5172 for (++i; i < __x_.size(); ++i)
5173 if (__x_[i] == '%')
5174 break;
5175 if (i == __x_.size())
5176 break;
5177 ++i;
5178 if (__x_[i] == 'y' || __x_[i] == 'Y')
5179 return time_base::mdy;
5180 break;
5181 }
5182 break;
5183 case 'd':
5184 for (++i; i < __x_.size(); ++i)
5185 if (__x_[i] == '%')
5186 break;
5187 if (i == __x_.size())
5188 break;
5189 ++i;
5190 if (__x_[i] == 'm')
5191 {
5192 for (++i; i < __x_.size(); ++i)
5193 if (__x_[i] == '%')
5194 break;
5195 if (i == __x_.size())
5196 break;
5197 ++i;
5198 if (__x_[i] == 'y' || __x_[i] == 'Y')
5199 return time_base::dmy;
5200 break;
5201 }
5202 break;
5203 }
5204 return time_base::no_order;
5205}
5206
5207template <>
5208time_base::dateorder
5209__time_get_storage<wchar_t>::__do_date_order() const
5210{
5211 unsigned i;
5212 for (i = 0; i < __x_.size(); ++i)
5213 if (__x_[i] == L'%')
5214 break;
5215 ++i;
5216 switch (__x_[i])
5217 {
5218 case L'y':
5219 case L'Y':
5220 for (++i; i < __x_.size(); ++i)
5221 if (__x_[i] == L'%')
5222 break;
5223 if (i == __x_.size())
5224 break;
5225 ++i;
5226 switch (__x_[i])
5227 {
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 return time_base::ymd;
5237 break;
5238 case L'd':
5239 for (++i; i < __x_.size(); ++i)
5240 if (__x_[i] == L'%')
5241 break;
5242 if (i == __x_.size())
5243 break;
5244 ++i;
5245 if (__x_[i] == L'm')
5246 return time_base::ydm;
5247 break;
5248 }
5249 break;
5250 case L'm':
5251 for (++i; i < __x_.size(); ++i)
5252 if (__x_[i] == L'%')
5253 break;
5254 if (i == __x_.size())
5255 break;
5256 ++i;
5257 if (__x_[i] == L'd')
5258 {
5259 for (++i; i < __x_.size(); ++i)
5260 if (__x_[i] == L'%')
5261 break;
5262 if (i == __x_.size())
5263 break;
5264 ++i;
5265 if (__x_[i] == L'y' || __x_[i] == L'Y')
5266 return time_base::mdy;
5267 break;
5268 }
5269 break;
5270 case L'd':
5271 for (++i; i < __x_.size(); ++i)
5272 if (__x_[i] == L'%')
5273 break;
5274 if (i == __x_.size())
5275 break;
5276 ++i;
5277 if (__x_[i] == L'm')
5278 {
5279 for (++i; i < __x_.size(); ++i)
5280 if (__x_[i] == L'%')
5281 break;
5282 if (i == __x_.size())
5283 break;
5284 ++i;
5285 if (__x_[i] == L'y' || __x_[i] == L'Y')
5286 return time_base::dmy;
5287 break;
5288 }
5289 break;
5290 }
5291 return time_base::no_order;
5292}
5293
5294// time_put
5295
5296__time_put::__time_put(const char* nm)
5297 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5298{
Howard Hinnantd4444702010-08-11 17:04:31 +00005299#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005300 if (__loc_ == 0)
5301 throw runtime_error("time_put_byname"
5302 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005303#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005304}
5305
5306__time_put::__time_put(const string& nm)
5307 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5308{
Howard Hinnantd4444702010-08-11 17:04:31 +00005309#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005310 if (__loc_ == 0)
5311 throw runtime_error("time_put_byname"
5312 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005313#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005314}
5315
5316__time_put::~__time_put()
5317{
5318 if (__loc_)
5319 freelocale(__loc_);
5320}
5321
5322void
5323__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5324 char __fmt, char __mod) const
5325{
5326 char fmt[] = {'%', __fmt, __mod, 0};
5327 if (__mod != 0)
5328 swap(fmt[1], fmt[2]);
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005329 size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005330 __ne = __nb + n;
5331}
5332
5333void
5334__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5335 char __fmt, char __mod) const
5336{
5337 char __nar[100];
5338 char* __ne = __nar + 100;
5339 __do_put(__nar, __ne, __tm, __fmt, __mod);
5340 mbstate_t mb = {0};
5341 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005342#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005343 size_t j = mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005344#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005345 size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_);
Sean Huntf3907e62011-07-15 05:40:33 +00005346#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005347 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005348 __throw_runtime_error("locale not supported");
5349 __we = __wb + j;
5350}
5351
5352// moneypunct_byname
5353
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005354template <class charT>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005355static
5356void
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005357__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_,
5358 bool intl, char cs_precedes, char sep_by_space, char sign_posn,
5359 charT space_char)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005360{
5361 const char sign = static_cast<char>(money_base::sign);
5362 const char space = static_cast<char>(money_base::space);
5363 const char none = static_cast<char>(money_base::none);
5364 const char symbol = static_cast<char>(money_base::symbol);
5365 const char value = static_cast<char>(money_base::value);
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005366 const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4;
5367
5368 // Comments on case branches reflect 'C11 7.11.2.1 The localeconv
5369 // function'. "Space between sign and symbol or value" means that
5370 // if the sign is adjacent to the symbol, there's a space between
5371 // them, and otherwise there's a space between the sign and value.
5372 //
5373 // C11's localeconv specifies that the fourth character of an
5374 // international curr_symbol is used to separate the sign and
5375 // value when sep_by_space says to do so. C++ can't represent
5376 // that, so we just use a space. When sep_by_space says to
5377 // separate the symbol and value-or-sign with a space, we rearrange the
5378 // curr_symbol to put its spacing character on the correct side of
5379 // the symbol.
5380 //
5381 // We also need to avoid adding an extra space between the sign
5382 // and value when the currency symbol is suppressed (by not
5383 // setting showbase). We match glibc's strfmon by interpreting
5384 // sep_by_space==1 as "omit the space when the currency symbol is
5385 // absent".
5386 //
5387 // Users who want to get this right should use ICU instead.
5388
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005389 switch (cs_precedes)
5390 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005391 case 0: // value before curr_symbol
5392 if (symbol_contains_sep) {
5393 // Move the separator to before the symbol, to place it
5394 // between the value and symbol.
5395 rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3,
5396 __curr_symbol_.end());
5397 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005398 switch (sign_posn)
5399 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005400 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005401 pat.field[0] = sign;
5402 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005403 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005404 pat.field[3] = symbol;
5405 switch (sep_by_space)
5406 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005407 case 0: // No space separates the currency symbol and value.
5408 // This case may have changed between C99 and C11;
5409 // assume the currency symbol matches the intention.
5410 case 2: // Space between sign and currency or value.
5411 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005412 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005413 case 1: // Space between currency-and-sign or currency and value.
5414 if (!symbol_contains_sep) {
5415 // We insert the space into the symbol instead of
5416 // setting pat.field[2]=space so that when
5417 // showbase is not set, the space goes away too.
5418 __curr_symbol_.insert(0, 1, space_char);
5419 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005420 return;
5421 default:
5422 break;
5423 }
5424 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005425 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005426 pat.field[0] = sign;
5427 pat.field[3] = symbol;
5428 switch (sep_by_space)
5429 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005430 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005431 pat.field[1] = value;
5432 pat.field[2] = none;
5433 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005434 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005435 pat.field[1] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005436 pat.field[2] = none;
5437 if (!symbol_contains_sep) {
5438 // We insert the space into the symbol instead of
5439 // setting pat.field[2]=space so that when
5440 // showbase is not set, the space goes away too.
5441 __curr_symbol_.insert(0, 1, space_char);
5442 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005443 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005444 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005445 pat.field[1] = space;
5446 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005447 if (symbol_contains_sep) {
5448 // Remove the separator from the symbol, since it
5449 // has already appeared after the sign.
5450 __curr_symbol_.erase(__curr_symbol_.begin());
5451 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005452 return;
5453 default:
5454 break;
5455 }
5456 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005457 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005458 pat.field[0] = value;
5459 pat.field[3] = sign;
5460 switch (sep_by_space)
5461 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005462 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005463 pat.field[1] = none;
5464 pat.field[2] = symbol;
5465 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005466 case 1: // Space between currency-and-sign or currency and value.
5467 if (!symbol_contains_sep) {
5468 // We insert the space into the symbol instead of
5469 // setting pat.field[1]=space so that when
5470 // showbase is not set, the space goes away too.
5471 __curr_symbol_.insert(0, 1, space_char);
5472 }
5473 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005474 pat.field[2] = symbol;
5475 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005476 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005477 pat.field[1] = symbol;
5478 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005479 if (symbol_contains_sep) {
5480 // Remove the separator from the symbol, since it
5481 // should not be removed if showbase is absent.
5482 __curr_symbol_.erase(__curr_symbol_.begin());
5483 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005484 return;
5485 default:
5486 break;
5487 }
5488 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005489 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005490 pat.field[0] = value;
5491 pat.field[3] = symbol;
5492 switch (sep_by_space)
5493 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005494 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005495 pat.field[1] = none;
5496 pat.field[2] = sign;
5497 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005498 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005499 pat.field[1] = space;
5500 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005501 if (symbol_contains_sep) {
5502 // Remove the separator from the symbol, since it
5503 // has already appeared before the sign.
5504 __curr_symbol_.erase(__curr_symbol_.begin());
5505 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005506 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005507 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005508 pat.field[1] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005509 pat.field[2] = none;
5510 if (!symbol_contains_sep) {
5511 // We insert the space into the symbol instead of
5512 // setting pat.field[2]=space so that when
5513 // showbase is not set, the space goes away too.
5514 __curr_symbol_.insert(0, 1, space_char);
5515 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005516 return;
5517 default:
5518 break;
5519 }
5520 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005521 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005522 pat.field[0] = value;
5523 pat.field[3] = sign;
5524 switch (sep_by_space)
5525 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005526 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005527 pat.field[1] = none;
5528 pat.field[2] = symbol;
5529 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005530 case 1: // Space between currency-and-sign or currency and value.
5531 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005532 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005533 if (!symbol_contains_sep) {
5534 // We insert the space into the symbol instead of
5535 // setting pat.field[1]=space so that when
5536 // showbase is not set, the space goes away too.
5537 __curr_symbol_.insert(0, 1, space_char);
5538 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005539 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005540 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005541 pat.field[1] = symbol;
5542 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005543 if (symbol_contains_sep) {
5544 // Remove the separator from the symbol, since it
5545 // should not disappear when showbase is absent.
5546 __curr_symbol_.erase(__curr_symbol_.begin());
5547 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005548 return;
5549 default:
5550 break;
5551 }
5552 break;
5553 default:
5554 break;
5555 }
5556 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005557 case 1: // curr_symbol before value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005558 switch (sign_posn)
5559 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005560 case 0: // Parentheses surround the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005561 pat.field[0] = sign;
5562 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005563 pat.field[2] = none; // Any space appears in the symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005564 pat.field[3] = value;
5565 switch (sep_by_space)
5566 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005567 case 0: // No space separates the currency symbol and value.
5568 // This case may have changed between C99 and C11;
5569 // assume the currency symbol matches the intention.
5570 case 2: // Space between sign and currency or value.
5571 // The "sign" is two parentheses, so no space here either.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005572 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005573 case 1: // Space between currency-and-sign or currency and value.
5574 if (!symbol_contains_sep) {
5575 // We insert the space into the symbol instead of
5576 // setting pat.field[2]=space so that when
5577 // showbase is not set, the space goes away too.
5578 __curr_symbol_.insert(0, 1, space_char);
5579 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005580 return;
5581 default:
5582 break;
5583 }
5584 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005585 case 1: // The sign string precedes the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005586 pat.field[0] = sign;
5587 pat.field[3] = value;
5588 switch (sep_by_space)
5589 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005590 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005591 pat.field[1] = symbol;
5592 pat.field[2] = none;
5593 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005594 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005595 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005596 pat.field[2] = none;
5597 if (!symbol_contains_sep) {
5598 // We insert the space into the symbol instead of
5599 // setting pat.field[2]=space so that when
5600 // showbase is not set, the space goes away too.
5601 __curr_symbol_.push_back(space_char);
5602 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005603 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005604 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005605 pat.field[1] = space;
5606 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005607 if (symbol_contains_sep) {
5608 // Remove the separator from the symbol, since it
5609 // has already appeared after the sign.
5610 __curr_symbol_.pop_back();
5611 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005612 return;
5613 default:
5614 break;
5615 }
5616 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005617 case 2: // The sign string succeeds the quantity and currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005618 pat.field[0] = symbol;
5619 pat.field[3] = sign;
5620 switch (sep_by_space)
5621 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005622 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005623 pat.field[1] = none;
5624 pat.field[2] = value;
5625 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005626 case 1: // Space between currency-and-sign or currency and value.
5627 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005628 pat.field[2] = value;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005629 if (!symbol_contains_sep) {
5630 // We insert the space into the symbol instead of
5631 // setting pat.field[1]=space so that when
5632 // showbase is not set, the space goes away too.
5633 __curr_symbol_.push_back(space_char);
5634 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005635 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005636 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005637 pat.field[1] = value;
5638 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005639 if (symbol_contains_sep) {
5640 // Remove the separator from the symbol, since it
5641 // will appear before the sign.
5642 __curr_symbol_.pop_back();
5643 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005644 return;
5645 default:
5646 break;
5647 }
5648 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005649 case 3: // The sign string immediately precedes the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005650 pat.field[0] = sign;
5651 pat.field[3] = value;
5652 switch (sep_by_space)
5653 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005654 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005655 pat.field[1] = symbol;
5656 pat.field[2] = none;
5657 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005658 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005659 pat.field[1] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005660 pat.field[2] = none;
5661 if (!symbol_contains_sep) {
5662 // We insert the space into the symbol instead of
5663 // setting pat.field[2]=space so that when
5664 // showbase is not set, the space goes away too.
5665 __curr_symbol_.push_back(space_char);
5666 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005667 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005668 case 2: // Space between sign and currency or value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005669 pat.field[1] = space;
5670 pat.field[2] = symbol;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005671 if (symbol_contains_sep) {
5672 // Remove the separator from the symbol, since it
5673 // has already appeared after the sign.
5674 __curr_symbol_.pop_back();
5675 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005676 return;
5677 default:
5678 break;
5679 }
5680 break;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005681 case 4: // The sign string immediately succeeds the currency symbol.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005682 pat.field[0] = symbol;
5683 pat.field[3] = value;
5684 switch (sep_by_space)
5685 {
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005686 case 0: // No space separates the currency symbol and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005687 pat.field[1] = sign;
5688 pat.field[2] = none;
5689 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005690 case 1: // Space between currency-and-sign or currency and value.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005691 pat.field[1] = sign;
5692 pat.field[2] = space;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005693 if (symbol_contains_sep) {
5694 // Remove the separator from the symbol, since it
5695 // should not disappear when showbase is absent.
5696 __curr_symbol_.pop_back();
5697 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005698 return;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005699 case 2: // Space between sign and currency or value.
5700 pat.field[1] = none;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005701 pat.field[2] = sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005702 if (!symbol_contains_sep) {
5703 // We insert the space into the symbol instead of
5704 // setting pat.field[1]=space so that when
5705 // showbase is not set, the space goes away too.
5706 __curr_symbol_.push_back(space_char);
5707 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005708 return;
5709 default:
5710 break;
5711 }
5712 break;
5713 default:
5714 break;
5715 }
5716 break;
5717 default:
5718 break;
5719 }
5720 pat.field[0] = symbol;
5721 pat.field[1] = sign;
5722 pat.field[2] = none;
5723 pat.field[3] = value;
5724}
5725
5726template<>
5727void
5728moneypunct_byname<char, false>::init(const char* nm)
5729{
5730 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005731 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005732#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005733 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005734 throw runtime_error("moneypunct_byname"
5735 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005736#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005737#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005738 lconv* lc = localeconv_l(loc.get());
5739#else
5740 lconv* lc = __localeconv_l(loc.get());
5741#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005742 if (*lc->mon_decimal_point)
5743 __decimal_point_ = *lc->mon_decimal_point;
5744 else
5745 __decimal_point_ = base::do_decimal_point();
5746 if (*lc->mon_thousands_sep)
5747 __thousands_sep_ = *lc->mon_thousands_sep;
5748 else
5749 __thousands_sep_ = base::do_thousands_sep();
5750 __grouping_ = lc->mon_grouping;
5751 __curr_symbol_ = lc->currency_symbol;
5752 if (lc->frac_digits != CHAR_MAX)
5753 __frac_digits_ = lc->frac_digits;
5754 else
5755 __frac_digits_ = base::do_frac_digits();
5756 if (lc->p_sign_posn == 0)
5757 __positive_sign_ = "()";
5758 else
5759 __positive_sign_ = lc->positive_sign;
5760 if (lc->n_sign_posn == 0)
5761 __negative_sign_ = "()";
5762 else
5763 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005764 // Assume the positive and negative formats will want spaces in
5765 // the same places in curr_symbol since there's no way to
5766 // represent anything else.
5767 string_type __dummy_curr_symbol = __curr_symbol_;
5768 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5769 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5770 __init_pat(__neg_format_, __curr_symbol_, false,
5771 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005772}
5773
5774template<>
5775void
5776moneypunct_byname<char, true>::init(const char* nm)
5777{
5778 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005779 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005780#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005781 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005782 throw runtime_error("moneypunct_byname"
5783 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005784#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005785#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005786 lconv* lc = localeconv_l(loc.get());
5787#else
5788 lconv* lc = __localeconv_l(loc.get());
5789#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005790 if (*lc->mon_decimal_point)
5791 __decimal_point_ = *lc->mon_decimal_point;
5792 else
5793 __decimal_point_ = base::do_decimal_point();
5794 if (*lc->mon_thousands_sep)
5795 __thousands_sep_ = *lc->mon_thousands_sep;
5796 else
5797 __thousands_sep_ = base::do_thousands_sep();
5798 __grouping_ = lc->mon_grouping;
5799 __curr_symbol_ = lc->int_curr_symbol;
5800 if (lc->int_frac_digits != CHAR_MAX)
5801 __frac_digits_ = lc->int_frac_digits;
5802 else
5803 __frac_digits_ = base::do_frac_digits();
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005804#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005805 if (lc->p_sign_posn == 0)
5806#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005807 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005808#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005809 __positive_sign_ = "()";
5810 else
5811 __positive_sign_ = lc->positive_sign;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005812#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005813 if(lc->n_sign_posn == 0)
5814#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005815 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005816#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005817 __negative_sign_ = "()";
5818 else
5819 __negative_sign_ = lc->negative_sign;
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005820 // Assume the positive and negative formats will want spaces in
5821 // the same places in curr_symbol since there's no way to
5822 // represent anything else.
5823 string_type __dummy_curr_symbol = __curr_symbol_;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005824#ifdef _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005825 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5826 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' ');
5827 __init_pat(__neg_format_, __curr_symbol_, true,
5828 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005829#else
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005830 __init_pat(__pos_format_, __dummy_curr_symbol, true,
5831 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
5832 lc->int_p_sign_posn, ' ');
5833 __init_pat(__neg_format_, __curr_symbol_, true,
5834 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
5835 lc->int_n_sign_posn, ' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005836#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005837}
5838
5839template<>
5840void
5841moneypunct_byname<wchar_t, false>::init(const char* nm)
5842{
5843 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005844 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005845#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005846 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005847 throw runtime_error("moneypunct_byname"
5848 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005849#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005850#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005851 lconv* lc = localeconv_l(loc.get());
5852#else
5853 lconv* lc = __localeconv_l(loc.get());
5854#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005855 if (*lc->mon_decimal_point)
5856 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5857 else
5858 __decimal_point_ = base::do_decimal_point();
5859 if (*lc->mon_thousands_sep)
5860 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5861 else
5862 __thousands_sep_ = base::do_thousands_sep();
5863 __grouping_ = lc->mon_grouping;
5864 wchar_t wbuf[100];
5865 mbstate_t mb = {0};
5866 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005867#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005868 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005869#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005870 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005871#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005872 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005873 __throw_runtime_error("locale not supported");
5874 wchar_t* wbe = wbuf + j;
5875 __curr_symbol_.assign(wbuf, wbe);
5876 if (lc->frac_digits != CHAR_MAX)
5877 __frac_digits_ = lc->frac_digits;
5878 else
5879 __frac_digits_ = base::do_frac_digits();
5880 if (lc->p_sign_posn == 0)
5881 __positive_sign_ = L"()";
5882 else
5883 {
5884 mb = mbstate_t();
5885 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005886#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005887 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005888#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005889 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005890#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005891 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005892 __throw_runtime_error("locale not supported");
5893 wbe = wbuf + j;
5894 __positive_sign_.assign(wbuf, wbe);
5895 }
5896 if (lc->n_sign_posn == 0)
5897 __negative_sign_ = L"()";
5898 else
5899 {
5900 mb = mbstate_t();
5901 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005902#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005903 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005904#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005905 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005906#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005907 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005908 __throw_runtime_error("locale not supported");
5909 wbe = wbuf + j;
5910 __negative_sign_.assign(wbuf, wbe);
5911 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00005912 // Assume the positive and negative formats will want spaces in
5913 // the same places in curr_symbol since there's no way to
5914 // represent anything else.
5915 string_type __dummy_curr_symbol = __curr_symbol_;
5916 __init_pat(__pos_format_, __dummy_curr_symbol, false,
5917 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
5918 __init_pat(__neg_format_, __curr_symbol_, false,
5919 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005920}
5921
5922template<>
5923void
5924moneypunct_byname<wchar_t, true>::init(const char* nm)
5925{
5926 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005927 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005928#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant05b57d52012-03-07 20:37:43 +00005929 if (loc == nullptr)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005930 throw runtime_error("moneypunct_byname"
5931 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005932#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005933#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005934 lconv* lc = localeconv_l(loc.get());
5935#else
5936 lconv* lc = __localeconv_l(loc.get());
5937#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005938 if (*lc->mon_decimal_point)
5939 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5940 else
5941 __decimal_point_ = base::do_decimal_point();
5942 if (*lc->mon_thousands_sep)
5943 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5944 else
5945 __thousands_sep_ = base::do_thousands_sep();
5946 __grouping_ = lc->mon_grouping;
5947 wchar_t wbuf[100];
5948 mbstate_t mb = {0};
5949 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005950#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005951 size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005952#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005953 size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005954#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005955 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005956 __throw_runtime_error("locale not supported");
5957 wchar_t* wbe = wbuf + j;
5958 __curr_symbol_.assign(wbuf, wbe);
5959 if (lc->int_frac_digits != CHAR_MAX)
5960 __frac_digits_ = lc->int_frac_digits;
5961 else
5962 __frac_digits_ = base::do_frac_digits();
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005963#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005964 if (lc->p_sign_posn == 0)
5965#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005966 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005967#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005968 __positive_sign_ = L"()";
5969 else
5970 {
5971 mb = mbstate_t();
5972 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005973#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
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#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005976 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005977#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005978 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005979 __throw_runtime_error("locale not supported");
5980 wbe = wbuf + j;
5981 __positive_sign_.assign(wbuf, wbe);
5982 }
Marshall Clowa22d2ad2013-03-18 17:04:29 +00005983#ifdef _WIN32
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005984 if (lc->n_sign_posn == 0)
5985#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005986 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005987#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005988 __negative_sign_ = L"()";
5989 else
5990 {
5991 mb = mbstate_t();
5992 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005993#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005994 j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005995#else
Howard Hinnantbf68bdc2012-12-27 21:17:53 +00005996 j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get());
Sean Huntf3907e62011-07-15 05:40:33 +00005997#endif
Howard Hinnantec3773c2011-12-01 20:21:04 +00005998 if (j == size_t(-1))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005999 __throw_runtime_error("locale not supported");
6000 wbe = wbuf + j;
6001 __negative_sign_.assign(wbuf, wbe);
6002 }
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006003 // Assume the positive and negative formats will want spaces in
6004 // the same places in curr_symbol since there's no way to
6005 // represent anything else.
6006 string_type __dummy_curr_symbol = __curr_symbol_;
Marshall Clowa22d2ad2013-03-18 17:04:29 +00006007#ifdef _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006008 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6009 lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' ');
6010 __init_pat(__neg_format_, __curr_symbol_, true,
6011 lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006012#else // _WIN32
Jeffrey Yasskin558ae172012-03-10 18:31:43 +00006013 __init_pat(__pos_format_, __dummy_curr_symbol, true,
6014 lc->int_p_cs_precedes, lc->int_p_sep_by_space,
6015 lc->int_p_sign_posn, L' ');
6016 __init_pat(__neg_format_, __curr_symbol_, true,
6017 lc->int_n_cs_precedes, lc->int_n_sep_by_space,
6018 lc->int_n_sign_posn, L' ');
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00006019#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006020}
6021
6022void __do_nothing(void*) {}
6023
6024void __throw_runtime_error(const char* msg)
6025{
Howard Hinnantd4444702010-08-11 17:04:31 +00006026#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006027 throw runtime_error(msg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +00006028#else
6029 (void)msg;
Howard Hinnantd4444702010-08-11 17:04:31 +00006030#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006031}
6032
6033template class collate<char>;
6034template class collate<wchar_t>;
6035
6036template class num_get<char>;
6037template class num_get<wchar_t>;
6038
Howard Hinnantec3773c2011-12-01 20:21:04 +00006039template struct __num_get<char>;
6040template struct __num_get<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006041
6042template class num_put<char>;
6043template class num_put<wchar_t>;
6044
Howard Hinnantec3773c2011-12-01 20:21:04 +00006045template struct __num_put<char>;
6046template struct __num_put<wchar_t>;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00006047
6048template class time_get<char>;
6049template class time_get<wchar_t>;
6050
6051template class time_get_byname<char>;
6052template class time_get_byname<wchar_t>;
6053
6054template class time_put<char>;
6055template class time_put<wchar_t>;
6056
6057template class time_put_byname<char>;
6058template class time_put_byname<wchar_t>;
6059
6060template class moneypunct<char, false>;
6061template class moneypunct<char, true>;
6062template class moneypunct<wchar_t, false>;
6063template class moneypunct<wchar_t, true>;
6064
6065template class moneypunct_byname<char, false>;
6066template class moneypunct_byname<char, true>;
6067template class moneypunct_byname<wchar_t, false>;
6068template class moneypunct_byname<wchar_t, true>;
6069
6070template class money_get<char>;
6071template class money_get<wchar_t>;
6072
6073template class __money_get<char>;
6074template class __money_get<wchar_t>;
6075
6076template class money_put<char>;
6077template class money_put<wchar_t>;
6078
6079template class __money_put<char>;
6080template class __money_put<wchar_t>;
6081
6082template class messages<char>;
6083template class messages<wchar_t>;
6084
6085template class messages_byname<char>;
6086template class messages_byname<wchar_t>;
6087
6088template class codecvt_byname<char, char, mbstate_t>;
6089template class codecvt_byname<wchar_t, char, mbstate_t>;
6090template class codecvt_byname<char16_t, char, mbstate_t>;
6091template class codecvt_byname<char32_t, char, mbstate_t>;
6092
6093template class __vector_base_common<true>;
6094
6095_LIBCPP_END_NAMESPACE_STD