blob: 373ac78c6b573615e8ea348b7223c210b817a3b6 [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
10#include "string"
11#include "locale"
Howard Hinnant87d1a8a2010-05-30 21:39:41 +000012#include "codecvt"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000013#include "vector"
14#include "algorithm"
15#include "algorithm"
16#include "typeinfo"
Howard Hinnantd318d492011-06-30 14:21:55 +000017#include "type_traits"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000018#include "clocale"
19#include "cstring"
20#include "cwctype"
21#include "__sso_allocator"
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000022#if _WIN32
23#include <locale.h>
24#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000025#include <langinfo.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000026#endif // _!WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000027#include <stdlib.h>
28
29_LIBCPP_BEGIN_NAMESPACE_STD
30
Howard Hinnant866569b2011-09-28 23:39:33 +000031#ifdef __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000032locale_t __cloc() {
33 // In theory this could create a race condition. In practice
34 // the race condition is non-fatal since it will just create
35 // a little resource leak. Better approach would be appreciated.
Sean Hunt62a6ac32011-07-09 00:56:23 +000036 static locale_t result = newlocale(LC_ALL_MASK, "C", 0);
37 return result;
Sean Hunt62a6ac32011-07-09 00:56:23 +000038}
Howard Hinnant866569b2011-09-28 23:39:33 +000039#endif // __cloc_defined
Sean Hunt62a6ac32011-07-09 00:56:23 +000040
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041namespace {
42
43struct release
44{
45 void operator()(locale::facet* p) {p->__release_shared();}
46};
47
48template <class T, class A0>
49inline
50T&
51make(A0 a0)
52{
53 static typename aligned_storage<sizeof(T)>::type buf;
54 ::new (&buf) T(a0);
55 return *(T*)&buf;
56}
57
58template <class T, class A0, class A1>
59inline
60T&
61make(A0 a0, A1 a1)
62{
63 static typename aligned_storage<sizeof(T)>::type buf;
64 ::new (&buf) T(a0, a1);
65 return *(T*)&buf;
66}
67
68template <class T, class A0, class A1, class A2>
69inline
70T&
71make(A0 a0, A1 a1, A2 a2)
72{
73 static typename aligned_storage<sizeof(T)>::type buf;
74 ::new (&buf) T(a0, a1, a2);
75 return *(T*)&buf;
76}
77
78}
79
80class _LIBCPP_HIDDEN locale::__imp
81 : public facet
82{
83 enum {N = 28};
84 string name_;
85 vector<facet*, __sso_allocator<facet*, N> > facets_;
86public:
87 explicit __imp(size_t refs = 0);
88 explicit __imp(const string& name, size_t refs = 0);
89 __imp(const __imp&);
90 __imp(const __imp&, const string&, locale::category c);
91 __imp(const __imp& other, const __imp& one, locale::category c);
92 __imp(const __imp&, facet* f, long id);
93 ~__imp();
94
95 const string& name() const {return name_;}
96 bool has_facet(long id) const {return id < facets_.size() && facets_[id];}
97 const locale::facet* use_facet(long id) const;
98
99 static const locale& make_classic();
100 static locale& make_global();
101private:
102 void install(facet* f, long id);
103 template <class F> void install(F* f) {install(f, f->id.__get());}
104 template <class F> void install_from(const __imp& other);
105};
106
107locale::__imp::__imp(size_t refs)
108 : facet(refs),
109 name_("C"),
110 facets_(N)
111{
112 facets_.clear();
Howard Hinnant0949eed2011-06-30 21:18:19 +0000113 install(&make<_VSTD::collate<char> >(1));
114 install(&make<_VSTD::collate<wchar_t> >(1));
115 install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1));
116 install(&make<_VSTD::ctype<wchar_t> >(1));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000117 install(&make<codecvt<char, char, mbstate_t> >(1));
118 install(&make<codecvt<wchar_t, char, mbstate_t> >(1));
119 install(&make<codecvt<char16_t, char, mbstate_t> >(1));
120 install(&make<codecvt<char32_t, char, mbstate_t> >(1));
121 install(&make<numpunct<char> >(1));
122 install(&make<numpunct<wchar_t> >(1));
123 install(&make<num_get<char> >(1));
124 install(&make<num_get<wchar_t> >(1));
125 install(&make<num_put<char> >(1));
126 install(&make<num_put<wchar_t> >(1));
127 install(&make<moneypunct<char, false> >(1));
128 install(&make<moneypunct<char, true> >(1));
129 install(&make<moneypunct<wchar_t, false> >(1));
130 install(&make<moneypunct<wchar_t, true> >(1));
131 install(&make<money_get<char> >(1));
132 install(&make<money_get<wchar_t> >(1));
133 install(&make<money_put<char> >(1));
134 install(&make<money_put<wchar_t> >(1));
135 install(&make<time_get<char> >(1));
136 install(&make<time_get<wchar_t> >(1));
137 install(&make<time_put<char> >(1));
138 install(&make<time_put<wchar_t> >(1));
Howard Hinnant0949eed2011-06-30 21:18:19 +0000139 install(&make<_VSTD::messages<char> >(1));
140 install(&make<_VSTD::messages<wchar_t> >(1));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000141}
142
143locale::__imp::__imp(const string& name, size_t refs)
144 : facet(refs),
145 name_(name),
146 facets_(N)
147{
Howard Hinnantd4444702010-08-11 17:04:31 +0000148#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000149 try
150 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000151#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000152 facets_ = locale::classic().__locale_->facets_;
153 for (unsigned i = 0; i < facets_.size(); ++i)
154 if (facets_[i])
155 facets_[i]->__add_shared();
156 install(new collate_byname<char>(name_));
157 install(new collate_byname<wchar_t>(name_));
158 install(new ctype_byname<char>(name_));
159 install(new ctype_byname<wchar_t>(name_));
160 install(new codecvt_byname<char, char, mbstate_t>(name_));
161 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
162 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
163 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
164 install(new numpunct_byname<char>(name_));
165 install(new numpunct_byname<wchar_t>(name_));
166 install(new moneypunct_byname<char, false>(name_));
167 install(new moneypunct_byname<char, true>(name_));
168 install(new moneypunct_byname<wchar_t, false>(name_));
169 install(new moneypunct_byname<wchar_t, true>(name_));
170 install(new time_get_byname<char>(name_));
171 install(new time_get_byname<wchar_t>(name_));
172 install(new time_put_byname<char>(name_));
173 install(new time_put_byname<wchar_t>(name_));
174 install(new messages_byname<char>(name_));
175 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000176#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000177 }
178 catch (...)
179 {
180 for (unsigned i = 0; i < facets_.size(); ++i)
181 if (facets_[i])
182 facets_[i]->__release_shared();
183 throw;
184 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000185#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000186}
187
188locale::__imp::__imp(const __imp& other)
189 : name_(other.name_),
190 facets_(max<size_t>(N, other.facets_.size()))
191{
192 facets_ = other.facets_;
193 for (unsigned i = 0; i < facets_.size(); ++i)
194 if (facets_[i])
195 facets_[i]->__add_shared();
196}
197
198locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
199 : name_("*"),
200 facets_(N)
201{
202 facets_ = other.facets_;
203 for (unsigned i = 0; i < facets_.size(); ++i)
204 if (facets_[i])
205 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000206#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000207 try
208 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000209#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000210 if (c & locale::collate)
211 {
212 install(new collate_byname<char>(name));
213 install(new collate_byname<wchar_t>(name));
214 }
215 if (c & locale::ctype)
216 {
217 install(new ctype_byname<char>(name));
218 install(new ctype_byname<wchar_t>(name));
219 install(new codecvt_byname<char, char, mbstate_t>(name));
220 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
221 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
222 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
223 }
224 if (c & locale::monetary)
225 {
226 install(new moneypunct_byname<char, false>(name));
227 install(new moneypunct_byname<char, true>(name));
228 install(new moneypunct_byname<wchar_t, false>(name));
229 install(new moneypunct_byname<wchar_t, true>(name));
230 }
231 if (c & locale::numeric)
232 {
233 install(new numpunct_byname<char>(name));
234 install(new numpunct_byname<wchar_t>(name));
235 }
236 if (c & locale::time)
237 {
238 install(new time_get_byname<char>(name));
239 install(new time_get_byname<wchar_t>(name));
240 install(new time_put_byname<char>(name));
241 install(new time_put_byname<wchar_t>(name));
242 }
243 if (c & locale::messages)
244 {
245 install(new messages_byname<char>(name));
246 install(new messages_byname<wchar_t>(name));
247 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000248#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000249 }
250 catch (...)
251 {
252 for (unsigned i = 0; i < facets_.size(); ++i)
253 if (facets_[i])
254 facets_[i]->__release_shared();
255 throw;
256 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000257#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000258}
259
260template<class F>
261inline
262void
263locale::__imp::install_from(const locale::__imp& one)
264{
265 long id = F::id.__get();
266 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
267}
268
269locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
270 : name_("*"),
271 facets_(N)
272{
273 facets_ = other.facets_;
274 for (unsigned i = 0; i < facets_.size(); ++i)
275 if (facets_[i])
276 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000277#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000278 try
279 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000280#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000281 if (c & locale::collate)
282 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000283 install_from<_VSTD::collate<char> >(one);
284 install_from<_VSTD::collate<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000285 }
286 if (c & locale::ctype)
287 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000288 install_from<_VSTD::ctype<char> >(one);
289 install_from<_VSTD::ctype<wchar_t> >(one);
290 install_from<_VSTD::codecvt<char, char, mbstate_t> >(one);
291 install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one);
292 install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one);
293 install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000294 }
295 if (c & locale::monetary)
296 {
297 install_from<moneypunct<char, false> >(one);
298 install_from<moneypunct<char, true> >(one);
299 install_from<moneypunct<wchar_t, false> >(one);
300 install_from<moneypunct<wchar_t, true> >(one);
301 install_from<money_get<char> >(one);
302 install_from<money_get<wchar_t> >(one);
303 install_from<money_put<char> >(one);
304 install_from<money_put<wchar_t> >(one);
305 }
306 if (c & locale::numeric)
307 {
308 install_from<numpunct<char> >(one);
309 install_from<numpunct<wchar_t> >(one);
310 install_from<num_get<char> >(one);
311 install_from<num_get<wchar_t> >(one);
312 install_from<num_put<char> >(one);
313 install_from<num_put<wchar_t> >(one);
314 }
315 if (c & locale::time)
316 {
317 install_from<time_get<char> >(one);
318 install_from<time_get<wchar_t> >(one);
319 install_from<time_put<char> >(one);
320 install_from<time_put<wchar_t> >(one);
321 }
322 if (c & locale::messages)
323 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000324 install_from<_VSTD::messages<char> >(one);
325 install_from<_VSTD::messages<wchar_t> >(one);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000326 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000327#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000328 }
329 catch (...)
330 {
331 for (unsigned i = 0; i < facets_.size(); ++i)
332 if (facets_[i])
333 facets_[i]->__release_shared();
334 throw;
335 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000336#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000337}
338
339locale::__imp::__imp(const __imp& other, facet* f, long id)
340 : name_("*"),
341 facets_(max<size_t>(N, other.facets_.size()+1))
342{
343 f->__add_shared();
344 unique_ptr<facet, release> hold(f);
345 facets_ = other.facets_;
346 for (unsigned i = 0; i < other.facets_.size(); ++i)
347 if (facets_[i])
348 facets_[i]->__add_shared();
349 install(hold.get(), id);
350}
351
352locale::__imp::~__imp()
353{
354 for (unsigned i = 0; i < facets_.size(); ++i)
355 if (facets_[i])
356 facets_[i]->__release_shared();
357}
358
359void
360locale::__imp::install(facet* f, long id)
361{
362 f->__add_shared();
363 unique_ptr<facet, release> hold(f);
364 if (id >= facets_.size())
365 facets_.resize(id+1);
366 if (facets_[id])
367 facets_[id]->__release_shared();
368 facets_[id] = hold.release();
369}
370
371const locale::facet*
372locale::__imp::use_facet(long id) const
373{
Howard Hinnantd4444702010-08-11 17:04:31 +0000374#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000375 if (!has_facet(id))
376 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000377#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000378 return facets_[id];
379}
380
381// locale
382
383const locale&
384locale::__imp::make_classic()
385{
386 // only one thread can get in here and it only gets in once
387 static aligned_storage<sizeof(locale)>::type buf;
388 locale* c = (locale*)&buf;
389 c->__locale_ = &make<__imp>(1);
390 return *c;
391}
392
393const locale&
394locale::classic()
395{
396 static const locale& c = __imp::make_classic();
397 return c;
398}
399
400locale&
401locale::__imp::make_global()
402{
403 // only one thread can get in here and it only gets in once
404 static aligned_storage<sizeof(locale)>::type buf;
405 locale* g = (locale*)&buf;
406 ::new (&buf) locale(locale::classic());
407 return *(locale*)&buf;
408}
409
410locale&
411locale::__global()
412{
413 static locale& g = __imp::make_global();
414 return g;
415}
416
Howard Hinnantc9834542011-05-31 15:34:58 +0000417locale::locale() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000418 : __locale_(__global().__locale_)
419{
420 __locale_->__add_shared();
421}
422
Howard Hinnantc9834542011-05-31 15:34:58 +0000423locale::locale(const locale& l) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000424 : __locale_(l.__locale_)
425{
426 __locale_->__add_shared();
427}
428
Howard Hinnantc9834542011-05-31 15:34:58 +0000429locale::~locale()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000430{
431 __locale_->__release_shared();
432}
433
434const locale&
Howard Hinnantc9834542011-05-31 15:34:58 +0000435locale::operator=(const locale& other) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000436{
437 other.__locale_->__add_shared();
438 __locale_->__release_shared();
439 __locale_ = other.__locale_;
440 return *this;
441}
442
443locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000444#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000445 : __locale_(name ? new __imp(name)
446 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000447#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000448 : __locale_(new __imp(name))
449#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000450{
451 __locale_->__add_shared();
452}
453
454locale::locale(const string& name)
455 : __locale_(new __imp(name))
456{
457 __locale_->__add_shared();
458}
459
460locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000461#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000462 : __locale_(name ? new __imp(*other.__locale_, name, c)
463 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000464#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000465 : __locale_(new __imp(*other.__locale_, name, c))
466#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000467{
468 __locale_->__add_shared();
469}
470
471locale::locale(const locale& other, const string& name, category c)
472 : __locale_(new __imp(*other.__locale_, name, c))
473{
474 __locale_->__add_shared();
475}
476
477locale::locale(const locale& other, const locale& one, category c)
478 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
479{
480 __locale_->__add_shared();
481}
482
483string
484locale::name() const
485{
486 return __locale_->name();
487}
488
489void
490locale::__install_ctor(const locale& other, facet* f, long id)
491{
492 if (f)
493 __locale_ = new __imp(*other.__locale_, f, id);
494 else
495 __locale_ = other.__locale_;
496 __locale_->__add_shared();
497}
498
499locale
500locale::global(const locale& loc)
501{
502 locale& g = __global();
503 locale r = g;
504 g = loc;
505 if (g.name() != "*")
506 setlocale(LC_ALL, g.name().c_str());
507 return r;
508}
509
510bool
511locale::has_facet(id& x) const
512{
513 return __locale_->has_facet(x.__get());
514}
515
516const locale::facet*
517locale::use_facet(id& x) const
518{
519 return __locale_->use_facet(x.__get());
520}
521
522bool
523locale::operator==(const locale& y) const
524{
525 return (__locale_ == y.__locale_)
526 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
527}
528
529// locale::facet
530
531locale::facet::~facet()
532{
533}
534
535void
Howard Hinnant1694d232011-05-28 14:41:13 +0000536locale::facet::__on_zero_shared() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000537{
538 delete this;
539}
540
541// locale::id
542
543int32_t locale::id::__next_id = 0;
544
545namespace
546{
547
548class __fake_bind
549{
550 locale::id* id_;
551 void (locale::id::* pmf_)();
552public:
553 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
554 : id_(id), pmf_(pmf) {}
555
556 void operator()() const
557 {
558 (id_->*pmf_)();
559 }
560};
561
562}
563
564long
565locale::id::__get()
566{
567 call_once(__flag_, __fake_bind(&locale::id::__init, this));
568 return __id_ - 1;
569}
570
571void
572locale::id::__init()
573{
Howard Hinnantadff4892010-05-24 17:49:41 +0000574 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000575}
576
577// template <> class collate_byname<char>
578
579collate_byname<char>::collate_byname(const char* n, size_t refs)
580 : collate<char>(refs),
581 __l(newlocale(LC_ALL_MASK, n, 0))
582{
Howard Hinnantd4444702010-08-11 17:04:31 +0000583#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000584 if (__l == 0)
585 throw runtime_error("collate_byname<char>::collate_byname"
586 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000587#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000588}
589
590collate_byname<char>::collate_byname(const string& name, size_t refs)
591 : collate<char>(refs),
592 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
593{
Howard Hinnantd4444702010-08-11 17:04:31 +0000594#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000595 if (__l == 0)
596 throw runtime_error("collate_byname<char>::collate_byname"
597 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000598#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000599}
600
601collate_byname<char>::~collate_byname()
602{
603 freelocale(__l);
604}
605
606int
607collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
608 const char_type* __lo2, const char_type* __hi2) const
609{
610 string_type lhs(__lo1, __hi1);
611 string_type rhs(__lo2, __hi2);
612 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
613 if (r < 0)
614 return -1;
615 if (r > 0)
616 return 1;
617 return r;
618}
619
620collate_byname<char>::string_type
621collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
622{
623 const string_type in(lo, hi);
624 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
625 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
626 return out;
627}
628
629// template <> class collate_byname<wchar_t>
630
631collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
632 : collate<wchar_t>(refs),
633 __l(newlocale(LC_ALL_MASK, n, 0))
634{
Howard Hinnantd4444702010-08-11 17:04:31 +0000635#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000636 if (__l == 0)
637 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
638 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000639#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000640}
641
642collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
643 : collate<wchar_t>(refs),
644 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
645{
Howard Hinnantd4444702010-08-11 17:04:31 +0000646#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000647 if (__l == 0)
648 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
649 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000650#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000651}
652
653collate_byname<wchar_t>::~collate_byname()
654{
655 freelocale(__l);
656}
657
658int
659collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
660 const char_type* __lo2, const char_type* __hi2) const
661{
662 string_type lhs(__lo1, __hi1);
663 string_type rhs(__lo2, __hi2);
664 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
665 if (r < 0)
666 return -1;
667 if (r > 0)
668 return 1;
669 return r;
670}
671
672collate_byname<wchar_t>::string_type
673collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
674{
675 const string_type in(lo, hi);
676 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
677 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
678 return out;
679}
680
681// template <> class ctype<wchar_t>;
682
683locale::id ctype<wchar_t>::id;
684
685ctype<wchar_t>::~ctype()
686{
687}
688
689bool
690ctype<wchar_t>::do_is(mask m, char_type c) const
691{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000692 return isascii(c) ? ctype<char>::classic_table()[c] & m : false;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000693}
694
695const wchar_t*
696ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
697{
698 for (; low != high; ++low, ++vec)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000699 *vec = static_cast<mask>(isascii(*low) ?
700 ctype<char>::classic_table()[*low] : 0);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000701 return low;
702}
703
704const wchar_t*
705ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
706{
707 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000708 if (isascii(*low) && (ctype<char>::classic_table()[*low] & m))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000709 break;
710 return low;
711}
712
713const wchar_t*
714ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
715{
716 for (; low != high; ++low)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000717 if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m)))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000718 break;
719 return low;
720}
721
722wchar_t
723ctype<wchar_t>::do_toupper(char_type c) const
724{
Howard Hinnant866569b2011-09-28 23:39:33 +0000725#ifndef _LIBCPP_HAS_DEFAULTRUNELOCALE
Sean Hunt62a6ac32011-07-09 00:56:23 +0000726 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000727#else
728 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
729#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000730}
731
732const wchar_t*
733ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
734{
735 for (; low != high; ++low)
Howard Hinnant866569b2011-09-28 23:39:33 +0000736#ifndef _LIBCPP_HAS_DEFAULTRUNELOCALE
Sean Hunt62a6ac32011-07-09 00:56:23 +0000737 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
738 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000739#else
740 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
741#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000742 return low;
743}
744
745wchar_t
746ctype<wchar_t>::do_tolower(char_type c) const
747{
Howard Hinnant866569b2011-09-28 23:39:33 +0000748#ifndef _LIBCPP_HAS_DEFAULTRUNELOCALE
Sean Hunt62a6ac32011-07-09 00:56:23 +0000749 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000750#else
751 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
752#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000753}
754
755const wchar_t*
756ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
757{
758 for (; low != high; ++low)
Howard Hinnant866569b2011-09-28 23:39:33 +0000759#ifndef _LIBCPP_HAS_DEFAULTRUNELOCALE
Sean Hunt62a6ac32011-07-09 00:56:23 +0000760 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
761 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000762#else
763 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
764#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000765 return low;
766}
767
768wchar_t
769ctype<wchar_t>::do_widen(char c) const
770{
771 return c;
772}
773
774const char*
775ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
776{
777 for (; low != high; ++low, ++dest)
778 *dest = *low;
779 return low;
780}
781
782char
783ctype<wchar_t>::do_narrow(char_type c, char dfault) const
784{
785 if (isascii(c))
786 return static_cast<char>(c);
787 return dfault;
788}
789
790const wchar_t*
791ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
792{
793 for (; low != high; ++low, ++dest)
794 if (isascii(*low))
795 *dest = *low;
796 else
797 *dest = dfault;
798 return low;
799}
800
801// template <> class ctype<char>;
802
803locale::id ctype<char>::id;
804
805ctype<char>::ctype(const mask* tab, bool del, size_t refs)
806 : locale::facet(refs),
807 __tab_(tab),
808 __del_(del)
809{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000810 if (__tab_ == 0)
811 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000812}
813
814ctype<char>::~ctype()
815{
816 if (__tab_ && __del_)
817 delete [] __tab_;
818}
819
820char
821ctype<char>::do_toupper(char_type c) const
822{
Howard Hinnant866569b2011-09-28 23:39:33 +0000823#ifndef _LIBCPP_HAS_DEFAULTRUNELOCALE
Sean Hunt62a6ac32011-07-09 00:56:23 +0000824 return isascii(c) ? __classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000825#else
826 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
827#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000828}
829
830const char*
831ctype<char>::do_toupper(char_type* low, const char_type* high) const
832{
833 for (; low != high; ++low)
Howard Hinnant866569b2011-09-28 23:39:33 +0000834#ifndef _LIBCPP_HAS_DEFAULTRUNELOCALE
Sean Hunt62a6ac32011-07-09 00:56:23 +0000835 *low = isascii(*low) ? __classic_upper_table()[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000836#else
Howard Hinnant66f26412011-07-09 19:47:01 +0000837 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000838#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000839 return low;
840}
841
842char
843ctype<char>::do_tolower(char_type c) const
844{
Howard Hinnant866569b2011-09-28 23:39:33 +0000845#ifndef _LIBCPP_HAS_DEFAULTRUNELOCALE
Sean Hunt62a6ac32011-07-09 00:56:23 +0000846 return isascii(c) ? __classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000847#else
848 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
849#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000850}
851
852const char*
853ctype<char>::do_tolower(char_type* low, const char_type* high) const
854{
855 for (; low != high; ++low)
Howard Hinnant866569b2011-09-28 23:39:33 +0000856#ifndef _LIBCPP_HAS_DEFAULTRUNELOCALE
Sean Hunt62a6ac32011-07-09 00:56:23 +0000857 *low = isascii(*low) ? __classic_lower_table()[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000858#else
Howard Hinnant66f26412011-07-09 19:47:01 +0000859 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000860#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000861 return low;
862}
863
864char
865ctype<char>::do_widen(char c) const
866{
867 return c;
868}
869
870const char*
871ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
872{
873 for (; low != high; ++low, ++dest)
874 *dest = *low;
875 return low;
876}
877
878char
879ctype<char>::do_narrow(char_type c, char dfault) const
880{
881 if (isascii(c))
882 return static_cast<char>(c);
883 return dfault;
884}
885
886const char*
887ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
888{
889 for (; low != high; ++low, ++dest)
890 if (isascii(*low))
891 *dest = *low;
892 else
893 *dest = dfault;
894 return low;
895}
896
897const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000898ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000899{
David Chisnallc512df12011-09-21 08:39:44 +0000900#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000901 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000902#elif defined(__GLIBC__)
903 return __cloc()->__ctype_b;
David Chisnallc512df12011-09-21 08:39:44 +0000904// This is assumed to be safe, which is a nonsense assumption because we're
905// going to end up dereferencing it later...
Sean Hunt62a6ac32011-07-09 00:56:23 +0000906#else
907 return NULL;
908#endif
909}
910
Howard Hinnant866569b2011-09-28 23:39:33 +0000911#ifndef _LIBCPP_HAS_DEFAULTRUNELOCALE
Sean Hunt62a6ac32011-07-09 00:56:23 +0000912const int*
913ctype<char>::__classic_lower_table() _NOEXCEPT
914{
David Chisnallc512df12011-09-21 08:39:44 +0000915#if defined(__APPLE__) || defined(__FreeBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000916 return _DefaultRuneLocale.__maplower;
917#elif defined(__GLIBC__)
918 return __cloc()->__ctype_tolower;
919#else
920 return NULL;
921#endif
922}
923
924const int*
925ctype<char>::__classic_upper_table() _NOEXCEPT
926{
David Chisnallc512df12011-09-21 08:39:44 +0000927#if defined(__APPLE__) || defined(__FreeBSD__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000928 return _DefaultRuneLocale.__mapupper;
929#elif defined(__GLIBC__)
930 return __cloc()->__ctype_toupper;
Michael J. Spencer626916f2010-12-10 19:47:54 +0000931#else
932 return NULL;
933#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000934}
Howard Hinnant866569b2011-09-28 23:39:33 +0000935#endif // _LIBCPP_HAS_DEFAULTRUNELOCALE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000936
937// template <> class ctype_byname<char>
938
939ctype_byname<char>::ctype_byname(const char* name, size_t refs)
940 : ctype<char>(0, false, refs),
941 __l(newlocale(LC_ALL_MASK, name, 0))
942{
Howard Hinnantd4444702010-08-11 17:04:31 +0000943#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000944 if (__l == 0)
945 throw runtime_error("ctype_byname<char>::ctype_byname"
946 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000947#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000948}
949
950ctype_byname<char>::ctype_byname(const string& name, size_t refs)
951 : ctype<char>(0, false, refs),
952 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
953{
Howard Hinnantd4444702010-08-11 17:04:31 +0000954#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000955 if (__l == 0)
956 throw runtime_error("ctype_byname<char>::ctype_byname"
957 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000958#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000959}
960
961ctype_byname<char>::~ctype_byname()
962{
963 freelocale(__l);
964}
965
966char
967ctype_byname<char>::do_toupper(char_type c) const
968{
969 return toupper_l(c, __l);
970}
971
972const char*
973ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
974{
975 for (; low != high; ++low)
976 *low = toupper_l(*low, __l);
977 return low;
978}
979
980char
981ctype_byname<char>::do_tolower(char_type c) const
982{
983 return tolower_l(c, __l);
984}
985
986const char*
987ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
988{
989 for (; low != high; ++low)
990 *low = tolower_l(*low, __l);
991 return low;
992}
993
994// template <> class ctype_byname<wchar_t>
995
996ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
997 : ctype<wchar_t>(refs),
998 __l(newlocale(LC_ALL_MASK, name, 0))
999{
Howard Hinnantd4444702010-08-11 17:04:31 +00001000#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001001 if (__l == 0)
1002 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1003 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001004#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001005}
1006
1007ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1008 : ctype<wchar_t>(refs),
1009 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1010{
Howard Hinnantd4444702010-08-11 17:04:31 +00001011#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001012 if (__l == 0)
1013 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1014 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001015#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001016}
1017
1018ctype_byname<wchar_t>::~ctype_byname()
1019{
1020 freelocale(__l);
1021}
1022
1023bool
1024ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1025{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001026#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001027 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001028#else
David Chisnallc512df12011-09-21 08:39:44 +00001029 // FIXME: This is broken for things that test more than one flag.
Sean Hunt6f0342c2011-07-09 03:40:04 +00001030 if (m & space && !iswspace_l(c, __l)) return false;
1031 if (m & print && !iswprint_l(c, __l)) return false;
1032 if (m & cntrl && !iswcntrl_l(c, __l)) return false;
1033 if (m & upper && !iswupper_l(c, __l)) return false;
1034 if (m & lower && !iswlower_l(c, __l)) return false;
1035 if (m & alpha && !iswalpha_l(c, __l)) return false;
1036 if (m & digit && !iswdigit_l(c, __l)) return false;
1037 if (m & punct && !iswpunct_l(c, __l)) return false;
1038 if (m & xdigit && !iswxdigit_l(c, __l)) return false;
1039 if (m & blank && !iswblank_l(c, __l)) return false;
1040 return true;
1041#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001042}
1043
1044const wchar_t*
1045ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1046{
1047 for (; low != high; ++low, ++vec)
1048 {
1049 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001050 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001051 else
1052 {
1053 *vec = 0;
1054 if (iswspace_l(*low, __l))
1055 *vec |= space;
1056 if (iswprint_l(*low, __l))
1057 *vec |= print;
1058 if (iswcntrl_l(*low, __l))
1059 *vec |= cntrl;
1060 if (iswupper_l(*low, __l))
1061 *vec |= upper;
1062 if (iswlower_l(*low, __l))
1063 *vec |= lower;
1064 if (iswalpha_l(*low, __l))
1065 *vec |= alpha;
1066 if (iswdigit_l(*low, __l))
1067 *vec |= digit;
1068 if (iswpunct_l(*low, __l))
1069 *vec |= punct;
1070 if (iswxdigit_l(*low, __l))
1071 *vec |= xdigit;
1072 }
1073 }
1074 return low;
1075}
1076
1077const wchar_t*
1078ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1079{
1080 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001081 {
1082#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001083 if (iswctype_l(*low, m, __l))
1084 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001085#else
1086 if (m & space && !iswspace_l(*low, __l)) continue;
1087 if (m & print && !iswprint_l(*low, __l)) continue;
1088 if (m & cntrl && !iswcntrl_l(*low, __l)) continue;
1089 if (m & upper && !iswupper_l(*low, __l)) continue;
1090 if (m & lower && !iswlower_l(*low, __l)) continue;
1091 if (m & alpha && !iswalpha_l(*low, __l)) continue;
1092 if (m & digit && !iswdigit_l(*low, __l)) continue;
1093 if (m & punct && !iswpunct_l(*low, __l)) continue;
1094 if (m & xdigit && !iswxdigit_l(*low, __l)) continue;
1095 if (m & blank && !iswblank_l(*low, __l)) continue;
1096 break;
1097#endif
1098 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001099 return low;
1100}
1101
1102const wchar_t*
1103ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1104{
1105 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001106 {
1107#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001108 if (!iswctype_l(*low, m, __l))
1109 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001110#else
1111 if (m & space && iswspace_l(*low, __l)) continue;
1112 if (m & print && iswprint_l(*low, __l)) continue;
1113 if (m & cntrl && iswcntrl_l(*low, __l)) continue;
1114 if (m & upper && iswupper_l(*low, __l)) continue;
1115 if (m & lower && iswlower_l(*low, __l)) continue;
1116 if (m & alpha && iswalpha_l(*low, __l)) continue;
1117 if (m & digit && iswdigit_l(*low, __l)) continue;
1118 if (m & punct && iswpunct_l(*low, __l)) continue;
1119 if (m & xdigit && iswxdigit_l(*low, __l)) continue;
1120 if (m & blank && iswblank_l(*low, __l)) continue;
1121 break;
1122#endif
1123 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001124 return low;
1125}
1126
1127wchar_t
1128ctype_byname<wchar_t>::do_toupper(char_type c) const
1129{
1130 return towupper_l(c, __l);
1131}
1132
1133const wchar_t*
1134ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1135{
1136 for (; low != high; ++low)
1137 *low = towupper_l(*low, __l);
1138 return low;
1139}
1140
1141wchar_t
1142ctype_byname<wchar_t>::do_tolower(char_type c) const
1143{
1144 return towlower_l(c, __l);
1145}
1146
1147const wchar_t*
1148ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1149{
1150 for (; low != high; ++low)
1151 *low = towlower_l(*low, __l);
1152 return low;
1153}
1154
1155wchar_t
1156ctype_byname<wchar_t>::do_widen(char c) const
1157{
Howard Hinnant866569b2011-09-28 23:39:33 +00001158#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001159 return btowc_l(c, __l);
1160#else
1161 return __btowc_l(c, __l);
1162#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001163}
1164
1165const char*
1166ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1167{
1168 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001169#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001170 *dest = btowc_l(*low, __l);
1171#else
1172 *dest = __btowc_l(*low, __l);
1173#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001174 return low;
1175}
1176
1177char
1178ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1179{
Howard Hinnant866569b2011-09-28 23:39:33 +00001180#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001181 int r = wctob_l(c, __l);
1182#else
1183 int r = __wctob_l(c, __l);
1184#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001185 return r != WEOF ? static_cast<char>(r) : dfault;
1186}
1187
1188const wchar_t*
1189ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1190{
1191 for (; low != high; ++low, ++dest)
1192 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001193#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001194 int r = wctob_l(*low, __l);
1195#else
1196 int r = __wctob_l(*low, __l);
1197#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001198 *dest = r != WEOF ? static_cast<char>(r) : dfault;
1199 }
1200 return low;
1201}
1202
1203// template <> class codecvt<char, char, mbstate_t>
1204
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001205locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001206
1207codecvt<char, char, mbstate_t>::~codecvt()
1208{
1209}
1210
1211codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001212codecvt<char, char, mbstate_t>::do_out(state_type&,
1213 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001214 extern_type* to, extern_type*, extern_type*& to_nxt) const
1215{
1216 frm_nxt = frm;
1217 to_nxt = to;
1218 return noconv;
1219}
1220
1221codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001222codecvt<char, char, mbstate_t>::do_in(state_type&,
1223 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001224 intern_type* to, intern_type*, intern_type*& to_nxt) const
1225{
1226 frm_nxt = frm;
1227 to_nxt = to;
1228 return noconv;
1229}
1230
1231codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001232codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001233 extern_type* to, extern_type*, extern_type*& to_nxt) const
1234{
1235 to_nxt = to;
1236 return noconv;
1237}
1238
1239int
Howard Hinnantc9834542011-05-31 15:34:58 +00001240codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001241{
1242 return 1;
1243}
1244
1245bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001246codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001247{
1248 return true;
1249}
1250
1251int
1252codecvt<char, char, mbstate_t>::do_length(state_type&,
1253 const extern_type* frm, const extern_type* end, size_t mx) const
1254{
1255 return static_cast<int>(min<size_t>(mx, end-frm));
1256}
1257
1258int
Howard Hinnantc9834542011-05-31 15:34:58 +00001259codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001260{
1261 return 1;
1262}
1263
1264// template <> class codecvt<wchar_t, char, mbstate_t>
1265
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001266locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001267
1268codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1269 : locale::facet(refs),
1270 __l(0)
1271{
1272}
1273
1274codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1275 : locale::facet(refs),
1276 __l(newlocale(LC_ALL_MASK, nm, 0))
1277{
Howard Hinnantd4444702010-08-11 17:04:31 +00001278#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001279 if (__l == 0)
1280 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1281 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001282#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001283}
1284
1285codecvt<wchar_t, char, mbstate_t>::~codecvt()
1286{
1287 if (__l != 0)
1288 freelocale(__l);
1289}
1290
1291codecvt<wchar_t, char, mbstate_t>::result
1292codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001293 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001294 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1295{
1296 // look for first internal null in frm
1297 const intern_type* fend = frm;
1298 for (; fend != frm_end; ++fend)
1299 if (*fend == 0)
1300 break;
1301 // loop over all null-terminated sequences in frm
1302 to_nxt = to;
1303 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1304 {
1305 // save state in case needed to reover to_nxt on error
1306 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001307#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001308 size_t n = wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1309#else
1310 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1311#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001312 if (n == size_t(-1))
1313 {
1314 // need to recover to_nxt
1315 for (to_nxt = to; frm != frm_nxt; ++frm)
1316 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001317#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001318 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1319#else
1320 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1321#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001322 if (n == size_t(-1))
1323 break;
1324 to_nxt += n;
1325 }
1326 frm_nxt = frm;
1327 return error;
1328 }
1329 if (n == 0)
1330 return partial;
1331 to_nxt += n;
1332 if (to_nxt == to_end)
1333 break;
1334 if (fend != frm_end) // set up next null terminated sequence
1335 {
1336 // Try to write the terminating null
1337 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001338#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001339 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1340#else
1341 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1342#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001343 if (n == size_t(-1)) // on error
1344 return error;
1345 if (n > to_end-to_nxt) // is there room?
1346 return partial;
1347 for (extern_type* p = tmp; n; --n) // write it
1348 *to_nxt++ = *p++;
1349 ++frm_nxt;
1350 // look for next null in frm
1351 for (fend = frm_nxt; fend != frm_end; ++fend)
1352 if (*fend == 0)
1353 break;
1354 }
1355 }
1356 return frm_nxt == frm_end ? ok : partial;
1357}
1358
1359codecvt<wchar_t, char, mbstate_t>::result
1360codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001361 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001362 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1363{
1364 // look for first internal null in frm
1365 const extern_type* fend = frm;
1366 for (; fend != frm_end; ++fend)
1367 if (*fend == 0)
1368 break;
1369 // loop over all null-terminated sequences in frm
1370 to_nxt = to;
1371 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1372 {
1373 // save state in case needed to reover to_nxt on error
1374 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001375#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001376 size_t n = mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1377#else
1378 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1379#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001380 if (n == size_t(-1))
1381 {
1382 // need to recover to_nxt
1383 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1384 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001385#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001386 n = mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1387#else
1388 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1389#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001390 switch (n)
1391 {
1392 case 0:
1393 ++frm;
1394 break;
1395 case -1:
1396 frm_nxt = frm;
1397 return error;
1398 case -2:
1399 frm_nxt = frm;
1400 return partial;
1401 default:
1402 frm += n;
1403 break;
1404 }
1405 }
1406 frm_nxt = frm;
1407 return frm_nxt == frm_end ? ok : partial;
1408 }
1409 if (n == 0)
1410 return error;
1411 to_nxt += n;
1412 if (to_nxt == to_end)
1413 break;
1414 if (fend != frm_end) // set up next null terminated sequence
1415 {
1416 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001417#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001418 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1419#else
1420 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1421#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001422 if (n != 0) // on error
1423 return error;
1424 ++to_nxt;
1425 ++frm_nxt;
1426 // look for next null in frm
1427 for (fend = frm_nxt; fend != frm_end; ++fend)
1428 if (*fend == 0)
1429 break;
1430 }
1431 }
1432 return frm_nxt == frm_end ? ok : partial;
1433}
1434
1435codecvt<wchar_t, char, mbstate_t>::result
1436codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1437 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1438{
1439 to_nxt = to;
1440 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001441#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001442 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1443#else
1444 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1445#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001446 if (n == size_t(-1) || n == 0) // on error
1447 return error;
1448 --n;
1449 if (n > to_end-to_nxt) // is there room?
1450 return partial;
1451 for (extern_type* p = tmp; n; --n) // write it
1452 *to_nxt++ = *p++;
1453 return ok;
1454}
1455
1456int
Howard Hinnantc9834542011-05-31 15:34:58 +00001457codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458{
Howard Hinnant866569b2011-09-28 23:39:33 +00001459#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001460 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1461#else
1462 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1463#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001464 {
1465 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001466#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001467 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1468#else
1469 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1470#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001471 return 1; // which take more than 1 char to form a wchar_t
1472 return 0;
1473 }
1474 return -1;
1475}
1476
1477bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001478codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001479{
1480 return false;
1481}
1482
1483int
1484codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1485 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1486{
1487 int nbytes = 0;
1488 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1489 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001490#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001491 size_t n = mbrlen_l(frm, frm_end-frm, &st, __l);
1492#else
1493 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1494#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001495 switch (n)
1496 {
1497 case 0:
1498 ++nbytes;
1499 ++frm;
1500 break;
1501 case -1:
1502 case -2:
1503 return nbytes;
1504 default:
1505 nbytes += n;
1506 frm += n;
1507 break;
1508 }
1509 }
1510 return nbytes;
1511}
1512
1513int
Howard Hinnantc9834542011-05-31 15:34:58 +00001514codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001515{
Howard Hinnant866569b2011-09-28 23:39:33 +00001516#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001517 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1518#else
1519 return __l == 0 ? 1 : __mb_cur_max_l(__l);
1520#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001521}
1522
1523// Valid UTF ranges
1524// UTF-32 UTF-16 UTF-8 # of code points
1525// first second first second third fourth
1526// 000000 - 00007F 0000 - 007F 00 - 7F 127
1527// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1528// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1529// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1530// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1531// 00D800 - 00DFFF invalid
1532// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1533// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1534// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1535// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1536
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001537static
1538codecvt_base::result
1539utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1540 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1541 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1542{
1543 frm_nxt = frm;
1544 to_nxt = to;
1545 if (mode & generate_header)
1546 {
1547 if (to_end-to_nxt < 3)
1548 return codecvt_base::partial;
1549 *to_nxt++ = static_cast<uint8_t>(0xEF);
1550 *to_nxt++ = static_cast<uint8_t>(0xBB);
1551 *to_nxt++ = static_cast<uint8_t>(0xBF);
1552 }
1553 for (; frm_nxt < frm_end; ++frm_nxt)
1554 {
1555 uint16_t wc1 = *frm_nxt;
1556 if (wc1 > Maxcode)
1557 return codecvt_base::error;
1558 if (wc1 < 0x0080)
1559 {
1560 if (to_end-to_nxt < 1)
1561 return codecvt_base::partial;
1562 *to_nxt++ = static_cast<uint8_t>(wc1);
1563 }
1564 else if (wc1 < 0x0800)
1565 {
1566 if (to_end-to_nxt < 2)
1567 return codecvt_base::partial;
1568 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1569 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1570 }
1571 else if (wc1 < 0xD800)
1572 {
1573 if (to_end-to_nxt < 3)
1574 return codecvt_base::partial;
1575 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1576 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1577 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1578 }
1579 else if (wc1 < 0xDC00)
1580 {
1581 if (frm_end-frm_nxt < 2)
1582 return codecvt_base::partial;
1583 uint16_t wc2 = frm_nxt[1];
1584 if ((wc2 & 0xFC00) != 0xDC00)
1585 return codecvt_base::error;
1586 if (to_end-to_nxt < 4)
1587 return codecvt_base::partial;
1588 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1589 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1590 return codecvt_base::error;
1591 ++frm_nxt;
1592 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1593 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1594 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1595 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1596 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1597 }
1598 else if (wc1 < 0xE000)
1599 {
1600 return codecvt_base::error;
1601 }
1602 else
1603 {
1604 if (to_end-to_nxt < 3)
1605 return codecvt_base::partial;
1606 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1607 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1608 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1609 }
1610 }
1611 return codecvt_base::ok;
1612}
1613
1614static
1615codecvt_base::result
1616utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1617 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1618 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1619{
1620 frm_nxt = frm;
1621 to_nxt = to;
1622 if (mode & generate_header)
1623 {
1624 if (to_end-to_nxt < 3)
1625 return codecvt_base::partial;
1626 *to_nxt++ = static_cast<uint8_t>(0xEF);
1627 *to_nxt++ = static_cast<uint8_t>(0xBB);
1628 *to_nxt++ = static_cast<uint8_t>(0xBF);
1629 }
1630 for (; frm_nxt < frm_end; ++frm_nxt)
1631 {
1632 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1633 if (wc1 > Maxcode)
1634 return codecvt_base::error;
1635 if (wc1 < 0x0080)
1636 {
1637 if (to_end-to_nxt < 1)
1638 return codecvt_base::partial;
1639 *to_nxt++ = static_cast<uint8_t>(wc1);
1640 }
1641 else if (wc1 < 0x0800)
1642 {
1643 if (to_end-to_nxt < 2)
1644 return codecvt_base::partial;
1645 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1646 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1647 }
1648 else if (wc1 < 0xD800)
1649 {
1650 if (to_end-to_nxt < 3)
1651 return codecvt_base::partial;
1652 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1653 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1654 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1655 }
1656 else if (wc1 < 0xDC00)
1657 {
1658 if (frm_end-frm_nxt < 2)
1659 return codecvt_base::partial;
1660 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1661 if ((wc2 & 0xFC00) != 0xDC00)
1662 return codecvt_base::error;
1663 if (to_end-to_nxt < 4)
1664 return codecvt_base::partial;
1665 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1666 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1667 return codecvt_base::error;
1668 ++frm_nxt;
1669 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1670 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1671 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1672 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1673 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1674 }
1675 else if (wc1 < 0xE000)
1676 {
1677 return codecvt_base::error;
1678 }
1679 else
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 }
1688 return codecvt_base::ok;
1689}
1690
1691static
1692codecvt_base::result
1693utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1694 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1695 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1696{
1697 frm_nxt = frm;
1698 to_nxt = to;
1699 if (mode & consume_header)
1700 {
1701 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1702 frm_nxt[2] == 0xBF)
1703 frm_nxt += 3;
1704 }
1705 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1706 {
1707 uint8_t c1 = *frm_nxt;
1708 if (c1 > Maxcode)
1709 return codecvt_base::error;
1710 if (c1 < 0x80)
1711 {
1712 *to_nxt = static_cast<uint16_t>(c1);
1713 ++frm_nxt;
1714 }
1715 else if (c1 < 0xC2)
1716 {
1717 return codecvt_base::error;
1718 }
1719 else if (c1 < 0xE0)
1720 {
1721 if (frm_end-frm_nxt < 2)
1722 return codecvt_base::partial;
1723 uint8_t c2 = frm_nxt[1];
1724 if ((c2 & 0xC0) != 0x80)
1725 return codecvt_base::error;
1726 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1727 if (t > Maxcode)
1728 return codecvt_base::error;
1729 *to_nxt = t;
1730 frm_nxt += 2;
1731 }
1732 else if (c1 < 0xF0)
1733 {
1734 if (frm_end-frm_nxt < 3)
1735 return codecvt_base::partial;
1736 uint8_t c2 = frm_nxt[1];
1737 uint8_t c3 = frm_nxt[2];
1738 switch (c1)
1739 {
1740 case 0xE0:
1741 if ((c2 & 0xE0) != 0xA0)
1742 return codecvt_base::error;
1743 break;
1744 case 0xED:
1745 if ((c2 & 0xE0) != 0x80)
1746 return codecvt_base::error;
1747 break;
1748 default:
1749 if ((c2 & 0xC0) != 0x80)
1750 return codecvt_base::error;
1751 break;
1752 }
1753 if ((c3 & 0xC0) != 0x80)
1754 return codecvt_base::error;
1755 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1756 | ((c2 & 0x3F) << 6)
1757 | (c3 & 0x3F));
1758 if (t > Maxcode)
1759 return codecvt_base::error;
1760 *to_nxt = t;
1761 frm_nxt += 3;
1762 }
1763 else if (c1 < 0xF5)
1764 {
1765 if (frm_end-frm_nxt < 4)
1766 return codecvt_base::partial;
1767 uint8_t c2 = frm_nxt[1];
1768 uint8_t c3 = frm_nxt[2];
1769 uint8_t c4 = frm_nxt[3];
1770 switch (c1)
1771 {
1772 case 0xF0:
1773 if (!(0x90 <= c2 && c2 <= 0xBF))
1774 return codecvt_base::error;
1775 break;
1776 case 0xF4:
1777 if ((c2 & 0xF0) != 0x80)
1778 return codecvt_base::error;
1779 break;
1780 default:
1781 if ((c2 & 0xC0) != 0x80)
1782 return codecvt_base::error;
1783 break;
1784 }
1785 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1786 return codecvt_base::error;
1787 if (to_end-to_nxt < 2)
1788 return codecvt_base::partial;
1789 if (((((unsigned long)c1 & 7) << 18) +
1790 (((unsigned long)c2 & 0x3F) << 12) +
1791 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1792 return codecvt_base::error;
1793 *to_nxt = static_cast<uint16_t>(
1794 0xD800
1795 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1796 | ((c2 & 0x0F) << 2)
1797 | ((c3 & 0x30) >> 4));
1798 *++to_nxt = static_cast<uint16_t>(
1799 0xDC00
1800 | ((c3 & 0x0F) << 6)
1801 | (c4 & 0x3F));
1802 frm_nxt += 4;
1803 }
1804 else
1805 {
1806 return codecvt_base::error;
1807 }
1808 }
1809 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1810}
1811
1812static
1813codecvt_base::result
1814utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1815 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1816 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1817{
1818 frm_nxt = frm;
1819 to_nxt = to;
1820 if (mode & consume_header)
1821 {
1822 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1823 frm_nxt[2] == 0xBF)
1824 frm_nxt += 3;
1825 }
1826 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1827 {
1828 uint8_t c1 = *frm_nxt;
1829 if (c1 > Maxcode)
1830 return codecvt_base::error;
1831 if (c1 < 0x80)
1832 {
1833 *to_nxt = static_cast<uint32_t>(c1);
1834 ++frm_nxt;
1835 }
1836 else if (c1 < 0xC2)
1837 {
1838 return codecvt_base::error;
1839 }
1840 else if (c1 < 0xE0)
1841 {
1842 if (frm_end-frm_nxt < 2)
1843 return codecvt_base::partial;
1844 uint8_t c2 = frm_nxt[1];
1845 if ((c2 & 0xC0) != 0x80)
1846 return codecvt_base::error;
1847 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1848 if (t > Maxcode)
1849 return codecvt_base::error;
1850 *to_nxt = static_cast<uint32_t>(t);
1851 frm_nxt += 2;
1852 }
1853 else if (c1 < 0xF0)
1854 {
1855 if (frm_end-frm_nxt < 3)
1856 return codecvt_base::partial;
1857 uint8_t c2 = frm_nxt[1];
1858 uint8_t c3 = frm_nxt[2];
1859 switch (c1)
1860 {
1861 case 0xE0:
1862 if ((c2 & 0xE0) != 0xA0)
1863 return codecvt_base::error;
1864 break;
1865 case 0xED:
1866 if ((c2 & 0xE0) != 0x80)
1867 return codecvt_base::error;
1868 break;
1869 default:
1870 if ((c2 & 0xC0) != 0x80)
1871 return codecvt_base::error;
1872 break;
1873 }
1874 if ((c3 & 0xC0) != 0x80)
1875 return codecvt_base::error;
1876 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1877 | ((c2 & 0x3F) << 6)
1878 | (c3 & 0x3F));
1879 if (t > Maxcode)
1880 return codecvt_base::error;
1881 *to_nxt = static_cast<uint32_t>(t);
1882 frm_nxt += 3;
1883 }
1884 else if (c1 < 0xF5)
1885 {
1886 if (frm_end-frm_nxt < 4)
1887 return codecvt_base::partial;
1888 uint8_t c2 = frm_nxt[1];
1889 uint8_t c3 = frm_nxt[2];
1890 uint8_t c4 = frm_nxt[3];
1891 switch (c1)
1892 {
1893 case 0xF0:
1894 if (!(0x90 <= c2 && c2 <= 0xBF))
1895 return codecvt_base::error;
1896 break;
1897 case 0xF4:
1898 if ((c2 & 0xF0) != 0x80)
1899 return codecvt_base::error;
1900 break;
1901 default:
1902 if ((c2 & 0xC0) != 0x80)
1903 return codecvt_base::error;
1904 break;
1905 }
1906 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1907 return codecvt_base::error;
1908 if (to_end-to_nxt < 2)
1909 return codecvt_base::partial;
1910 if (((((unsigned long)c1 & 7) << 18) +
1911 (((unsigned long)c2 & 0x3F) << 12) +
1912 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1913 return codecvt_base::error;
1914 *to_nxt = static_cast<uint32_t>(
1915 0xD800
1916 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1917 | ((c2 & 0x0F) << 2)
1918 | ((c3 & 0x30) >> 4));
1919 *++to_nxt = static_cast<uint32_t>(
1920 0xDC00
1921 | ((c3 & 0x0F) << 6)
1922 | (c4 & 0x3F));
1923 frm_nxt += 4;
1924 }
1925 else
1926 {
1927 return codecvt_base::error;
1928 }
1929 }
1930 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1931}
1932
1933static
1934int
1935utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
1936 size_t mx, unsigned long Maxcode = 0x10FFFF,
1937 codecvt_mode mode = codecvt_mode(0))
1938{
1939 const uint8_t* frm_nxt = frm;
1940 if (mode & consume_header)
1941 {
1942 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1943 frm_nxt[2] == 0xBF)
1944 frm_nxt += 3;
1945 }
1946 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1947 {
1948 uint8_t c1 = *frm_nxt;
1949 if (c1 > Maxcode)
1950 break;
1951 if (c1 < 0x80)
1952 {
1953 ++frm_nxt;
1954 }
1955 else if (c1 < 0xC2)
1956 {
1957 break;
1958 }
1959 else if (c1 < 0xE0)
1960 {
1961 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
1962 break;
1963 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
1964 if (t > Maxcode)
1965 break;
1966 frm_nxt += 2;
1967 }
1968 else if (c1 < 0xF0)
1969 {
1970 if (frm_end-frm_nxt < 3)
1971 break;
1972 uint8_t c2 = frm_nxt[1];
1973 uint8_t c3 = frm_nxt[2];
1974 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1975 | ((c2 & 0x3F) << 6)
1976 | (c3 & 0x3F));
1977 switch (c1)
1978 {
1979 case 0xE0:
1980 if ((c2 & 0xE0) != 0xA0)
1981 return static_cast<int>(frm_nxt - frm);
1982 break;
1983 case 0xED:
1984 if ((c2 & 0xE0) != 0x80)
1985 return static_cast<int>(frm_nxt - frm);
1986 break;
1987 default:
1988 if ((c2 & 0xC0) != 0x80)
1989 return static_cast<int>(frm_nxt - frm);
1990 break;
1991 }
1992 if ((c3 & 0xC0) != 0x80)
1993 break;
1994 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
1995 break;
1996 frm_nxt += 3;
1997 }
1998 else if (c1 < 0xF5)
1999 {
2000 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2001 break;
2002 uint8_t c2 = frm_nxt[1];
2003 uint8_t c3 = frm_nxt[2];
2004 uint8_t c4 = frm_nxt[3];
2005 switch (c1)
2006 {
2007 case 0xF0:
2008 if (!(0x90 <= c2 && c2 <= 0xBF))
2009 return static_cast<int>(frm_nxt - frm);
2010 break;
2011 case 0xF4:
2012 if ((c2 & 0xF0) != 0x80)
2013 return static_cast<int>(frm_nxt - frm);
2014 break;
2015 default:
2016 if ((c2 & 0xC0) != 0x80)
2017 return static_cast<int>(frm_nxt - frm);
2018 break;
2019 }
2020 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2021 break;
2022 if (((((unsigned long)c1 & 7) << 18) +
2023 (((unsigned long)c2 & 0x3F) << 12) +
2024 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2025 break;
2026 ++nchar16_t;
2027 frm_nxt += 4;
2028 }
2029 else
2030 {
2031 break;
2032 }
2033 }
2034 return static_cast<int>(frm_nxt - frm);
2035}
2036
2037static
2038codecvt_base::result
2039ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2040 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2041 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2042{
2043 frm_nxt = frm;
2044 to_nxt = to;
2045 if (mode & generate_header)
2046 {
2047 if (to_end-to_nxt < 3)
2048 return codecvt_base::partial;
2049 *to_nxt++ = static_cast<uint8_t>(0xEF);
2050 *to_nxt++ = static_cast<uint8_t>(0xBB);
2051 *to_nxt++ = static_cast<uint8_t>(0xBF);
2052 }
2053 for (; frm_nxt < frm_end; ++frm_nxt)
2054 {
2055 uint32_t wc = *frm_nxt;
2056 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2057 return codecvt_base::error;
2058 if (wc < 0x000080)
2059 {
2060 if (to_end-to_nxt < 1)
2061 return codecvt_base::partial;
2062 *to_nxt++ = static_cast<uint8_t>(wc);
2063 }
2064 else if (wc < 0x000800)
2065 {
2066 if (to_end-to_nxt < 2)
2067 return codecvt_base::partial;
2068 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2069 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2070 }
2071 else if (wc < 0x010000)
2072 {
2073 if (to_end-to_nxt < 3)
2074 return codecvt_base::partial;
2075 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2076 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2077 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2078 }
2079 else // if (wc < 0x110000)
2080 {
2081 if (to_end-to_nxt < 4)
2082 return codecvt_base::partial;
2083 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2084 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2085 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2086 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2087 }
2088 }
2089 return codecvt_base::ok;
2090}
2091
2092static
2093codecvt_base::result
2094utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2095 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2096 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2097{
2098 frm_nxt = frm;
2099 to_nxt = to;
2100 if (mode & consume_header)
2101 {
2102 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2103 frm_nxt[2] == 0xBF)
2104 frm_nxt += 3;
2105 }
2106 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2107 {
2108 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2109 if (c1 < 0x80)
2110 {
2111 if (c1 > Maxcode)
2112 return codecvt_base::error;
2113 *to_nxt = static_cast<uint32_t>(c1);
2114 ++frm_nxt;
2115 }
2116 else if (c1 < 0xC2)
2117 {
2118 return codecvt_base::error;
2119 }
2120 else if (c1 < 0xE0)
2121 {
2122 if (frm_end-frm_nxt < 2)
2123 return codecvt_base::partial;
2124 uint8_t c2 = frm_nxt[1];
2125 if ((c2 & 0xC0) != 0x80)
2126 return codecvt_base::error;
2127 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2128 | (c2 & 0x3F));
2129 if (t > Maxcode)
2130 return codecvt_base::error;
2131 *to_nxt = t;
2132 frm_nxt += 2;
2133 }
2134 else if (c1 < 0xF0)
2135 {
2136 if (frm_end-frm_nxt < 3)
2137 return codecvt_base::partial;
2138 uint8_t c2 = frm_nxt[1];
2139 uint8_t c3 = frm_nxt[2];
2140 switch (c1)
2141 {
2142 case 0xE0:
2143 if ((c2 & 0xE0) != 0xA0)
2144 return codecvt_base::error;
2145 break;
2146 case 0xED:
2147 if ((c2 & 0xE0) != 0x80)
2148 return codecvt_base::error;
2149 break;
2150 default:
2151 if ((c2 & 0xC0) != 0x80)
2152 return codecvt_base::error;
2153 break;
2154 }
2155 if ((c3 & 0xC0) != 0x80)
2156 return codecvt_base::error;
2157 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2158 | ((c2 & 0x3F) << 6)
2159 | (c3 & 0x3F));
2160 if (t > Maxcode)
2161 return codecvt_base::error;
2162 *to_nxt = t;
2163 frm_nxt += 3;
2164 }
2165 else if (c1 < 0xF5)
2166 {
2167 if (frm_end-frm_nxt < 4)
2168 return codecvt_base::partial;
2169 uint8_t c2 = frm_nxt[1];
2170 uint8_t c3 = frm_nxt[2];
2171 uint8_t c4 = frm_nxt[3];
2172 switch (c1)
2173 {
2174 case 0xF0:
2175 if (!(0x90 <= c2 && c2 <= 0xBF))
2176 return codecvt_base::error;
2177 break;
2178 case 0xF4:
2179 if ((c2 & 0xF0) != 0x80)
2180 return codecvt_base::error;
2181 break;
2182 default:
2183 if ((c2 & 0xC0) != 0x80)
2184 return codecvt_base::error;
2185 break;
2186 }
2187 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2188 return codecvt_base::error;
2189 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2190 | ((c2 & 0x3F) << 12)
2191 | ((c3 & 0x3F) << 6)
2192 | (c4 & 0x3F));
2193 if (t > Maxcode)
2194 return codecvt_base::error;
2195 *to_nxt = t;
2196 frm_nxt += 4;
2197 }
2198 else
2199 {
2200 return codecvt_base::error;
2201 }
2202 }
2203 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2204}
2205
2206static
2207int
2208utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2209 size_t mx, unsigned long Maxcode = 0x10FFFF,
2210 codecvt_mode mode = codecvt_mode(0))
2211{
2212 const uint8_t* frm_nxt = frm;
2213 if (mode & consume_header)
2214 {
2215 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2216 frm_nxt[2] == 0xBF)
2217 frm_nxt += 3;
2218 }
2219 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2220 {
2221 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2222 if (c1 < 0x80)
2223 {
2224 if (c1 > Maxcode)
2225 break;
2226 ++frm_nxt;
2227 }
2228 else if (c1 < 0xC2)
2229 {
2230 break;
2231 }
2232 else if (c1 < 0xE0)
2233 {
2234 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2235 break;
2236 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2237 break;
2238 frm_nxt += 2;
2239 }
2240 else if (c1 < 0xF0)
2241 {
2242 if (frm_end-frm_nxt < 3)
2243 break;
2244 uint8_t c2 = frm_nxt[1];
2245 uint8_t c3 = frm_nxt[2];
2246 switch (c1)
2247 {
2248 case 0xE0:
2249 if ((c2 & 0xE0) != 0xA0)
2250 return static_cast<int>(frm_nxt - frm);
2251 break;
2252 case 0xED:
2253 if ((c2 & 0xE0) != 0x80)
2254 return static_cast<int>(frm_nxt - frm);
2255 break;
2256 default:
2257 if ((c2 & 0xC0) != 0x80)
2258 return static_cast<int>(frm_nxt - frm);
2259 break;
2260 }
2261 if ((c3 & 0xC0) != 0x80)
2262 break;
2263 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2264 break;
2265 frm_nxt += 3;
2266 }
2267 else if (c1 < 0xF5)
2268 {
2269 if (frm_end-frm_nxt < 4)
2270 break;
2271 uint8_t c2 = frm_nxt[1];
2272 uint8_t c3 = frm_nxt[2];
2273 uint8_t c4 = frm_nxt[3];
2274 switch (c1)
2275 {
2276 case 0xF0:
2277 if (!(0x90 <= c2 && c2 <= 0xBF))
2278 return static_cast<int>(frm_nxt - frm);
2279 break;
2280 case 0xF4:
2281 if ((c2 & 0xF0) != 0x80)
2282 return static_cast<int>(frm_nxt - frm);
2283 break;
2284 default:
2285 if ((c2 & 0xC0) != 0x80)
2286 return static_cast<int>(frm_nxt - frm);
2287 break;
2288 }
2289 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2290 break;
2291 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2292 | ((c2 & 0x3F) << 12)
2293 | ((c3 & 0x3F) << 6)
2294 | (c4 & 0x3F));
2295 if ((((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) |
2296 ((c3 & 0x3F) << 6) | (c4 & 0x3F)) > Maxcode)
2297 break;
2298 frm_nxt += 4;
2299 }
2300 else
2301 {
2302 break;
2303 }
2304 }
2305 return static_cast<int>(frm_nxt - frm);
2306}
2307
2308static
2309codecvt_base::result
2310ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2311 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2312 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2313{
2314 frm_nxt = frm;
2315 to_nxt = to;
2316 if (mode & generate_header)
2317 {
2318 if (to_end-to_nxt < 3)
2319 return codecvt_base::partial;
2320 *to_nxt++ = static_cast<uint8_t>(0xEF);
2321 *to_nxt++ = static_cast<uint8_t>(0xBB);
2322 *to_nxt++ = static_cast<uint8_t>(0xBF);
2323 }
2324 for (; frm_nxt < frm_end; ++frm_nxt)
2325 {
2326 uint16_t wc = *frm_nxt;
2327 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2328 return codecvt_base::error;
2329 if (wc < 0x0080)
2330 {
2331 if (to_end-to_nxt < 1)
2332 return codecvt_base::partial;
2333 *to_nxt++ = static_cast<uint8_t>(wc);
2334 }
2335 else if (wc < 0x0800)
2336 {
2337 if (to_end-to_nxt < 2)
2338 return codecvt_base::partial;
2339 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2340 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2341 }
2342 else // if (wc <= 0xFFFF)
2343 {
2344 if (to_end-to_nxt < 3)
2345 return codecvt_base::partial;
2346 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2347 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2348 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2349 }
2350 }
2351 return codecvt_base::ok;
2352}
2353
2354static
2355codecvt_base::result
2356utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2357 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2358 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2359{
2360 frm_nxt = frm;
2361 to_nxt = to;
2362 if (mode & consume_header)
2363 {
2364 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2365 frm_nxt[2] == 0xBF)
2366 frm_nxt += 3;
2367 }
2368 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2369 {
2370 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2371 if (c1 < 0x80)
2372 {
2373 if (c1 > Maxcode)
2374 return codecvt_base::error;
2375 *to_nxt = static_cast<uint16_t>(c1);
2376 ++frm_nxt;
2377 }
2378 else if (c1 < 0xC2)
2379 {
2380 return codecvt_base::error;
2381 }
2382 else if (c1 < 0xE0)
2383 {
2384 if (frm_end-frm_nxt < 2)
2385 return codecvt_base::partial;
2386 uint8_t c2 = frm_nxt[1];
2387 if ((c2 & 0xC0) != 0x80)
2388 return codecvt_base::error;
2389 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2390 | (c2 & 0x3F));
2391 if (t > Maxcode)
2392 return codecvt_base::error;
2393 *to_nxt = t;
2394 frm_nxt += 2;
2395 }
2396 else if (c1 < 0xF0)
2397 {
2398 if (frm_end-frm_nxt < 3)
2399 return codecvt_base::partial;
2400 uint8_t c2 = frm_nxt[1];
2401 uint8_t c3 = frm_nxt[2];
2402 switch (c1)
2403 {
2404 case 0xE0:
2405 if ((c2 & 0xE0) != 0xA0)
2406 return codecvt_base::error;
2407 break;
2408 case 0xED:
2409 if ((c2 & 0xE0) != 0x80)
2410 return codecvt_base::error;
2411 break;
2412 default:
2413 if ((c2 & 0xC0) != 0x80)
2414 return codecvt_base::error;
2415 break;
2416 }
2417 if ((c3 & 0xC0) != 0x80)
2418 return codecvt_base::error;
2419 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2420 | ((c2 & 0x3F) << 6)
2421 | (c3 & 0x3F));
2422 if (t > Maxcode)
2423 return codecvt_base::error;
2424 *to_nxt = t;
2425 frm_nxt += 3;
2426 }
2427 else
2428 {
2429 return codecvt_base::error;
2430 }
2431 }
2432 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2433}
2434
2435static
2436int
2437utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2438 size_t mx, unsigned long Maxcode = 0x10FFFF,
2439 codecvt_mode mode = codecvt_mode(0))
2440{
2441 const uint8_t* frm_nxt = frm;
2442 if (mode & consume_header)
2443 {
2444 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2445 frm_nxt[2] == 0xBF)
2446 frm_nxt += 3;
2447 }
2448 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2449 {
2450 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2451 if (c1 < 0x80)
2452 {
2453 if (c1 > Maxcode)
2454 break;
2455 ++frm_nxt;
2456 }
2457 else if (c1 < 0xC2)
2458 {
2459 break;
2460 }
2461 else if (c1 < 0xE0)
2462 {
2463 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2464 break;
2465 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2466 break;
2467 frm_nxt += 2;
2468 }
2469 else if (c1 < 0xF0)
2470 {
2471 if (frm_end-frm_nxt < 3)
2472 break;
2473 uint8_t c2 = frm_nxt[1];
2474 uint8_t c3 = frm_nxt[2];
2475 switch (c1)
2476 {
2477 case 0xE0:
2478 if ((c2 & 0xE0) != 0xA0)
2479 return static_cast<int>(frm_nxt - frm);
2480 break;
2481 case 0xED:
2482 if ((c2 & 0xE0) != 0x80)
2483 return static_cast<int>(frm_nxt - frm);
2484 break;
2485 default:
2486 if ((c2 & 0xC0) != 0x80)
2487 return static_cast<int>(frm_nxt - frm);
2488 break;
2489 }
2490 if ((c3 & 0xC0) != 0x80)
2491 break;
2492 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2493 break;
2494 frm_nxt += 3;
2495 }
2496 else
2497 {
2498 break;
2499 }
2500 }
2501 return static_cast<int>(frm_nxt - frm);
2502}
2503
2504static
2505codecvt_base::result
2506ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2507 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2508 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2509{
2510 frm_nxt = frm;
2511 to_nxt = to;
2512 if (mode & generate_header)
2513 {
2514 if (to_end-to_nxt < 2)
2515 return codecvt_base::partial;
2516 *to_nxt++ = static_cast<uint8_t>(0xFE);
2517 *to_nxt++ = static_cast<uint8_t>(0xFF);
2518 }
2519 for (; frm_nxt < frm_end; ++frm_nxt)
2520 {
2521 uint32_t wc = *frm_nxt;
2522 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2523 return codecvt_base::error;
2524 if (wc < 0x010000)
2525 {
2526 if (to_end-to_nxt < 2)
2527 return codecvt_base::partial;
2528 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2529 *to_nxt++ = static_cast<uint8_t>(wc);
2530 }
2531 else
2532 {
2533 if (to_end-to_nxt < 4)
2534 return codecvt_base::partial;
2535 uint16_t t = static_cast<uint16_t>(
2536 0xD800
2537 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2538 | ((wc & 0x00FC00) >> 10));
2539 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2540 *to_nxt++ = static_cast<uint8_t>(t);
2541 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2542 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2543 *to_nxt++ = static_cast<uint8_t>(t);
2544 }
2545 }
2546 return codecvt_base::ok;
2547}
2548
2549static
2550codecvt_base::result
2551utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2552 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2553 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2554{
2555 frm_nxt = frm;
2556 to_nxt = to;
2557 if (mode & consume_header)
2558 {
2559 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2560 frm_nxt += 2;
2561 }
2562 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2563 {
2564 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2565 if ((c1 & 0xFC00) == 0xDC00)
2566 return codecvt_base::error;
2567 if ((c1 & 0xFC00) != 0xD800)
2568 {
2569 if (c1 > Maxcode)
2570 return codecvt_base::error;
2571 *to_nxt = static_cast<uint32_t>(c1);
2572 frm_nxt += 2;
2573 }
2574 else
2575 {
2576 if (frm_end-frm_nxt < 4)
2577 return codecvt_base::partial;
2578 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2579 if ((c2 & 0xFC00) != 0xDC00)
2580 return codecvt_base::error;
2581 uint32_t t = static_cast<uint32_t>(
2582 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2583 | ((c1 & 0x003F) << 10)
2584 | (c2 & 0x03FF));
2585 if (t > Maxcode)
2586 return codecvt_base::error;
2587 *to_nxt = t;
2588 frm_nxt += 4;
2589 }
2590 }
2591 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2592}
2593
2594static
2595int
2596utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2597 size_t mx, unsigned long Maxcode = 0x10FFFF,
2598 codecvt_mode mode = codecvt_mode(0))
2599{
2600 const uint8_t* frm_nxt = frm;
2601 frm_nxt = frm;
2602 if (mode & consume_header)
2603 {
2604 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2605 frm_nxt += 2;
2606 }
2607 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2608 {
2609 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2610 if ((c1 & 0xFC00) == 0xDC00)
2611 break;
2612 if ((c1 & 0xFC00) != 0xD800)
2613 {
2614 if (c1 > Maxcode)
2615 break;
2616 frm_nxt += 2;
2617 }
2618 else
2619 {
2620 if (frm_end-frm_nxt < 4)
2621 break;
2622 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2623 if ((c2 & 0xFC00) != 0xDC00)
2624 break;
2625 uint32_t t = static_cast<uint32_t>(
2626 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2627 | ((c1 & 0x003F) << 10)
2628 | (c2 & 0x03FF));
2629 if (t > Maxcode)
2630 break;
2631 frm_nxt += 4;
2632 }
2633 }
2634 return static_cast<int>(frm_nxt - frm);
2635}
2636
2637static
2638codecvt_base::result
2639ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2640 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2641 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2642{
2643 frm_nxt = frm;
2644 to_nxt = to;
2645 if (mode & generate_header)
2646 {
2647 if (to_end-to_nxt < 2)
2648 return codecvt_base::partial;
2649 *to_nxt++ = static_cast<uint8_t>(0xFF);
2650 *to_nxt++ = static_cast<uint8_t>(0xFE);
2651 }
2652 for (; frm_nxt < frm_end; ++frm_nxt)
2653 {
2654 uint32_t wc = *frm_nxt;
2655 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2656 return codecvt_base::error;
2657 if (wc < 0x010000)
2658 {
2659 if (to_end-to_nxt < 2)
2660 return codecvt_base::partial;
2661 *to_nxt++ = static_cast<uint8_t>(wc);
2662 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2663 }
2664 else
2665 {
2666 if (to_end-to_nxt < 4)
2667 return codecvt_base::partial;
2668 uint16_t t = static_cast<uint16_t>(
2669 0xD800
2670 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2671 | ((wc & 0x00FC00) >> 10));
2672 *to_nxt++ = static_cast<uint8_t>(t);
2673 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2674 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2675 *to_nxt++ = static_cast<uint8_t>(t);
2676 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2677 }
2678 }
2679 return codecvt_base::ok;
2680}
2681
2682static
2683codecvt_base::result
2684utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2685 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2686 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2687{
2688 frm_nxt = frm;
2689 to_nxt = to;
2690 if (mode & consume_header)
2691 {
2692 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2693 frm_nxt += 2;
2694 }
2695 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2696 {
2697 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2698 if ((c1 & 0xFC00) == 0xDC00)
2699 return codecvt_base::error;
2700 if ((c1 & 0xFC00) != 0xD800)
2701 {
2702 if (c1 > Maxcode)
2703 return codecvt_base::error;
2704 *to_nxt = static_cast<uint32_t>(c1);
2705 frm_nxt += 2;
2706 }
2707 else
2708 {
2709 if (frm_end-frm_nxt < 4)
2710 return codecvt_base::partial;
2711 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2712 if ((c2 & 0xFC00) != 0xDC00)
2713 return codecvt_base::error;
2714 uint32_t t = static_cast<uint32_t>(
2715 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2716 | ((c1 & 0x003F) << 10)
2717 | (c2 & 0x03FF));
2718 if (t > Maxcode)
2719 return codecvt_base::error;
2720 *to_nxt = t;
2721 frm_nxt += 4;
2722 }
2723 }
2724 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2725}
2726
2727static
2728int
2729utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2730 size_t mx, unsigned long Maxcode = 0x10FFFF,
2731 codecvt_mode mode = codecvt_mode(0))
2732{
2733 const uint8_t* frm_nxt = frm;
2734 frm_nxt = frm;
2735 if (mode & consume_header)
2736 {
2737 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2738 frm_nxt += 2;
2739 }
2740 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2741 {
2742 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2743 if ((c1 & 0xFC00) == 0xDC00)
2744 break;
2745 if ((c1 & 0xFC00) != 0xD800)
2746 {
2747 if (c1 > Maxcode)
2748 break;
2749 frm_nxt += 2;
2750 }
2751 else
2752 {
2753 if (frm_end-frm_nxt < 4)
2754 break;
2755 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2756 if ((c2 & 0xFC00) != 0xDC00)
2757 break;
2758 uint32_t t = static_cast<uint32_t>(
2759 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2760 | ((c1 & 0x003F) << 10)
2761 | (c2 & 0x03FF));
2762 if (t > Maxcode)
2763 break;
2764 frm_nxt += 4;
2765 }
2766 }
2767 return static_cast<int>(frm_nxt - frm);
2768}
2769
2770static
2771codecvt_base::result
2772ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2773 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2774 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2775{
2776 frm_nxt = frm;
2777 to_nxt = to;
2778 if (mode & generate_header)
2779 {
2780 if (to_end-to_nxt < 2)
2781 return codecvt_base::partial;
2782 *to_nxt++ = static_cast<uint8_t>(0xFE);
2783 *to_nxt++ = static_cast<uint8_t>(0xFF);
2784 }
2785 for (; frm_nxt < frm_end; ++frm_nxt)
2786 {
2787 uint16_t wc = *frm_nxt;
2788 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2789 return codecvt_base::error;
2790 if (to_end-to_nxt < 2)
2791 return codecvt_base::partial;
2792 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2793 *to_nxt++ = static_cast<uint8_t>(wc);
2794 }
2795 return codecvt_base::ok;
2796}
2797
2798static
2799codecvt_base::result
2800utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2801 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2802 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2803{
2804 frm_nxt = frm;
2805 to_nxt = to;
2806 if (mode & consume_header)
2807 {
2808 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2809 frm_nxt += 2;
2810 }
2811 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2812 {
2813 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2814 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2815 return codecvt_base::error;
2816 *to_nxt = c1;
2817 frm_nxt += 2;
2818 }
2819 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2820}
2821
2822static
2823int
2824utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2825 size_t mx, unsigned long Maxcode = 0x10FFFF,
2826 codecvt_mode mode = codecvt_mode(0))
2827{
2828 const uint8_t* frm_nxt = frm;
2829 frm_nxt = frm;
2830 if (mode & consume_header)
2831 {
2832 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2833 frm_nxt += 2;
2834 }
2835 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2836 {
2837 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2838 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2839 break;
2840 frm_nxt += 2;
2841 }
2842 return static_cast<int>(frm_nxt - frm);
2843}
2844
2845static
2846codecvt_base::result
2847ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2848 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2849 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2850{
2851 frm_nxt = frm;
2852 to_nxt = to;
2853 if (mode & generate_header)
2854 {
2855 if (to_end-to_nxt < 2)
2856 return codecvt_base::partial;
2857 *to_nxt++ = static_cast<uint8_t>(0xFF);
2858 *to_nxt++ = static_cast<uint8_t>(0xFE);
2859 }
2860 for (; frm_nxt < frm_end; ++frm_nxt)
2861 {
2862 uint16_t wc = *frm_nxt;
2863 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2864 return codecvt_base::error;
2865 if (to_end-to_nxt < 2)
2866 return codecvt_base::partial;
2867 *to_nxt++ = static_cast<uint8_t>(wc);
2868 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2869 }
2870 return codecvt_base::ok;
2871}
2872
2873static
2874codecvt_base::result
2875utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2876 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2877 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2878{
2879 frm_nxt = frm;
2880 to_nxt = to;
2881 if (mode & consume_header)
2882 {
2883 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2884 frm_nxt += 2;
2885 }
2886 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2887 {
2888 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2889 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2890 return codecvt_base::error;
2891 *to_nxt = c1;
2892 frm_nxt += 2;
2893 }
2894 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2895}
2896
2897static
2898int
2899utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2900 size_t mx, unsigned long Maxcode = 0x10FFFF,
2901 codecvt_mode mode = codecvt_mode(0))
2902{
2903 const uint8_t* frm_nxt = frm;
2904 frm_nxt = frm;
2905 if (mode & consume_header)
2906 {
2907 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2908 frm_nxt += 2;
2909 }
2910 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2911 {
2912 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2913 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2914 break;
2915 frm_nxt += 2;
2916 }
2917 return static_cast<int>(frm_nxt - frm);
2918}
2919
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002920// template <> class codecvt<char16_t, char, mbstate_t>
2921
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002922locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002923
2924codecvt<char16_t, char, mbstate_t>::~codecvt()
2925{
2926}
2927
2928codecvt<char16_t, char, mbstate_t>::result
2929codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002930 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002931 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2932{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002933 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2934 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2935 const uint16_t* _frm_nxt = _frm;
2936 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2937 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2938 uint8_t* _to_nxt = _to;
2939 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2940 frm_nxt = frm + (_frm_nxt - _frm);
2941 to_nxt = to + (_to_nxt - _to);
2942 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002943}
2944
2945codecvt<char16_t, char, mbstate_t>::result
2946codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002947 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002948 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2949{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002950 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2951 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2952 const uint8_t* _frm_nxt = _frm;
2953 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2954 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2955 uint16_t* _to_nxt = _to;
2956 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2957 frm_nxt = frm + (_frm_nxt - _frm);
2958 to_nxt = to + (_to_nxt - _to);
2959 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002960}
2961
2962codecvt<char16_t, char, mbstate_t>::result
2963codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
2964 extern_type* to, extern_type*, extern_type*& to_nxt) const
2965{
2966 to_nxt = to;
2967 return noconv;
2968}
2969
2970int
Howard Hinnantc9834542011-05-31 15:34:58 +00002971codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002972{
2973 return 0;
2974}
2975
2976bool
Howard Hinnantc9834542011-05-31 15:34:58 +00002977codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002978{
2979 return false;
2980}
2981
2982int
2983codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
2984 const extern_type* frm, const extern_type* frm_end, size_t mx) const
2985{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002986 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2987 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2988 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002989}
2990
2991int
Howard Hinnantc9834542011-05-31 15:34:58 +00002992codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002993{
2994 return 4;
2995}
2996
2997// template <> class codecvt<char32_t, char, mbstate_t>
2998
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002999locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003000
3001codecvt<char32_t, char, mbstate_t>::~codecvt()
3002{
3003}
3004
3005codecvt<char32_t, char, mbstate_t>::result
3006codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003007 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003008 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3009{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003010 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3011 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3012 const uint32_t* _frm_nxt = _frm;
3013 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3014 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3015 uint8_t* _to_nxt = _to;
3016 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3017 frm_nxt = frm + (_frm_nxt - _frm);
3018 to_nxt = to + (_to_nxt - _to);
3019 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003020}
3021
3022codecvt<char32_t, char, mbstate_t>::result
3023codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003024 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003025 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3026{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003027 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3028 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3029 const uint8_t* _frm_nxt = _frm;
3030 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3031 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3032 uint32_t* _to_nxt = _to;
3033 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3034 frm_nxt = frm + (_frm_nxt - _frm);
3035 to_nxt = to + (_to_nxt - _to);
3036 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003037}
3038
3039codecvt<char32_t, char, mbstate_t>::result
3040codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3041 extern_type* to, extern_type*, extern_type*& to_nxt) const
3042{
3043 to_nxt = to;
3044 return noconv;
3045}
3046
3047int
Howard Hinnantc9834542011-05-31 15:34:58 +00003048codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003049{
3050 return 0;
3051}
3052
3053bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003054codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003055{
3056 return false;
3057}
3058
3059int
3060codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3061 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3062{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003063 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3064 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3065 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003066}
3067
3068int
Howard Hinnantc9834542011-05-31 15:34:58 +00003069codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003070{
3071 return 4;
3072}
3073
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003074// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003075
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003076__codecvt_utf8<wchar_t>::result
3077__codecvt_utf8<wchar_t>::do_out(state_type&,
3078 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003079 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3080{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003081 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3082 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3083 const uint32_t* _frm_nxt = _frm;
3084 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3085 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3086 uint8_t* _to_nxt = _to;
3087 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3088 _Maxcode_, _Mode_);
3089 frm_nxt = frm + (_frm_nxt - _frm);
3090 to_nxt = to + (_to_nxt - _to);
3091 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003092}
3093
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003094__codecvt_utf8<wchar_t>::result
3095__codecvt_utf8<wchar_t>::do_in(state_type&,
3096 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003097 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3098{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003099 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3100 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3101 const uint8_t* _frm_nxt = _frm;
3102 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3103 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3104 uint32_t* _to_nxt = _to;
3105 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3106 _Maxcode_, _Mode_);
3107 frm_nxt = frm + (_frm_nxt - _frm);
3108 to_nxt = to + (_to_nxt - _to);
3109 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003110}
3111
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003112__codecvt_utf8<wchar_t>::result
3113__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003114 extern_type* to, extern_type*, extern_type*& to_nxt) const
3115{
3116 to_nxt = to;
3117 return noconv;
3118}
3119
3120int
Howard Hinnantc9834542011-05-31 15:34:58 +00003121__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003122{
3123 return 0;
3124}
3125
3126bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003127__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003128{
3129 return false;
3130}
3131
3132int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003133__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003134 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3135{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003136 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3137 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3138 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003139}
3140
3141int
Howard Hinnantc9834542011-05-31 15:34:58 +00003142__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003143{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003144 if (_Mode_ & consume_header)
3145 return 7;
3146 return 4;
3147}
3148
3149// __codecvt_utf8<char16_t>
3150
3151__codecvt_utf8<char16_t>::result
3152__codecvt_utf8<char16_t>::do_out(state_type&,
3153 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3154 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3155{
3156 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3157 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3158 const uint16_t* _frm_nxt = _frm;
3159 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3160 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3161 uint8_t* _to_nxt = _to;
3162 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3163 _Maxcode_, _Mode_);
3164 frm_nxt = frm + (_frm_nxt - _frm);
3165 to_nxt = to + (_to_nxt - _to);
3166 return r;
3167}
3168
3169__codecvt_utf8<char16_t>::result
3170__codecvt_utf8<char16_t>::do_in(state_type&,
3171 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3172 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3173{
3174 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3175 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3176 const uint8_t* _frm_nxt = _frm;
3177 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3178 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3179 uint16_t* _to_nxt = _to;
3180 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3181 _Maxcode_, _Mode_);
3182 frm_nxt = frm + (_frm_nxt - _frm);
3183 to_nxt = to + (_to_nxt - _to);
3184 return r;
3185}
3186
3187__codecvt_utf8<char16_t>::result
3188__codecvt_utf8<char16_t>::do_unshift(state_type&,
3189 extern_type* to, extern_type*, extern_type*& to_nxt) const
3190{
3191 to_nxt = to;
3192 return noconv;
3193}
3194
3195int
Howard Hinnantc9834542011-05-31 15:34:58 +00003196__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003197{
3198 return 0;
3199}
3200
3201bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003202__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003203{
3204 return false;
3205}
3206
3207int
3208__codecvt_utf8<char16_t>::do_length(state_type&,
3209 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3210{
3211 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3212 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3213 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3214}
3215
3216int
Howard Hinnantc9834542011-05-31 15:34:58 +00003217__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003218{
3219 if (_Mode_ & consume_header)
3220 return 6;
3221 return 3;
3222}
3223
3224// __codecvt_utf8<char32_t>
3225
3226__codecvt_utf8<char32_t>::result
3227__codecvt_utf8<char32_t>::do_out(state_type&,
3228 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3229 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3230{
3231 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3232 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3233 const uint32_t* _frm_nxt = _frm;
3234 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3235 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3236 uint8_t* _to_nxt = _to;
3237 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3238 _Maxcode_, _Mode_);
3239 frm_nxt = frm + (_frm_nxt - _frm);
3240 to_nxt = to + (_to_nxt - _to);
3241 return r;
3242}
3243
3244__codecvt_utf8<char32_t>::result
3245__codecvt_utf8<char32_t>::do_in(state_type&,
3246 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3247 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3248{
3249 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3250 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3251 const uint8_t* _frm_nxt = _frm;
3252 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3253 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3254 uint32_t* _to_nxt = _to;
3255 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3256 _Maxcode_, _Mode_);
3257 frm_nxt = frm + (_frm_nxt - _frm);
3258 to_nxt = to + (_to_nxt - _to);
3259 return r;
3260}
3261
3262__codecvt_utf8<char32_t>::result
3263__codecvt_utf8<char32_t>::do_unshift(state_type&,
3264 extern_type* to, extern_type*, extern_type*& to_nxt) const
3265{
3266 to_nxt = to;
3267 return noconv;
3268}
3269
3270int
Howard Hinnantc9834542011-05-31 15:34:58 +00003271__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003272{
3273 return 0;
3274}
3275
3276bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003277__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003278{
3279 return false;
3280}
3281
3282int
3283__codecvt_utf8<char32_t>::do_length(state_type&,
3284 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3285{
3286 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3287 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3288 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3289}
3290
3291int
Howard Hinnantc9834542011-05-31 15:34:58 +00003292__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003293{
3294 if (_Mode_ & consume_header)
3295 return 7;
3296 return 4;
3297}
3298
3299// __codecvt_utf16<wchar_t, false>
3300
3301__codecvt_utf16<wchar_t, false>::result
3302__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3303 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3304 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3305{
3306 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3307 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3308 const uint32_t* _frm_nxt = _frm;
3309 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3310 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3311 uint8_t* _to_nxt = _to;
3312 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3313 _Maxcode_, _Mode_);
3314 frm_nxt = frm + (_frm_nxt - _frm);
3315 to_nxt = to + (_to_nxt - _to);
3316 return r;
3317}
3318
3319__codecvt_utf16<wchar_t, false>::result
3320__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3321 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3322 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3323{
3324 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3325 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3326 const uint8_t* _frm_nxt = _frm;
3327 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3328 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3329 uint32_t* _to_nxt = _to;
3330 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3331 _Maxcode_, _Mode_);
3332 frm_nxt = frm + (_frm_nxt - _frm);
3333 to_nxt = to + (_to_nxt - _to);
3334 return r;
3335}
3336
3337__codecvt_utf16<wchar_t, false>::result
3338__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3339 extern_type* to, extern_type*, extern_type*& to_nxt) const
3340{
3341 to_nxt = to;
3342 return noconv;
3343}
3344
3345int
Howard Hinnantc9834542011-05-31 15:34:58 +00003346__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003347{
3348 return 0;
3349}
3350
3351bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003352__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003353{
3354 return false;
3355}
3356
3357int
3358__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3359 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3360{
3361 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3362 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3363 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3364}
3365
3366int
Howard Hinnantc9834542011-05-31 15:34:58 +00003367__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003368{
3369 if (_Mode_ & consume_header)
3370 return 6;
3371 return 4;
3372}
3373
3374// __codecvt_utf16<wchar_t, true>
3375
3376__codecvt_utf16<wchar_t, true>::result
3377__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3378 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3379 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3380{
3381 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3382 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3383 const uint32_t* _frm_nxt = _frm;
3384 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3385 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3386 uint8_t* _to_nxt = _to;
3387 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3388 _Maxcode_, _Mode_);
3389 frm_nxt = frm + (_frm_nxt - _frm);
3390 to_nxt = to + (_to_nxt - _to);
3391 return r;
3392}
3393
3394__codecvt_utf16<wchar_t, true>::result
3395__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3396 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3397 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3398{
3399 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3400 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3401 const uint8_t* _frm_nxt = _frm;
3402 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3403 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3404 uint32_t* _to_nxt = _to;
3405 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3406 _Maxcode_, _Mode_);
3407 frm_nxt = frm + (_frm_nxt - _frm);
3408 to_nxt = to + (_to_nxt - _to);
3409 return r;
3410}
3411
3412__codecvt_utf16<wchar_t, true>::result
3413__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3414 extern_type* to, extern_type*, extern_type*& to_nxt) const
3415{
3416 to_nxt = to;
3417 return noconv;
3418}
3419
3420int
Howard Hinnantc9834542011-05-31 15:34:58 +00003421__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003422{
3423 return 0;
3424}
3425
3426bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003427__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003428{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003429 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003430}
3431
3432int
3433__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3434 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3435{
3436 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3437 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3438 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3439}
3440
3441int
Howard Hinnantc9834542011-05-31 15:34:58 +00003442__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003443{
3444 if (_Mode_ & consume_header)
3445 return 6;
3446 return 4;
3447}
3448
3449// __codecvt_utf16<char16_t, false>
3450
3451__codecvt_utf16<char16_t, false>::result
3452__codecvt_utf16<char16_t, false>::do_out(state_type&,
3453 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3454 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3455{
3456 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3457 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3458 const uint16_t* _frm_nxt = _frm;
3459 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3460 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3461 uint8_t* _to_nxt = _to;
3462 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3463 _Maxcode_, _Mode_);
3464 frm_nxt = frm + (_frm_nxt - _frm);
3465 to_nxt = to + (_to_nxt - _to);
3466 return r;
3467}
3468
3469__codecvt_utf16<char16_t, false>::result
3470__codecvt_utf16<char16_t, false>::do_in(state_type&,
3471 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3472 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3473{
3474 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3475 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3476 const uint8_t* _frm_nxt = _frm;
3477 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3478 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3479 uint16_t* _to_nxt = _to;
3480 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3481 _Maxcode_, _Mode_);
3482 frm_nxt = frm + (_frm_nxt - _frm);
3483 to_nxt = to + (_to_nxt - _to);
3484 return r;
3485}
3486
3487__codecvt_utf16<char16_t, false>::result
3488__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3489 extern_type* to, extern_type*, extern_type*& to_nxt) const
3490{
3491 to_nxt = to;
3492 return noconv;
3493}
3494
3495int
Howard Hinnantc9834542011-05-31 15:34:58 +00003496__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003497{
3498 return 0;
3499}
3500
3501bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003502__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003503{
3504 return false;
3505}
3506
3507int
3508__codecvt_utf16<char16_t, false>::do_length(state_type&,
3509 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3510{
3511 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3512 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3513 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3514}
3515
3516int
Howard Hinnantc9834542011-05-31 15:34:58 +00003517__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003518{
3519 if (_Mode_ & consume_header)
3520 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003521 return 2;
3522}
3523
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003524// __codecvt_utf16<char16_t, true>
3525
3526__codecvt_utf16<char16_t, true>::result
3527__codecvt_utf16<char16_t, true>::do_out(state_type&,
3528 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3529 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3530{
3531 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3532 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3533 const uint16_t* _frm_nxt = _frm;
3534 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3535 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3536 uint8_t* _to_nxt = _to;
3537 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3538 _Maxcode_, _Mode_);
3539 frm_nxt = frm + (_frm_nxt - _frm);
3540 to_nxt = to + (_to_nxt - _to);
3541 return r;
3542}
3543
3544__codecvt_utf16<char16_t, true>::result
3545__codecvt_utf16<char16_t, true>::do_in(state_type&,
3546 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3547 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3548{
3549 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3550 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3551 const uint8_t* _frm_nxt = _frm;
3552 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3553 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3554 uint16_t* _to_nxt = _to;
3555 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3556 _Maxcode_, _Mode_);
3557 frm_nxt = frm + (_frm_nxt - _frm);
3558 to_nxt = to + (_to_nxt - _to);
3559 return r;
3560}
3561
3562__codecvt_utf16<char16_t, true>::result
3563__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3564 extern_type* to, extern_type*, extern_type*& to_nxt) const
3565{
3566 to_nxt = to;
3567 return noconv;
3568}
3569
3570int
Howard Hinnantc9834542011-05-31 15:34:58 +00003571__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003572{
3573 return 0;
3574}
3575
3576bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003577__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003578{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003579 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003580}
3581
3582int
3583__codecvt_utf16<char16_t, true>::do_length(state_type&,
3584 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3585{
3586 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3587 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3588 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3589}
3590
3591int
Howard Hinnantc9834542011-05-31 15:34:58 +00003592__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003593{
3594 if (_Mode_ & consume_header)
3595 return 4;
3596 return 2;
3597}
3598
3599// __codecvt_utf16<char32_t, false>
3600
3601__codecvt_utf16<char32_t, false>::result
3602__codecvt_utf16<char32_t, false>::do_out(state_type&,
3603 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3604 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3605{
3606 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3607 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3608 const uint32_t* _frm_nxt = _frm;
3609 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3610 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3611 uint8_t* _to_nxt = _to;
3612 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3613 _Maxcode_, _Mode_);
3614 frm_nxt = frm + (_frm_nxt - _frm);
3615 to_nxt = to + (_to_nxt - _to);
3616 return r;
3617}
3618
3619__codecvt_utf16<char32_t, false>::result
3620__codecvt_utf16<char32_t, false>::do_in(state_type&,
3621 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3622 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3623{
3624 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3625 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3626 const uint8_t* _frm_nxt = _frm;
3627 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3628 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3629 uint32_t* _to_nxt = _to;
3630 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3631 _Maxcode_, _Mode_);
3632 frm_nxt = frm + (_frm_nxt - _frm);
3633 to_nxt = to + (_to_nxt - _to);
3634 return r;
3635}
3636
3637__codecvt_utf16<char32_t, false>::result
3638__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3639 extern_type* to, extern_type*, extern_type*& to_nxt) const
3640{
3641 to_nxt = to;
3642 return noconv;
3643}
3644
3645int
Howard Hinnantc9834542011-05-31 15:34:58 +00003646__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003647{
3648 return 0;
3649}
3650
3651bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003652__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003653{
3654 return false;
3655}
3656
3657int
3658__codecvt_utf16<char32_t, false>::do_length(state_type&,
3659 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3660{
3661 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3662 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3663 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3664}
3665
3666int
Howard Hinnantc9834542011-05-31 15:34:58 +00003667__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003668{
3669 if (_Mode_ & consume_header)
3670 return 6;
3671 return 4;
3672}
3673
3674// __codecvt_utf16<char32_t, true>
3675
3676__codecvt_utf16<char32_t, true>::result
3677__codecvt_utf16<char32_t, true>::do_out(state_type&,
3678 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3679 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3680{
3681 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3682 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3683 const uint32_t* _frm_nxt = _frm;
3684 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3685 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3686 uint8_t* _to_nxt = _to;
3687 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3688 _Maxcode_, _Mode_);
3689 frm_nxt = frm + (_frm_nxt - _frm);
3690 to_nxt = to + (_to_nxt - _to);
3691 return r;
3692}
3693
3694__codecvt_utf16<char32_t, true>::result
3695__codecvt_utf16<char32_t, true>::do_in(state_type&,
3696 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3697 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3698{
3699 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3700 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3701 const uint8_t* _frm_nxt = _frm;
3702 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3703 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3704 uint32_t* _to_nxt = _to;
3705 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3706 _Maxcode_, _Mode_);
3707 frm_nxt = frm + (_frm_nxt - _frm);
3708 to_nxt = to + (_to_nxt - _to);
3709 return r;
3710}
3711
3712__codecvt_utf16<char32_t, true>::result
3713__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3714 extern_type* to, extern_type*, extern_type*& to_nxt) const
3715{
3716 to_nxt = to;
3717 return noconv;
3718}
3719
3720int
Howard Hinnantc9834542011-05-31 15:34:58 +00003721__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003722{
3723 return 0;
3724}
3725
3726bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003727__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003728{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003729 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003730}
3731
3732int
3733__codecvt_utf16<char32_t, true>::do_length(state_type&,
3734 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3735{
3736 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3737 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3738 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3739}
3740
3741int
Howard Hinnantc9834542011-05-31 15:34:58 +00003742__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003743{
3744 if (_Mode_ & consume_header)
3745 return 6;
3746 return 4;
3747}
3748
3749// __codecvt_utf8_utf16<wchar_t>
3750
3751__codecvt_utf8_utf16<wchar_t>::result
3752__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3753 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3754 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3755{
3756 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3757 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3758 const uint32_t* _frm_nxt = _frm;
3759 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3760 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3761 uint8_t* _to_nxt = _to;
3762 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3763 _Maxcode_, _Mode_);
3764 frm_nxt = frm + (_frm_nxt - _frm);
3765 to_nxt = to + (_to_nxt - _to);
3766 return r;
3767}
3768
3769__codecvt_utf8_utf16<wchar_t>::result
3770__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3771 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3772 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3773{
3774 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3775 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3776 const uint8_t* _frm_nxt = _frm;
3777 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3778 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3779 uint32_t* _to_nxt = _to;
3780 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3781 _Maxcode_, _Mode_);
3782 frm_nxt = frm + (_frm_nxt - _frm);
3783 to_nxt = to + (_to_nxt - _to);
3784 return r;
3785}
3786
3787__codecvt_utf8_utf16<wchar_t>::result
3788__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3789 extern_type* to, extern_type*, extern_type*& to_nxt) const
3790{
3791 to_nxt = to;
3792 return noconv;
3793}
3794
3795int
Howard Hinnantc9834542011-05-31 15:34:58 +00003796__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003797{
3798 return 0;
3799}
3800
3801bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003802__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003803{
3804 return false;
3805}
3806
3807int
3808__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3809 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3810{
3811 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3812 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3813 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3814}
3815
3816int
Howard Hinnantc9834542011-05-31 15:34:58 +00003817__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003818{
3819 if (_Mode_ & consume_header)
3820 return 7;
3821 return 4;
3822}
3823
3824// __codecvt_utf8_utf16<char16_t>
3825
3826__codecvt_utf8_utf16<char16_t>::result
3827__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3828 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3829 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3830{
3831 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3832 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3833 const uint16_t* _frm_nxt = _frm;
3834 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3835 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3836 uint8_t* _to_nxt = _to;
3837 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3838 _Maxcode_, _Mode_);
3839 frm_nxt = frm + (_frm_nxt - _frm);
3840 to_nxt = to + (_to_nxt - _to);
3841 return r;
3842}
3843
3844__codecvt_utf8_utf16<char16_t>::result
3845__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3846 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3847 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3848{
3849 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3850 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3851 const uint8_t* _frm_nxt = _frm;
3852 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3853 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3854 uint16_t* _to_nxt = _to;
3855 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3856 _Maxcode_, _Mode_);
3857 frm_nxt = frm + (_frm_nxt - _frm);
3858 to_nxt = to + (_to_nxt - _to);
3859 return r;
3860}
3861
3862__codecvt_utf8_utf16<char16_t>::result
3863__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3864 extern_type* to, extern_type*, extern_type*& to_nxt) const
3865{
3866 to_nxt = to;
3867 return noconv;
3868}
3869
3870int
Howard Hinnantc9834542011-05-31 15:34:58 +00003871__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003872{
3873 return 0;
3874}
3875
3876bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003877__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003878{
3879 return false;
3880}
3881
3882int
3883__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3884 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3885{
3886 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3887 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3888 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3889}
3890
3891int
Howard Hinnantc9834542011-05-31 15:34:58 +00003892__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003893{
3894 if (_Mode_ & consume_header)
3895 return 7;
3896 return 4;
3897}
3898
3899// __codecvt_utf8_utf16<char32_t>
3900
3901__codecvt_utf8_utf16<char32_t>::result
3902__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3903 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3904 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3905{
3906 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3907 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3908 const uint32_t* _frm_nxt = _frm;
3909 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3910 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3911 uint8_t* _to_nxt = _to;
3912 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3913 _Maxcode_, _Mode_);
3914 frm_nxt = frm + (_frm_nxt - _frm);
3915 to_nxt = to + (_to_nxt - _to);
3916 return r;
3917}
3918
3919__codecvt_utf8_utf16<char32_t>::result
3920__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3921 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3922 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3923{
3924 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3925 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3926 const uint8_t* _frm_nxt = _frm;
3927 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3928 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3929 uint32_t* _to_nxt = _to;
3930 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3931 _Maxcode_, _Mode_);
3932 frm_nxt = frm + (_frm_nxt - _frm);
3933 to_nxt = to + (_to_nxt - _to);
3934 return r;
3935}
3936
3937__codecvt_utf8_utf16<char32_t>::result
3938__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
3939 extern_type* to, extern_type*, extern_type*& to_nxt) const
3940{
3941 to_nxt = to;
3942 return noconv;
3943}
3944
3945int
Howard Hinnantc9834542011-05-31 15:34:58 +00003946__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003947{
3948 return 0;
3949}
3950
3951bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003952__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003953{
3954 return false;
3955}
3956
3957int
3958__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
3959 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3960{
3961 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3962 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3963 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3964}
3965
3966int
Howard Hinnantc9834542011-05-31 15:34:58 +00003967__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003968{
3969 if (_Mode_ & consume_header)
3970 return 7;
3971 return 4;
3972}
3973
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003974// __narrow_to_utf8<16>
3975
3976__narrow_to_utf8<16>::~__narrow_to_utf8()
3977{
3978}
3979
3980// __narrow_to_utf8<32>
3981
3982__narrow_to_utf8<32>::~__narrow_to_utf8()
3983{
3984}
3985
3986// __widen_from_utf8<16>
3987
3988__widen_from_utf8<16>::~__widen_from_utf8()
3989{
3990}
3991
3992// __widen_from_utf8<32>
3993
3994__widen_from_utf8<32>::~__widen_from_utf8()
3995{
3996}
3997
3998// numpunct<char> && numpunct<wchar_t>
3999
4000locale::id numpunct< char >::id;
4001locale::id numpunct<wchar_t>::id;
4002
4003numpunct<char>::numpunct(size_t refs)
4004 : locale::facet(refs),
4005 __decimal_point_('.'),
4006 __thousands_sep_(',')
4007{
4008}
4009
4010numpunct<wchar_t>::numpunct(size_t refs)
4011 : locale::facet(refs),
4012 __decimal_point_(L'.'),
4013 __thousands_sep_(L',')
4014{
4015}
4016
4017numpunct<char>::~numpunct()
4018{
4019}
4020
4021numpunct<wchar_t>::~numpunct()
4022{
4023}
4024
4025 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4026wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4027
4028 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4029wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4030
4031string numpunct< char >::do_grouping() const {return __grouping_;}
4032string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4033
4034 string numpunct< char >::do_truename() const {return "true";}
4035wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4036
4037 string numpunct< char >::do_falsename() const {return "false";}
4038wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4039
4040// numpunct_byname<char>
4041
4042numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4043 : numpunct<char>(refs)
4044{
4045 __init(nm);
4046}
4047
4048numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4049 : numpunct<char>(refs)
4050{
4051 __init(nm.c_str());
4052}
4053
4054numpunct_byname<char>::~numpunct_byname()
4055{
4056}
4057
4058void
4059numpunct_byname<char>::__init(const char* nm)
4060{
4061 if (strcmp(nm, "C") != 0)
4062 {
Sean Huntf3907e62011-07-15 05:40:33 +00004063 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004064#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004065 if (loc == 0)
4066 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4067 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004068#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004069#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004070 lconv* lc = localeconv_l(loc.get());
4071#else
4072 lconv* lc = __localeconv_l(loc.get());
4073#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004074 if (*lc->decimal_point)
4075 __decimal_point_ = *lc->decimal_point;
4076 if (*lc->thousands_sep)
4077 __thousands_sep_ = *lc->thousands_sep;
4078 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004079 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004080 }
4081}
4082
4083// numpunct_byname<wchar_t>
4084
4085numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4086 : numpunct<wchar_t>(refs)
4087{
4088 __init(nm);
4089}
4090
4091numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4092 : numpunct<wchar_t>(refs)
4093{
4094 __init(nm.c_str());
4095}
4096
4097numpunct_byname<wchar_t>::~numpunct_byname()
4098{
4099}
4100
4101void
4102numpunct_byname<wchar_t>::__init(const char* nm)
4103{
4104 if (strcmp(nm, "C") != 0)
4105 {
Sean Huntf3907e62011-07-15 05:40:33 +00004106 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004107#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004108 if (loc == 0)
4109 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4110 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004111#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004112#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004113 lconv* lc = localeconv_l(loc.get());
4114#else
4115 lconv* lc = __localeconv_l(loc.get());
4116#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004117 if (*lc->decimal_point)
4118 __decimal_point_ = *lc->decimal_point;
4119 if (*lc->thousands_sep)
4120 __thousands_sep_ = *lc->thousands_sep;
4121 __grouping_ = lc->grouping;
4122 // locallization for truename and falsename is not available
4123 }
4124}
4125
4126// num_get helpers
4127
4128int
4129__num_get_base::__get_base(ios_base& iob)
4130{
4131 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4132 if (__basefield == ios_base::oct)
4133 return 8;
4134 else if (__basefield == ios_base::hex)
4135 return 16;
4136 else if (__basefield == 0)
4137 return 0;
4138 return 10;
4139}
4140
4141const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4142
4143void
4144__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4145 ios_base::iostate& __err)
4146{
4147 if (__grouping.size() != 0)
4148 {
4149 reverse(__g, __g_end);
4150 const char* __ig = __grouping.data();
4151 const char* __eg = __ig + __grouping.size();
4152 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4153 {
4154 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4155 {
4156 if (*__ig != *__r)
4157 {
4158 __err = ios_base::failbit;
4159 return;
4160 }
4161 }
4162 if (__eg - __ig > 1)
4163 ++__ig;
4164 }
4165 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4166 {
4167 if (*__ig < __g_end[-1] || __g_end[-1] == 0)
4168 __err = ios_base::failbit;
4169 }
4170 }
4171}
4172
4173void
4174__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4175 ios_base::fmtflags __flags)
4176{
4177 if (__flags & ios_base::showpos)
4178 *__fmtp++ = '+';
4179 if (__flags & ios_base::showbase)
4180 *__fmtp++ = '#';
4181 while(*__len)
4182 *__fmtp++ = *__len++;
4183 if ((__flags & ios_base::basefield) == ios_base::oct)
4184 *__fmtp = 'o';
4185 else if ((__flags & ios_base::basefield) == ios_base::hex)
4186 {
4187 if (__flags & ios_base::uppercase)
4188 *__fmtp = 'X';
4189 else
4190 *__fmtp = 'x';
4191 }
4192 else if (__signd)
4193 *__fmtp = 'd';
4194 else
4195 *__fmtp = 'u';
4196}
4197
4198bool
4199__num_put_base::__format_float(char* __fmtp, const char* __len,
4200 ios_base::fmtflags __flags)
4201{
4202 bool specify_precision = true;
4203 if (__flags & ios_base::showpos)
4204 *__fmtp++ = '+';
4205 if (__flags & ios_base::showpoint)
4206 *__fmtp++ = '#';
4207 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4208 bool uppercase = __flags & ios_base::uppercase;
4209 if (floatfield == (ios_base::fixed | ios_base::scientific))
4210 specify_precision = false;
4211 else
4212 {
4213 *__fmtp++ = '.';
4214 *__fmtp++ = '*';
4215 }
4216 while(*__len)
4217 *__fmtp++ = *__len++;
4218 if (floatfield == ios_base::fixed)
4219 {
4220 if (uppercase)
4221 *__fmtp = 'F';
4222 else
4223 *__fmtp = 'f';
4224 }
4225 else if (floatfield == ios_base::scientific)
4226 {
4227 if (uppercase)
4228 *__fmtp = 'E';
4229 else
4230 *__fmtp = 'e';
4231 }
4232 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4233 {
4234 if (uppercase)
4235 *__fmtp = 'A';
4236 else
4237 *__fmtp = 'a';
4238 }
4239 else
4240 {
4241 if (uppercase)
4242 *__fmtp = 'G';
4243 else
4244 *__fmtp = 'g';
4245 }
4246 return specify_precision;
4247}
4248
4249char*
4250__num_put_base::__identify_padding(char* __nb, char* __ne,
4251 const ios_base& __iob)
4252{
4253 switch (__iob.flags() & ios_base::adjustfield)
4254 {
4255 case ios_base::internal:
4256 if (__nb[0] == '-' || __nb[0] == '+')
4257 return __nb+1;
4258 if (__ne - __nb >= 2 && __nb[0] == '0'
4259 && (__nb[1] == 'x' || __nb[1] == 'X'))
4260 return __nb+2;
4261 break;
4262 case ios_base::left:
4263 return __ne;
4264 case ios_base::right:
4265 default:
4266 break;
4267 }
4268 return __nb;
4269}
4270
4271// time_get
4272
4273static
4274string*
4275init_weeks()
4276{
4277 static string weeks[14];
4278 weeks[0] = "Sunday";
4279 weeks[1] = "Monday";
4280 weeks[2] = "Tuesday";
4281 weeks[3] = "Wednesday";
4282 weeks[4] = "Thursday";
4283 weeks[5] = "Friday";
4284 weeks[6] = "Saturday";
4285 weeks[7] = "Sun";
4286 weeks[8] = "Mon";
4287 weeks[9] = "Tue";
4288 weeks[10] = "Wed";
4289 weeks[11] = "Thu";
4290 weeks[12] = "Fri";
4291 weeks[13] = "Sat";
4292 return weeks;
4293}
4294
4295static
4296wstring*
4297init_wweeks()
4298{
4299 static wstring weeks[14];
4300 weeks[0] = L"Sunday";
4301 weeks[1] = L"Monday";
4302 weeks[2] = L"Tuesday";
4303 weeks[3] = L"Wednesday";
4304 weeks[4] = L"Thursday";
4305 weeks[5] = L"Friday";
4306 weeks[6] = L"Saturday";
4307 weeks[7] = L"Sun";
4308 weeks[8] = L"Mon";
4309 weeks[9] = L"Tue";
4310 weeks[10] = L"Wed";
4311 weeks[11] = L"Thu";
4312 weeks[12] = L"Fri";
4313 weeks[13] = L"Sat";
4314 return weeks;
4315}
4316
4317template <>
4318const string*
4319__time_get_c_storage<char>::__weeks() const
4320{
4321 static const string* weeks = init_weeks();
4322 return weeks;
4323}
4324
4325template <>
4326const wstring*
4327__time_get_c_storage<wchar_t>::__weeks() const
4328{
4329 static const wstring* weeks = init_wweeks();
4330 return weeks;
4331}
4332
4333static
4334string*
4335init_months()
4336{
4337 static string months[24];
4338 months[0] = "January";
4339 months[1] = "February";
4340 months[2] = "March";
4341 months[3] = "April";
4342 months[4] = "May";
4343 months[5] = "June";
4344 months[6] = "July";
4345 months[7] = "August";
4346 months[8] = "September";
4347 months[9] = "October";
4348 months[10] = "November";
4349 months[11] = "December";
4350 months[12] = "Jan";
4351 months[13] = "Feb";
4352 months[14] = "Mar";
4353 months[15] = "Apr";
4354 months[16] = "May";
4355 months[17] = "Jun";
4356 months[18] = "Jul";
4357 months[19] = "Aug";
4358 months[20] = "Sep";
4359 months[21] = "Oct";
4360 months[22] = "Nov";
4361 months[23] = "Dec";
4362 return months;
4363}
4364
4365static
4366wstring*
4367init_wmonths()
4368{
4369 static wstring months[24];
4370 months[0] = L"January";
4371 months[1] = L"February";
4372 months[2] = L"March";
4373 months[3] = L"April";
4374 months[4] = L"May";
4375 months[5] = L"June";
4376 months[6] = L"July";
4377 months[7] = L"August";
4378 months[8] = L"September";
4379 months[9] = L"October";
4380 months[10] = L"November";
4381 months[11] = L"December";
4382 months[12] = L"Jan";
4383 months[13] = L"Feb";
4384 months[14] = L"Mar";
4385 months[15] = L"Apr";
4386 months[16] = L"May";
4387 months[17] = L"Jun";
4388 months[18] = L"Jul";
4389 months[19] = L"Aug";
4390 months[20] = L"Sep";
4391 months[21] = L"Oct";
4392 months[22] = L"Nov";
4393 months[23] = L"Dec";
4394 return months;
4395}
4396
4397template <>
4398const string*
4399__time_get_c_storage<char>::__months() const
4400{
4401 static const string* months = init_months();
4402 return months;
4403}
4404
4405template <>
4406const wstring*
4407__time_get_c_storage<wchar_t>::__months() const
4408{
4409 static const wstring* months = init_wmonths();
4410 return months;
4411}
4412
4413static
4414string*
4415init_am_pm()
4416{
4417 static string am_pm[24];
4418 am_pm[0] = "AM";
4419 am_pm[1] = "PM";
4420 return am_pm;
4421}
4422
4423static
4424wstring*
4425init_wam_pm()
4426{
4427 static wstring am_pm[24];
4428 am_pm[0] = L"AM";
4429 am_pm[1] = L"PM";
4430 return am_pm;
4431}
4432
4433template <>
4434const string*
4435__time_get_c_storage<char>::__am_pm() const
4436{
4437 static const string* am_pm = init_am_pm();
4438 return am_pm;
4439}
4440
4441template <>
4442const wstring*
4443__time_get_c_storage<wchar_t>::__am_pm() const
4444{
4445 static const wstring* am_pm = init_wam_pm();
4446 return am_pm;
4447}
4448
4449template <>
4450const string&
4451__time_get_c_storage<char>::__x() const
4452{
4453 static string s("%m/%d/%y");
4454 return s;
4455}
4456
4457template <>
4458const wstring&
4459__time_get_c_storage<wchar_t>::__x() const
4460{
4461 static wstring s(L"%m/%d/%y");
4462 return s;
4463}
4464
4465template <>
4466const string&
4467__time_get_c_storage<char>::__X() const
4468{
4469 static string s("%H:%M:%S");
4470 return s;
4471}
4472
4473template <>
4474const wstring&
4475__time_get_c_storage<wchar_t>::__X() const
4476{
4477 static wstring s(L"%H:%M:%S");
4478 return s;
4479}
4480
4481template <>
4482const string&
4483__time_get_c_storage<char>::__c() const
4484{
4485 static string s("%a %b %d %H:%M:%S %Y");
4486 return s;
4487}
4488
4489template <>
4490const wstring&
4491__time_get_c_storage<wchar_t>::__c() const
4492{
4493 static wstring s(L"%a %b %d %H:%M:%S %Y");
4494 return s;
4495}
4496
4497template <>
4498const string&
4499__time_get_c_storage<char>::__r() const
4500{
4501 static string s("%I:%M:%S %p");
4502 return s;
4503}
4504
4505template <>
4506const wstring&
4507__time_get_c_storage<wchar_t>::__r() const
4508{
4509 static wstring s(L"%I:%M:%S %p");
4510 return s;
4511}
4512
4513// time_get_byname
4514
4515__time_get::__time_get(const char* nm)
4516 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4517{
Howard Hinnantd4444702010-08-11 17:04:31 +00004518#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004519 if (__loc_ == 0)
4520 throw runtime_error("time_get_byname"
4521 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004522#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004523}
4524
4525__time_get::__time_get(const string& nm)
4526 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4527{
Howard Hinnantd4444702010-08-11 17:04:31 +00004528#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004529 if (__loc_ == 0)
4530 throw runtime_error("time_get_byname"
4531 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004532#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004533}
4534
4535__time_get::~__time_get()
4536{
4537 freelocale(__loc_);
4538}
4539
4540template <>
4541string
4542__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4543{
4544 tm t;
4545 t.tm_sec = 59;
4546 t.tm_min = 55;
4547 t.tm_hour = 23;
4548 t.tm_mday = 31;
4549 t.tm_mon = 11;
4550 t.tm_year = 161;
4551 t.tm_wday = 6;
4552 t.tm_yday = 364;
4553 t.tm_isdst = -1;
4554 char buf[100];
4555 char f[3] = {0};
4556 f[0] = '%';
4557 f[1] = fmt;
4558 size_t n = strftime_l(buf, 100, f, &t, __loc_);
4559 char* bb = buf;
4560 char* be = buf + n;
4561 string result;
4562 while (bb != be)
4563 {
4564 if (ct.is(ctype_base::space, *bb))
4565 {
4566 result.push_back(' ');
4567 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4568 ;
4569 continue;
4570 }
4571 char* w = bb;
4572 ios_base::iostate err = ios_base::goodbit;
4573 int i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
4574 ct, err, false)
4575 - this->__weeks_;
4576 if (i < 14)
4577 {
4578 result.push_back('%');
4579 if (i < 7)
4580 result.push_back('A');
4581 else
4582 result.push_back('a');
4583 bb = w;
4584 continue;
4585 }
4586 w = bb;
4587 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4588 ct, err, false)
4589 - this->__months_;
4590 if (i < 24)
4591 {
4592 result.push_back('%');
4593 if (i < 12)
4594 result.push_back('B');
4595 else
4596 result.push_back('b');
4597 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4598 result.back() = 'm';
4599 bb = w;
4600 continue;
4601 }
4602 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4603 {
4604 w = bb;
4605 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4606 ct, err, false) - this->__am_pm_;
4607 if (i < 2)
4608 {
4609 result.push_back('%');
4610 result.push_back('p');
4611 bb = w;
4612 continue;
4613 }
4614 }
4615 w = bb;
4616 if (ct.is(ctype_base::digit, *bb))
4617 {
4618 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4619 {
4620 case 6:
4621 result.push_back('%');
4622 result.push_back('w');
4623 break;
4624 case 7:
4625 result.push_back('%');
4626 result.push_back('u');
4627 break;
4628 case 11:
4629 result.push_back('%');
4630 result.push_back('I');
4631 break;
4632 case 12:
4633 result.push_back('%');
4634 result.push_back('m');
4635 break;
4636 case 23:
4637 result.push_back('%');
4638 result.push_back('H');
4639 break;
4640 case 31:
4641 result.push_back('%');
4642 result.push_back('d');
4643 break;
4644 case 55:
4645 result.push_back('%');
4646 result.push_back('M');
4647 break;
4648 case 59:
4649 result.push_back('%');
4650 result.push_back('S');
4651 break;
4652 case 61:
4653 result.push_back('%');
4654 result.push_back('y');
4655 break;
4656 case 364:
4657 result.push_back('%');
4658 result.push_back('j');
4659 break;
4660 case 2061:
4661 result.push_back('%');
4662 result.push_back('Y');
4663 break;
4664 default:
4665 for (; w != bb; ++w)
4666 result.push_back(*w);
4667 break;
4668 }
4669 continue;
4670 }
4671 if (*bb == '%')
4672 {
4673 result.push_back('%');
4674 result.push_back('%');
4675 ++bb;
4676 continue;
4677 }
4678 result.push_back(*bb);
4679 ++bb;
4680 }
4681 return result;
4682}
4683
4684template <>
4685wstring
4686__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4687{
4688 tm t;
4689 t.tm_sec = 59;
4690 t.tm_min = 55;
4691 t.tm_hour = 23;
4692 t.tm_mday = 31;
4693 t.tm_mon = 11;
4694 t.tm_year = 161;
4695 t.tm_wday = 6;
4696 t.tm_yday = 364;
4697 t.tm_isdst = -1;
4698 char buf[100];
4699 char f[3] = {0};
4700 f[0] = '%';
4701 f[1] = fmt;
4702 size_t be = strftime_l(buf, 100, f, &t, __loc_);
4703 wchar_t wbuf[100];
4704 wchar_t* wbb = wbuf;
4705 mbstate_t mb = {0};
4706 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004707#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004708 size_t i = mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4709#else
4710 size_t i = __mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4711#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004712 if (i == -1)
4713 __throw_runtime_error("locale not supported");
4714 wchar_t* wbe = wbb + i;
4715 wstring result;
4716 while (wbb != wbe)
4717 {
4718 if (ct.is(ctype_base::space, *wbb))
4719 {
4720 result.push_back(L' ');
4721 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4722 ;
4723 continue;
4724 }
4725 wchar_t* w = wbb;
4726 ios_base::iostate err = ios_base::goodbit;
4727 int i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
4728 ct, err, false)
4729 - this->__weeks_;
4730 if (i < 14)
4731 {
4732 result.push_back(L'%');
4733 if (i < 7)
4734 result.push_back(L'A');
4735 else
4736 result.push_back(L'a');
4737 wbb = w;
4738 continue;
4739 }
4740 w = wbb;
4741 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4742 ct, err, false)
4743 - this->__months_;
4744 if (i < 24)
4745 {
4746 result.push_back(L'%');
4747 if (i < 12)
4748 result.push_back(L'B');
4749 else
4750 result.push_back(L'b');
4751 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4752 result.back() = L'm';
4753 wbb = w;
4754 continue;
4755 }
4756 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4757 {
4758 w = wbb;
4759 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4760 ct, err, false) - this->__am_pm_;
4761 if (i < 2)
4762 {
4763 result.push_back(L'%');
4764 result.push_back(L'p');
4765 wbb = w;
4766 continue;
4767 }
4768 }
4769 w = wbb;
4770 if (ct.is(ctype_base::digit, *wbb))
4771 {
4772 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4773 {
4774 case 6:
4775 result.push_back(L'%');
4776 result.push_back(L'w');
4777 break;
4778 case 7:
4779 result.push_back(L'%');
4780 result.push_back(L'u');
4781 break;
4782 case 11:
4783 result.push_back(L'%');
4784 result.push_back(L'I');
4785 break;
4786 case 12:
4787 result.push_back(L'%');
4788 result.push_back(L'm');
4789 break;
4790 case 23:
4791 result.push_back(L'%');
4792 result.push_back(L'H');
4793 break;
4794 case 31:
4795 result.push_back(L'%');
4796 result.push_back(L'd');
4797 break;
4798 case 55:
4799 result.push_back(L'%');
4800 result.push_back(L'M');
4801 break;
4802 case 59:
4803 result.push_back(L'%');
4804 result.push_back(L'S');
4805 break;
4806 case 61:
4807 result.push_back(L'%');
4808 result.push_back(L'y');
4809 break;
4810 case 364:
4811 result.push_back(L'%');
4812 result.push_back(L'j');
4813 break;
4814 case 2061:
4815 result.push_back(L'%');
4816 result.push_back(L'Y');
4817 break;
4818 default:
4819 for (; w != wbb; ++w)
4820 result.push_back(*w);
4821 break;
4822 }
4823 continue;
4824 }
4825 if (ct.narrow(*wbb, 0) == '%')
4826 {
4827 result.push_back(L'%');
4828 result.push_back(L'%');
4829 ++wbb;
4830 continue;
4831 }
4832 result.push_back(*wbb);
4833 ++wbb;
4834 }
4835 return result;
4836}
4837
4838template <>
4839void
4840__time_get_storage<char>::init(const ctype<char>& ct)
4841{
4842 tm t;
4843 char buf[100];
4844 // __weeks_
4845 for (int i = 0; i < 7; ++i)
4846 {
4847 t.tm_wday = i;
4848 strftime_l(buf, 100, "%A", &t, __loc_);
4849 __weeks_[i] = buf;
4850 strftime_l(buf, 100, "%a", &t, __loc_);
4851 __weeks_[i+7] = buf;
4852 }
4853 // __months_
4854 for (int i = 0; i < 12; ++i)
4855 {
4856 t.tm_mon = i;
4857 strftime_l(buf, 100, "%B", &t, __loc_);
4858 __months_[i] = buf;
4859 strftime_l(buf, 100, "%b", &t, __loc_);
4860 __months_[i+12] = buf;
4861 }
4862 // __am_pm_
4863 t.tm_hour = 1;
4864 strftime_l(buf, 100, "%p", &t, __loc_);
4865 __am_pm_[0] = buf;
4866 t.tm_hour = 13;
4867 strftime_l(buf, 100, "%p", &t, __loc_);
4868 __am_pm_[1] = buf;
4869 __c_ = __analyze('c', ct);
4870 __r_ = __analyze('r', ct);
4871 __x_ = __analyze('x', ct);
4872 __X_ = __analyze('X', ct);
4873}
4874
4875template <>
4876void
4877__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4878{
4879 tm t = {0};
4880 char buf[100];
4881 size_t be;
4882 wchar_t wbuf[100];
4883 wchar_t* wbe;
4884 mbstate_t mb = {0};
4885 // __weeks_
4886 for (int i = 0; i < 7; ++i)
4887 {
4888 t.tm_wday = i;
4889 be = strftime_l(buf, 100, "%A", &t, __loc_);
4890 mb = mbstate_t();
4891 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004892#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004893 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4894#else
4895 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4896#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004897 if (j == -1)
4898 __throw_runtime_error("locale not supported");
4899 wbe = wbuf + j;
4900 __weeks_[i].assign(wbuf, wbe);
4901 be = strftime_l(buf, 100, "%a", &t, __loc_);
4902 mb = mbstate_t();
4903 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004904#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004905 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4906#else
4907 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4908#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004909 if (j == -1)
4910 __throw_runtime_error("locale not supported");
4911 wbe = wbuf + j;
4912 __weeks_[i+7].assign(wbuf, wbe);
4913 }
4914 // __months_
4915 for (int i = 0; i < 12; ++i)
4916 {
4917 t.tm_mon = i;
4918 be = strftime_l(buf, 100, "%B", &t, __loc_);
4919 mb = mbstate_t();
4920 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004921#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004922 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4923#else
4924 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4925#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004926 if (j == -1)
4927 __throw_runtime_error("locale not supported");
4928 wbe = wbuf + j;
4929 __months_[i].assign(wbuf, wbe);
4930 be = strftime_l(buf, 100, "%b", &t, __loc_);
4931 mb = mbstate_t();
4932 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004933#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004934 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4935#else
4936 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4937#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004938 if (j == -1)
4939 __throw_runtime_error("locale not supported");
4940 wbe = wbuf + j;
4941 __months_[i+12].assign(wbuf, wbe);
4942 }
4943 // __am_pm_
4944 t.tm_hour = 1;
4945 be = strftime_l(buf, 100, "%p", &t, __loc_);
4946 mb = mbstate_t();
4947 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004948#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004949 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4950#else
4951 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4952#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004953 if (j == -1)
4954 __throw_runtime_error("locale not supported");
4955 wbe = wbuf + j;
4956 __am_pm_[0].assign(wbuf, wbe);
4957 t.tm_hour = 13;
4958 be = strftime_l(buf, 100, "%p", &t, __loc_);
4959 mb = mbstate_t();
4960 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004961#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004962 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4963#else
4964 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4965#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004966 if (j == -1)
4967 __throw_runtime_error("locale not supported");
4968 wbe = wbuf + j;
4969 __am_pm_[1].assign(wbuf, wbe);
4970 __c_ = __analyze('c', ct);
4971 __r_ = __analyze('r', ct);
4972 __x_ = __analyze('x', ct);
4973 __X_ = __analyze('X', ct);
4974}
4975
4976template <class CharT>
4977struct _LIBCPP_HIDDEN __time_get_temp
4978 : public ctype_byname<CharT>
4979{
4980 explicit __time_get_temp(const char* nm)
4981 : ctype_byname<CharT>(nm, 1) {}
4982 explicit __time_get_temp(const string& nm)
4983 : ctype_byname<CharT>(nm, 1) {}
4984};
4985
4986template <>
4987__time_get_storage<char>::__time_get_storage(const char* __nm)
4988 : __time_get(__nm)
4989{
4990 const __time_get_temp<char> ct(__nm);
4991 init(ct);
4992}
4993
4994template <>
4995__time_get_storage<char>::__time_get_storage(const string& __nm)
4996 : __time_get(__nm)
4997{
4998 const __time_get_temp<char> ct(__nm);
4999 init(ct);
5000}
5001
5002template <>
5003__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5004 : __time_get(__nm)
5005{
5006 const __time_get_temp<wchar_t> ct(__nm);
5007 init(ct);
5008}
5009
5010template <>
5011__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5012 : __time_get(__nm)
5013{
5014 const __time_get_temp<wchar_t> ct(__nm);
5015 init(ct);
5016}
5017
5018template <>
5019time_base::dateorder
5020__time_get_storage<char>::__do_date_order() const
5021{
5022 unsigned i;
5023 for (i = 0; i < __x_.size(); ++i)
5024 if (__x_[i] == '%')
5025 break;
5026 ++i;
5027 switch (__x_[i])
5028 {
5029 case 'y':
5030 case 'Y':
5031 for (++i; i < __x_.size(); ++i)
5032 if (__x_[i] == '%')
5033 break;
5034 if (i == __x_.size())
5035 break;
5036 ++i;
5037 switch (__x_[i])
5038 {
5039 case 'm':
5040 for (++i; i < __x_.size(); ++i)
5041 if (__x_[i] == '%')
5042 break;
5043 if (i == __x_.size())
5044 break;
5045 ++i;
5046 if (__x_[i] == 'd')
5047 return time_base::ymd;
5048 break;
5049 case 'd':
5050 for (++i; i < __x_.size(); ++i)
5051 if (__x_[i] == '%')
5052 break;
5053 if (i == __x_.size())
5054 break;
5055 ++i;
5056 if (__x_[i] == 'm')
5057 return time_base::ydm;
5058 break;
5059 }
5060 break;
5061 case 'm':
5062 for (++i; i < __x_.size(); ++i)
5063 if (__x_[i] == '%')
5064 break;
5065 if (i == __x_.size())
5066 break;
5067 ++i;
5068 if (__x_[i] == 'd')
5069 {
5070 for (++i; i < __x_.size(); ++i)
5071 if (__x_[i] == '%')
5072 break;
5073 if (i == __x_.size())
5074 break;
5075 ++i;
5076 if (__x_[i] == 'y' || __x_[i] == 'Y')
5077 return time_base::mdy;
5078 break;
5079 }
5080 break;
5081 case 'd':
5082 for (++i; i < __x_.size(); ++i)
5083 if (__x_[i] == '%')
5084 break;
5085 if (i == __x_.size())
5086 break;
5087 ++i;
5088 if (__x_[i] == 'm')
5089 {
5090 for (++i; i < __x_.size(); ++i)
5091 if (__x_[i] == '%')
5092 break;
5093 if (i == __x_.size())
5094 break;
5095 ++i;
5096 if (__x_[i] == 'y' || __x_[i] == 'Y')
5097 return time_base::dmy;
5098 break;
5099 }
5100 break;
5101 }
5102 return time_base::no_order;
5103}
5104
5105template <>
5106time_base::dateorder
5107__time_get_storage<wchar_t>::__do_date_order() const
5108{
5109 unsigned i;
5110 for (i = 0; i < __x_.size(); ++i)
5111 if (__x_[i] == L'%')
5112 break;
5113 ++i;
5114 switch (__x_[i])
5115 {
5116 case L'y':
5117 case L'Y':
5118 for (++i; i < __x_.size(); ++i)
5119 if (__x_[i] == L'%')
5120 break;
5121 if (i == __x_.size())
5122 break;
5123 ++i;
5124 switch (__x_[i])
5125 {
5126 case L'm':
5127 for (++i; i < __x_.size(); ++i)
5128 if (__x_[i] == L'%')
5129 break;
5130 if (i == __x_.size())
5131 break;
5132 ++i;
5133 if (__x_[i] == L'd')
5134 return time_base::ymd;
5135 break;
5136 case L'd':
5137 for (++i; i < __x_.size(); ++i)
5138 if (__x_[i] == L'%')
5139 break;
5140 if (i == __x_.size())
5141 break;
5142 ++i;
5143 if (__x_[i] == L'm')
5144 return time_base::ydm;
5145 break;
5146 }
5147 break;
5148 case L'm':
5149 for (++i; i < __x_.size(); ++i)
5150 if (__x_[i] == L'%')
5151 break;
5152 if (i == __x_.size())
5153 break;
5154 ++i;
5155 if (__x_[i] == L'd')
5156 {
5157 for (++i; i < __x_.size(); ++i)
5158 if (__x_[i] == L'%')
5159 break;
5160 if (i == __x_.size())
5161 break;
5162 ++i;
5163 if (__x_[i] == L'y' || __x_[i] == L'Y')
5164 return time_base::mdy;
5165 break;
5166 }
5167 break;
5168 case L'd':
5169 for (++i; i < __x_.size(); ++i)
5170 if (__x_[i] == L'%')
5171 break;
5172 if (i == __x_.size())
5173 break;
5174 ++i;
5175 if (__x_[i] == L'm')
5176 {
5177 for (++i; i < __x_.size(); ++i)
5178 if (__x_[i] == L'%')
5179 break;
5180 if (i == __x_.size())
5181 break;
5182 ++i;
5183 if (__x_[i] == L'y' || __x_[i] == L'Y')
5184 return time_base::dmy;
5185 break;
5186 }
5187 break;
5188 }
5189 return time_base::no_order;
5190}
5191
5192// time_put
5193
5194__time_put::__time_put(const char* nm)
5195 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5196{
Howard Hinnantd4444702010-08-11 17:04:31 +00005197#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005198 if (__loc_ == 0)
5199 throw runtime_error("time_put_byname"
5200 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005201#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005202}
5203
5204__time_put::__time_put(const string& nm)
5205 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5206{
Howard Hinnantd4444702010-08-11 17:04:31 +00005207#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005208 if (__loc_ == 0)
5209 throw runtime_error("time_put_byname"
5210 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005211#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005212}
5213
5214__time_put::~__time_put()
5215{
5216 if (__loc_)
5217 freelocale(__loc_);
5218}
5219
5220void
5221__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5222 char __fmt, char __mod) const
5223{
5224 char fmt[] = {'%', __fmt, __mod, 0};
5225 if (__mod != 0)
5226 swap(fmt[1], fmt[2]);
5227 size_t n = strftime_l(__nb, __ne-__nb, fmt, __tm, __loc_);
5228 __ne = __nb + n;
5229}
5230
5231void
5232__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5233 char __fmt, char __mod) const
5234{
5235 char __nar[100];
5236 char* __ne = __nar + 100;
5237 __do_put(__nar, __ne, __tm, __fmt, __mod);
5238 mbstate_t mb = {0};
5239 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005240#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005241 size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5242#else
5243 size_t j = __mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5244#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005245 if (j == -1)
5246 __throw_runtime_error("locale not supported");
5247 __we = __wb + j;
5248}
5249
5250// moneypunct_byname
5251
5252static
5253void
5254__init_pat(money_base::pattern& pat, char cs_precedes, char sep_by_space, char sign_posn)
5255{
5256 const char sign = static_cast<char>(money_base::sign);
5257 const char space = static_cast<char>(money_base::space);
5258 const char none = static_cast<char>(money_base::none);
5259 const char symbol = static_cast<char>(money_base::symbol);
5260 const char value = static_cast<char>(money_base::value);
5261 switch (cs_precedes)
5262 {
5263 case 0:
5264 switch (sign_posn)
5265 {
5266 case 0:
5267 pat.field[0] = sign;
5268 pat.field[1] = value;
5269 pat.field[3] = symbol;
5270 switch (sep_by_space)
5271 {
5272 case 0:
5273 pat.field[2] = none;
5274 return;
5275 case 1:
5276 case 2:
5277 pat.field[2] = space;
5278 return;
5279 default:
5280 break;
5281 }
5282 break;
5283 case 1:
5284 pat.field[0] = sign;
5285 pat.field[3] = symbol;
5286 switch (sep_by_space)
5287 {
5288 case 0:
5289 pat.field[1] = value;
5290 pat.field[2] = none;
5291 return;
5292 case 1:
5293 pat.field[1] = value;
5294 pat.field[2] = space;
5295 return;
5296 case 2:
5297 pat.field[1] = space;
5298 pat.field[2] = value;
5299 return;
5300 default:
5301 break;
5302 }
5303 break;
5304 case 2:
5305 pat.field[0] = value;
5306 pat.field[3] = sign;
5307 switch (sep_by_space)
5308 {
5309 case 0:
5310 pat.field[1] = none;
5311 pat.field[2] = symbol;
5312 return;
5313 case 1:
5314 pat.field[1] = space;
5315 pat.field[2] = symbol;
5316 return;
5317 case 2:
5318 pat.field[1] = symbol;
5319 pat.field[2] = space;
5320 return;
5321 default:
5322 break;
5323 }
5324 break;
5325 case 3:
5326 pat.field[0] = value;
5327 pat.field[3] = symbol;
5328 switch (sep_by_space)
5329 {
5330 case 0:
5331 pat.field[1] = none;
5332 pat.field[2] = sign;
5333 return;
5334 case 1:
5335 pat.field[1] = space;
5336 pat.field[2] = sign;
5337 return;
5338 case 2:
5339 pat.field[1] = sign;
5340 pat.field[2] = space;
5341 return;
5342 default:
5343 break;
5344 }
5345 break;
5346 case 4:
5347 pat.field[0] = value;
5348 pat.field[3] = sign;
5349 switch (sep_by_space)
5350 {
5351 case 0:
5352 pat.field[1] = none;
5353 pat.field[2] = symbol;
5354 return;
5355 case 1:
5356 pat.field[1] = space;
5357 pat.field[2] = symbol;
5358 return;
5359 case 2:
5360 pat.field[1] = symbol;
5361 pat.field[2] = space;
5362 return;
5363 default:
5364 break;
5365 }
5366 break;
5367 default:
5368 break;
5369 }
5370 break;
5371 case 1:
5372 switch (sign_posn)
5373 {
5374 case 0:
5375 pat.field[0] = sign;
5376 pat.field[1] = symbol;
5377 pat.field[3] = value;
5378 switch (sep_by_space)
5379 {
5380 case 0:
5381 pat.field[2] = none;
5382 return;
5383 case 1:
5384 case 2:
5385 pat.field[2] = space;
5386 return;
5387 default:
5388 break;
5389 }
5390 break;
5391 case 1:
5392 pat.field[0] = sign;
5393 pat.field[3] = value;
5394 switch (sep_by_space)
5395 {
5396 case 0:
5397 pat.field[1] = symbol;
5398 pat.field[2] = none;
5399 return;
5400 case 1:
5401 pat.field[1] = symbol;
5402 pat.field[2] = space;
5403 return;
5404 case 2:
5405 pat.field[1] = space;
5406 pat.field[2] = symbol;
5407 return;
5408 default:
5409 break;
5410 }
5411 break;
5412 case 2:
5413 pat.field[0] = symbol;
5414 pat.field[3] = sign;
5415 switch (sep_by_space)
5416 {
5417 case 0:
5418 pat.field[1] = none;
5419 pat.field[2] = value;
5420 return;
5421 case 1:
5422 pat.field[1] = space;
5423 pat.field[2] = value;
5424 return;
5425 case 2:
5426 pat.field[1] = value;
5427 pat.field[2] = space;
5428 return;
5429 default:
5430 break;
5431 }
5432 break;
5433 case 3:
5434 pat.field[0] = sign;
5435 pat.field[3] = value;
5436 switch (sep_by_space)
5437 {
5438 case 0:
5439 pat.field[1] = symbol;
5440 pat.field[2] = none;
5441 return;
5442 case 1:
5443 pat.field[1] = symbol;
5444 pat.field[2] = space;
5445 return;
5446 case 2:
5447 pat.field[1] = space;
5448 pat.field[2] = symbol;
5449 return;
5450 default:
5451 break;
5452 }
5453 break;
5454 case 4:
5455 pat.field[0] = symbol;
5456 pat.field[3] = value;
5457 switch (sep_by_space)
5458 {
5459 case 0:
5460 pat.field[1] = sign;
5461 pat.field[2] = none;
5462 return;
5463 case 1:
5464 pat.field[1] = sign;
5465 pat.field[2] = space;
5466 return;
5467 case 2:
5468 pat.field[1] = space;
5469 pat.field[2] = sign;
5470 return;
5471 default:
5472 break;
5473 }
5474 break;
5475 default:
5476 break;
5477 }
5478 break;
5479 default:
5480 break;
5481 }
5482 pat.field[0] = symbol;
5483 pat.field[1] = sign;
5484 pat.field[2] = none;
5485 pat.field[3] = value;
5486}
5487
5488template<>
5489void
5490moneypunct_byname<char, false>::init(const char* nm)
5491{
5492 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005493 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005494#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005495 if (loc == 0)
5496 throw runtime_error("moneypunct_byname"
5497 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005498#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005499#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005500 lconv* lc = localeconv_l(loc.get());
5501#else
5502 lconv* lc = __localeconv_l(loc.get());
5503#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005504 if (*lc->mon_decimal_point)
5505 __decimal_point_ = *lc->mon_decimal_point;
5506 else
5507 __decimal_point_ = base::do_decimal_point();
5508 if (*lc->mon_thousands_sep)
5509 __thousands_sep_ = *lc->mon_thousands_sep;
5510 else
5511 __thousands_sep_ = base::do_thousands_sep();
5512 __grouping_ = lc->mon_grouping;
5513 __curr_symbol_ = lc->currency_symbol;
5514 if (lc->frac_digits != CHAR_MAX)
5515 __frac_digits_ = lc->frac_digits;
5516 else
5517 __frac_digits_ = base::do_frac_digits();
5518 if (lc->p_sign_posn == 0)
5519 __positive_sign_ = "()";
5520 else
5521 __positive_sign_ = lc->positive_sign;
5522 if (lc->n_sign_posn == 0)
5523 __negative_sign_ = "()";
5524 else
5525 __negative_sign_ = lc->negative_sign;
5526 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5527 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5528}
5529
5530template<>
5531void
5532moneypunct_byname<char, true>::init(const char* nm)
5533{
5534 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005535 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005536#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005537 if (loc == 0)
5538 throw runtime_error("moneypunct_byname"
5539 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005540#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005541#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005542 lconv* lc = localeconv_l(loc.get());
5543#else
5544 lconv* lc = __localeconv_l(loc.get());
5545#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005546 if (*lc->mon_decimal_point)
5547 __decimal_point_ = *lc->mon_decimal_point;
5548 else
5549 __decimal_point_ = base::do_decimal_point();
5550 if (*lc->mon_thousands_sep)
5551 __thousands_sep_ = *lc->mon_thousands_sep;
5552 else
5553 __thousands_sep_ = base::do_thousands_sep();
5554 __grouping_ = lc->mon_grouping;
5555 __curr_symbol_ = lc->int_curr_symbol;
5556 if (lc->int_frac_digits != CHAR_MAX)
5557 __frac_digits_ = lc->int_frac_digits;
5558 else
5559 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005560#if _WIN32
5561 if (lc->p_sign_posn == 0)
5562#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005563 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005564#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005565 __positive_sign_ = "()";
5566 else
5567 __positive_sign_ = lc->positive_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005568#if _WIN32
5569 if(lc->n_sign_posn == 0)
5570#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005571 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005572#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005573 __negative_sign_ = "()";
5574 else
5575 __negative_sign_ = lc->negative_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005576#if _WIN32
5577 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5578 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5579#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005580 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5581 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005582#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005583}
5584
5585template<>
5586void
5587moneypunct_byname<wchar_t, false>::init(const char* nm)
5588{
5589 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005590 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005591#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005592 if (loc == 0)
5593 throw runtime_error("moneypunct_byname"
5594 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005595#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005596#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005597 lconv* lc = localeconv_l(loc.get());
5598#else
5599 lconv* lc = __localeconv_l(loc.get());
5600#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005601 if (*lc->mon_decimal_point)
5602 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5603 else
5604 __decimal_point_ = base::do_decimal_point();
5605 if (*lc->mon_thousands_sep)
5606 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5607 else
5608 __thousands_sep_ = base::do_thousands_sep();
5609 __grouping_ = lc->mon_grouping;
5610 wchar_t wbuf[100];
5611 mbstate_t mb = {0};
5612 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005613#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005614 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5615#else
5616 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5617#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005618 if (j == -1)
5619 __throw_runtime_error("locale not supported");
5620 wchar_t* wbe = wbuf + j;
5621 __curr_symbol_.assign(wbuf, wbe);
5622 if (lc->frac_digits != CHAR_MAX)
5623 __frac_digits_ = lc->frac_digits;
5624 else
5625 __frac_digits_ = base::do_frac_digits();
5626 if (lc->p_sign_posn == 0)
5627 __positive_sign_ = L"()";
5628 else
5629 {
5630 mb = mbstate_t();
5631 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005632#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005633 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5634#else
5635 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5636#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005637 if (j == -1)
5638 __throw_runtime_error("locale not supported");
5639 wbe = wbuf + j;
5640 __positive_sign_.assign(wbuf, wbe);
5641 }
5642 if (lc->n_sign_posn == 0)
5643 __negative_sign_ = L"()";
5644 else
5645 {
5646 mb = mbstate_t();
5647 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005648#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005649 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5650#else
5651 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5652#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005653 if (j == -1)
5654 __throw_runtime_error("locale not supported");
5655 wbe = wbuf + j;
5656 __negative_sign_.assign(wbuf, wbe);
5657 }
5658 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5659 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5660}
5661
5662template<>
5663void
5664moneypunct_byname<wchar_t, true>::init(const char* nm)
5665{
5666 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005667 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005668#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005669 if (loc == 0)
5670 throw runtime_error("moneypunct_byname"
5671 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005672#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005673#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005674 lconv* lc = localeconv_l(loc.get());
5675#else
5676 lconv* lc = __localeconv_l(loc.get());
5677#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005678 if (*lc->mon_decimal_point)
5679 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5680 else
5681 __decimal_point_ = base::do_decimal_point();
5682 if (*lc->mon_thousands_sep)
5683 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5684 else
5685 __thousands_sep_ = base::do_thousands_sep();
5686 __grouping_ = lc->mon_grouping;
5687 wchar_t wbuf[100];
5688 mbstate_t mb = {0};
5689 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005690#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005691 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5692#else
5693 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5694#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005695 if (j == -1)
5696 __throw_runtime_error("locale not supported");
5697 wchar_t* wbe = wbuf + j;
5698 __curr_symbol_.assign(wbuf, wbe);
5699 if (lc->int_frac_digits != CHAR_MAX)
5700 __frac_digits_ = lc->int_frac_digits;
5701 else
5702 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005703#if _WIN32
5704 if (lc->p_sign_posn == 0)
5705#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005706 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005707#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005708 __positive_sign_ = L"()";
5709 else
5710 {
5711 mb = mbstate_t();
5712 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005713#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005714 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5715#else
5716 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5717#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005718 if (j == -1)
5719 __throw_runtime_error("locale not supported");
5720 wbe = wbuf + j;
5721 __positive_sign_.assign(wbuf, wbe);
5722 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005723#if _WIN32
5724 if (lc->n_sign_posn == 0)
5725#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005726 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005727#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005728 __negative_sign_ = L"()";
5729 else
5730 {
5731 mb = mbstate_t();
5732 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005733#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005734 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5735#else
5736 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5737#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005738 if (j == -1)
5739 __throw_runtime_error("locale not supported");
5740 wbe = wbuf + j;
5741 __negative_sign_.assign(wbuf, wbe);
5742 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005743#if _WIN32
5744 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5745 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5746#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005747 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5748 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005749#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005750}
5751
5752void __do_nothing(void*) {}
5753
5754void __throw_runtime_error(const char* msg)
5755{
Howard Hinnantd4444702010-08-11 17:04:31 +00005756#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005757 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00005758#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005759}
5760
5761template class collate<char>;
5762template class collate<wchar_t>;
5763
5764template class num_get<char>;
5765template class num_get<wchar_t>;
5766
5767template class __num_get<char>;
5768template class __num_get<wchar_t>;
5769
5770template class num_put<char>;
5771template class num_put<wchar_t>;
5772
5773template class __num_put<char>;
5774template class __num_put<wchar_t>;
5775
5776template class time_get<char>;
5777template class time_get<wchar_t>;
5778
5779template class time_get_byname<char>;
5780template class time_get_byname<wchar_t>;
5781
5782template class time_put<char>;
5783template class time_put<wchar_t>;
5784
5785template class time_put_byname<char>;
5786template class time_put_byname<wchar_t>;
5787
5788template class moneypunct<char, false>;
5789template class moneypunct<char, true>;
5790template class moneypunct<wchar_t, false>;
5791template class moneypunct<wchar_t, true>;
5792
5793template class moneypunct_byname<char, false>;
5794template class moneypunct_byname<char, true>;
5795template class moneypunct_byname<wchar_t, false>;
5796template class moneypunct_byname<wchar_t, true>;
5797
5798template class money_get<char>;
5799template class money_get<wchar_t>;
5800
5801template class __money_get<char>;
5802template class __money_get<wchar_t>;
5803
5804template class money_put<char>;
5805template class money_put<wchar_t>;
5806
5807template class __money_put<char>;
5808template class __money_put<wchar_t>;
5809
5810template class messages<char>;
5811template class messages<wchar_t>;
5812
5813template class messages_byname<char>;
5814template class messages_byname<wchar_t>;
5815
5816template class codecvt_byname<char, char, mbstate_t>;
5817template class codecvt_byname<wchar_t, char, mbstate_t>;
5818template class codecvt_byname<char16_t, char, mbstate_t>;
5819template class codecvt_byname<char32_t, char, mbstate_t>;
5820
5821template class __vector_base_common<true>;
5822
5823_LIBCPP_END_NAMESPACE_STD