blob: c75a1542d9d0f68ae6deb4c079d1ae9dc91584c4 [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
Howard Hinnant14fa9f92011-09-29 20:33:10 +000023#include <support/win32/locale_win32.h>
Howard Hinnant6cd05ee2011-09-23 16:11:27 +000024#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 Hinnant3c466fc2011-09-29 13:33:15 +0000725#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
726 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
727#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000728 return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000729#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000730 return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000731#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000732}
733
734const wchar_t*
735ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
736{
737 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000738#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
739 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
740#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000741 *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low]
742 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000743#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000744 *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000745#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000746 return low;
747}
748
749wchar_t
750ctype<wchar_t>::do_tolower(char_type c) const
751{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000752#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
753 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
754#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000755 return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000756#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000757 return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000758#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000759}
760
761const wchar_t*
762ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
763{
764 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000765#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
766 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
767#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000768 *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low]
769 : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000770#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000771 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000772#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000773 return low;
774}
775
776wchar_t
777ctype<wchar_t>::do_widen(char c) const
778{
779 return c;
780}
781
782const char*
783ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
784{
785 for (; low != high; ++low, ++dest)
786 *dest = *low;
787 return low;
788}
789
790char
791ctype<wchar_t>::do_narrow(char_type c, char dfault) const
792{
793 if (isascii(c))
794 return static_cast<char>(c);
795 return dfault;
796}
797
798const wchar_t*
799ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
800{
801 for (; low != high; ++low, ++dest)
802 if (isascii(*low))
803 *dest = *low;
804 else
805 *dest = dfault;
806 return low;
807}
808
809// template <> class ctype<char>;
810
811locale::id ctype<char>::id;
812
813ctype<char>::ctype(const mask* tab, bool del, size_t refs)
814 : locale::facet(refs),
815 __tab_(tab),
816 __del_(del)
817{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000818 if (__tab_ == 0)
819 __tab_ = classic_table();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000820}
821
822ctype<char>::~ctype()
823{
824 if (__tab_ && __del_)
825 delete [] __tab_;
826}
827
828char
829ctype<char>::do_toupper(char_type c) const
830{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000831#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
832 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
833#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000834 return isascii(c) ? __classic_upper_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000835#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000836 return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000837#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000838}
839
840const char*
841ctype<char>::do_toupper(char_type* low, const char_type* high) const
842{
843 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000844#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
845 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
846#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000847 *low = isascii(*low) ? __classic_upper_table()[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000848#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000849 *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000850#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000851 return low;
852}
853
854char
855ctype<char>::do_tolower(char_type c) const
856{
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000857#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
858 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
859#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000860 return isascii(c) ? __classic_lower_table()[c] : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000861#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000862 return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c;
Sean Hunte59f7242011-07-09 01:09:31 +0000863#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000864}
865
866const char*
867ctype<char>::do_tolower(char_type* low, const char_type* high) const
868{
869 for (; low != high; ++low)
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000870#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE
871 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
872#elif defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000873 *low = isascii(*low) ? __classic_lower_table()[*low] : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000874#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000875 *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low;
Sean Hunte59f7242011-07-09 01:09:31 +0000876#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000877 return low;
878}
879
880char
881ctype<char>::do_widen(char c) const
882{
883 return c;
884}
885
886const char*
887ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
888{
889 for (; low != high; ++low, ++dest)
890 *dest = *low;
891 return low;
892}
893
894char
895ctype<char>::do_narrow(char_type c, char dfault) const
896{
897 if (isascii(c))
898 return static_cast<char>(c);
899 return dfault;
900}
901
902const char*
903ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
904{
905 for (; low != high; ++low, ++dest)
906 if (isascii(*low))
907 *dest = *low;
908 else
909 *dest = dfault;
910 return low;
911}
912
913const ctype<char>::mask*
Howard Hinnantc9834542011-05-31 15:34:58 +0000914ctype<char>::classic_table() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000915{
David Chisnallc512df12011-09-21 08:39:44 +0000916#if defined(__APPLE__) || defined(__FreeBSD__)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000917 return _DefaultRuneLocale.__runetype;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000918#elif defined(__GLIBC__)
919 return __cloc()->__ctype_b;
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000920#elif _WIN32
921 return _ctype+1; // internal ctype mask table defined in msvcrt.dll
David Chisnallc512df12011-09-21 08:39:44 +0000922// This is assumed to be safe, which is a nonsense assumption because we're
923// going to end up dereferencing it later...
Sean Hunt62a6ac32011-07-09 00:56:23 +0000924#else
925 return NULL;
926#endif
927}
928
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000929#if defined(__GLIBC__)
Sean Hunt62a6ac32011-07-09 00:56:23 +0000930const int*
931ctype<char>::__classic_lower_table() _NOEXCEPT
932{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000933 return __cloc()->__ctype_tolower;
Sean Hunt62a6ac32011-07-09 00:56:23 +0000934}
935
936const int*
937ctype<char>::__classic_upper_table() _NOEXCEPT
938{
Sean Hunt62a6ac32011-07-09 00:56:23 +0000939 return __cloc()->__ctype_toupper;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000940}
Howard Hinnant3c466fc2011-09-29 13:33:15 +0000941#endif // __GLIBC__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000942
943// template <> class ctype_byname<char>
944
945ctype_byname<char>::ctype_byname(const char* name, size_t refs)
946 : ctype<char>(0, false, refs),
947 __l(newlocale(LC_ALL_MASK, name, 0))
948{
Howard Hinnantd4444702010-08-11 17:04:31 +0000949#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000950 if (__l == 0)
951 throw runtime_error("ctype_byname<char>::ctype_byname"
952 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000953#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000954}
955
956ctype_byname<char>::ctype_byname(const string& name, size_t refs)
957 : ctype<char>(0, false, refs),
958 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
959{
Howard Hinnantd4444702010-08-11 17:04:31 +0000960#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000961 if (__l == 0)
962 throw runtime_error("ctype_byname<char>::ctype_byname"
963 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000964#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000965}
966
967ctype_byname<char>::~ctype_byname()
968{
969 freelocale(__l);
970}
971
972char
973ctype_byname<char>::do_toupper(char_type c) const
974{
975 return toupper_l(c, __l);
976}
977
978const char*
979ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
980{
981 for (; low != high; ++low)
982 *low = toupper_l(*low, __l);
983 return low;
984}
985
986char
987ctype_byname<char>::do_tolower(char_type c) const
988{
989 return tolower_l(c, __l);
990}
991
992const char*
993ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
994{
995 for (; low != high; ++low)
996 *low = tolower_l(*low, __l);
997 return low;
998}
999
1000// template <> class ctype_byname<wchar_t>
1001
1002ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
1003 : ctype<wchar_t>(refs),
1004 __l(newlocale(LC_ALL_MASK, name, 0))
1005{
Howard Hinnantd4444702010-08-11 17:04:31 +00001006#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001007 if (__l == 0)
1008 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1009 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001010#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001011}
1012
1013ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
1014 : ctype<wchar_t>(refs),
1015 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
1016{
Howard Hinnantd4444702010-08-11 17:04:31 +00001017#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001018 if (__l == 0)
1019 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
1020 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001021#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001022}
1023
1024ctype_byname<wchar_t>::~ctype_byname()
1025{
1026 freelocale(__l);
1027}
1028
1029bool
1030ctype_byname<wchar_t>::do_is(mask m, char_type c) const
1031{
Sean Hunt6f0342c2011-07-09 03:40:04 +00001032#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001033 return static_cast<bool>(iswctype_l(c, m, __l));
Sean Hunt6f0342c2011-07-09 03:40:04 +00001034#else
Howard Hinnant3c466fc2011-09-29 13:33:15 +00001035 bool result = true;
1036 if (m & space && !iswspace_l(c, __l)) result = false;
1037 if (m & print && !iswprint_l(c, __l)) result = false;
1038 if (m & cntrl && !iswcntrl_l(c, __l)) result = false;
1039 if (m & upper && !iswupper_l(c, __l)) result = false;
1040 if (m & lower && !iswlower_l(c, __l)) result = false;
1041 if (m & alpha && !iswalpha_l(c, __l)) result = false;
1042 if (m & digit && !iswdigit_l(c, __l)) result = false;
1043 if (m & punct && !iswpunct_l(c, __l)) result = false;
1044 if (m & xdigit && !iswxdigit_l(c, __l)) result = false;
1045 if (m & blank && !iswblank_l(c, __l)) result = false;
1046 return result;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001047#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001048}
1049
1050const wchar_t*
1051ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
1052{
1053 for (; low != high; ++low, ++vec)
1054 {
1055 if (isascii(*low))
Sean Hunt62a6ac32011-07-09 00:56:23 +00001056 *vec = static_cast<mask>(ctype<char>::classic_table()[*low]);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001057 else
1058 {
1059 *vec = 0;
1060 if (iswspace_l(*low, __l))
1061 *vec |= space;
1062 if (iswprint_l(*low, __l))
1063 *vec |= print;
1064 if (iswcntrl_l(*low, __l))
1065 *vec |= cntrl;
1066 if (iswupper_l(*low, __l))
1067 *vec |= upper;
1068 if (iswlower_l(*low, __l))
1069 *vec |= lower;
1070 if (iswalpha_l(*low, __l))
1071 *vec |= alpha;
1072 if (iswdigit_l(*low, __l))
1073 *vec |= digit;
1074 if (iswpunct_l(*low, __l))
1075 *vec |= punct;
1076 if (iswxdigit_l(*low, __l))
1077 *vec |= xdigit;
1078 }
1079 }
1080 return low;
1081}
1082
1083const wchar_t*
1084ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
1085{
1086 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001087 {
1088#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001089 if (iswctype_l(*low, m, __l))
1090 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001091#else
1092 if (m & space && !iswspace_l(*low, __l)) continue;
1093 if (m & print && !iswprint_l(*low, __l)) continue;
1094 if (m & cntrl && !iswcntrl_l(*low, __l)) continue;
1095 if (m & upper && !iswupper_l(*low, __l)) continue;
1096 if (m & lower && !iswlower_l(*low, __l)) continue;
1097 if (m & alpha && !iswalpha_l(*low, __l)) continue;
1098 if (m & digit && !iswdigit_l(*low, __l)) continue;
1099 if (m & punct && !iswpunct_l(*low, __l)) continue;
1100 if (m & xdigit && !iswxdigit_l(*low, __l)) continue;
1101 if (m & blank && !iswblank_l(*low, __l)) continue;
1102 break;
1103#endif
1104 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001105 return low;
1106}
1107
1108const wchar_t*
1109ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
1110{
1111 for (; low != high; ++low)
Sean Hunt6f0342c2011-07-09 03:40:04 +00001112 {
1113#ifdef _LIBCPP_WCTYPE_IS_MASK
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001114 if (!iswctype_l(*low, m, __l))
1115 break;
Sean Hunt6f0342c2011-07-09 03:40:04 +00001116#else
1117 if (m & space && iswspace_l(*low, __l)) continue;
1118 if (m & print && iswprint_l(*low, __l)) continue;
1119 if (m & cntrl && iswcntrl_l(*low, __l)) continue;
1120 if (m & upper && iswupper_l(*low, __l)) continue;
1121 if (m & lower && iswlower_l(*low, __l)) continue;
1122 if (m & alpha && iswalpha_l(*low, __l)) continue;
1123 if (m & digit && iswdigit_l(*low, __l)) continue;
1124 if (m & punct && iswpunct_l(*low, __l)) continue;
1125 if (m & xdigit && iswxdigit_l(*low, __l)) continue;
1126 if (m & blank && iswblank_l(*low, __l)) continue;
1127 break;
1128#endif
1129 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001130 return low;
1131}
1132
1133wchar_t
1134ctype_byname<wchar_t>::do_toupper(char_type c) const
1135{
1136 return towupper_l(c, __l);
1137}
1138
1139const wchar_t*
1140ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1141{
1142 for (; low != high; ++low)
1143 *low = towupper_l(*low, __l);
1144 return low;
1145}
1146
1147wchar_t
1148ctype_byname<wchar_t>::do_tolower(char_type c) const
1149{
1150 return towlower_l(c, __l);
1151}
1152
1153const wchar_t*
1154ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1155{
1156 for (; low != high; ++low)
1157 *low = towlower_l(*low, __l);
1158 return low;
1159}
1160
1161wchar_t
1162ctype_byname<wchar_t>::do_widen(char c) const
1163{
Howard Hinnant866569b2011-09-28 23:39:33 +00001164#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001165 return btowc_l(c, __l);
1166#else
1167 return __btowc_l(c, __l);
1168#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001169}
1170
1171const char*
1172ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1173{
1174 for (; low != high; ++low, ++dest)
Howard Hinnant866569b2011-09-28 23:39:33 +00001175#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001176 *dest = btowc_l(*low, __l);
1177#else
1178 *dest = __btowc_l(*low, __l);
1179#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001180 return low;
1181}
1182
1183char
1184ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1185{
Howard Hinnant866569b2011-09-28 23:39:33 +00001186#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001187 int r = wctob_l(c, __l);
1188#else
1189 int r = __wctob_l(c, __l);
1190#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001191 return r != WEOF ? static_cast<char>(r) : dfault;
1192}
1193
1194const wchar_t*
1195ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1196{
1197 for (; low != high; ++low, ++dest)
1198 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001199#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001200 int r = wctob_l(*low, __l);
1201#else
1202 int r = __wctob_l(*low, __l);
1203#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001204 *dest = r != WEOF ? static_cast<char>(r) : dfault;
1205 }
1206 return low;
1207}
1208
1209// template <> class codecvt<char, char, mbstate_t>
1210
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001211locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001212
1213codecvt<char, char, mbstate_t>::~codecvt()
1214{
1215}
1216
1217codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001218codecvt<char, char, mbstate_t>::do_out(state_type&,
1219 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001220 extern_type* to, extern_type*, extern_type*& to_nxt) const
1221{
1222 frm_nxt = frm;
1223 to_nxt = to;
1224 return noconv;
1225}
1226
1227codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001228codecvt<char, char, mbstate_t>::do_in(state_type&,
1229 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001230 intern_type* to, intern_type*, intern_type*& to_nxt) const
1231{
1232 frm_nxt = frm;
1233 to_nxt = to;
1234 return noconv;
1235}
1236
1237codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001238codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001239 extern_type* to, extern_type*, extern_type*& to_nxt) const
1240{
1241 to_nxt = to;
1242 return noconv;
1243}
1244
1245int
Howard Hinnantc9834542011-05-31 15:34:58 +00001246codecvt<char, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001247{
1248 return 1;
1249}
1250
1251bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001252codecvt<char, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001253{
1254 return true;
1255}
1256
1257int
1258codecvt<char, char, mbstate_t>::do_length(state_type&,
1259 const extern_type* frm, const extern_type* end, size_t mx) const
1260{
1261 return static_cast<int>(min<size_t>(mx, end-frm));
1262}
1263
1264int
Howard Hinnantc9834542011-05-31 15:34:58 +00001265codecvt<char, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001266{
1267 return 1;
1268}
1269
1270// template <> class codecvt<wchar_t, char, mbstate_t>
1271
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001272locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001273
1274codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1275 : locale::facet(refs),
1276 __l(0)
1277{
1278}
1279
1280codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1281 : locale::facet(refs),
1282 __l(newlocale(LC_ALL_MASK, nm, 0))
1283{
Howard Hinnantd4444702010-08-11 17:04:31 +00001284#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001285 if (__l == 0)
1286 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1287 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001288#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001289}
1290
1291codecvt<wchar_t, char, mbstate_t>::~codecvt()
1292{
1293 if (__l != 0)
1294 freelocale(__l);
1295}
1296
1297codecvt<wchar_t, char, mbstate_t>::result
1298codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001299 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001300 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1301{
1302 // look for first internal null in frm
1303 const intern_type* fend = frm;
1304 for (; fend != frm_end; ++fend)
1305 if (*fend == 0)
1306 break;
1307 // loop over all null-terminated sequences in frm
1308 to_nxt = to;
1309 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1310 {
1311 // save state in case needed to reover to_nxt on error
1312 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001313#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001314 size_t n = wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1315#else
1316 size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1317#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001318 if (n == size_t(-1))
1319 {
1320 // need to recover to_nxt
1321 for (to_nxt = to; frm != frm_nxt; ++frm)
1322 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001323#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001324 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1325#else
1326 n = __wcrtomb_l(to_nxt, *frm, &save_state, __l);
1327#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001328 if (n == size_t(-1))
1329 break;
1330 to_nxt += n;
1331 }
1332 frm_nxt = frm;
1333 return error;
1334 }
1335 if (n == 0)
1336 return partial;
1337 to_nxt += n;
1338 if (to_nxt == to_end)
1339 break;
1340 if (fend != frm_end) // set up next null terminated sequence
1341 {
1342 // Try to write the terminating null
1343 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001344#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001345 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1346#else
1347 n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1348#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001349 if (n == size_t(-1)) // on error
1350 return error;
1351 if (n > to_end-to_nxt) // is there room?
1352 return partial;
1353 for (extern_type* p = tmp; n; --n) // write it
1354 *to_nxt++ = *p++;
1355 ++frm_nxt;
1356 // look for next null in frm
1357 for (fend = frm_nxt; fend != frm_end; ++fend)
1358 if (*fend == 0)
1359 break;
1360 }
1361 }
1362 return frm_nxt == frm_end ? ok : partial;
1363}
1364
1365codecvt<wchar_t, char, mbstate_t>::result
1366codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001367 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001368 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1369{
1370 // look for first internal null in frm
1371 const extern_type* fend = frm;
1372 for (; fend != frm_end; ++fend)
1373 if (*fend == 0)
1374 break;
1375 // loop over all null-terminated sequences in frm
1376 to_nxt = to;
1377 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1378 {
1379 // save state in case needed to reover to_nxt on error
1380 mbstate_t save_state = st;
Howard Hinnant866569b2011-09-28 23:39:33 +00001381#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001382 size_t n = mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1383#else
1384 size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1385#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001386 if (n == size_t(-1))
1387 {
1388 // need to recover to_nxt
1389 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1390 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001391#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001392 n = mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1393#else
1394 n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1395#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001396 switch (n)
1397 {
1398 case 0:
1399 ++frm;
1400 break;
1401 case -1:
1402 frm_nxt = frm;
1403 return error;
1404 case -2:
1405 frm_nxt = frm;
1406 return partial;
1407 default:
1408 frm += n;
1409 break;
1410 }
1411 }
1412 frm_nxt = frm;
1413 return frm_nxt == frm_end ? ok : partial;
1414 }
1415 if (n == 0)
1416 return error;
1417 to_nxt += n;
1418 if (to_nxt == to_end)
1419 break;
1420 if (fend != frm_end) // set up next null terminated sequence
1421 {
1422 // Try to write the terminating null
Howard Hinnant866569b2011-09-28 23:39:33 +00001423#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001424 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1425#else
1426 n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1427#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001428 if (n != 0) // on error
1429 return error;
1430 ++to_nxt;
1431 ++frm_nxt;
1432 // look for next null in frm
1433 for (fend = frm_nxt; fend != frm_end; ++fend)
1434 if (*fend == 0)
1435 break;
1436 }
1437 }
1438 return frm_nxt == frm_end ? ok : partial;
1439}
1440
1441codecvt<wchar_t, char, mbstate_t>::result
1442codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1443 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1444{
1445 to_nxt = to;
1446 extern_type tmp[MB_LEN_MAX];
Howard Hinnant866569b2011-09-28 23:39:33 +00001447#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001448 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1449#else
1450 size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l);
1451#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001452 if (n == size_t(-1) || n == 0) // on error
1453 return error;
1454 --n;
1455 if (n > to_end-to_nxt) // is there room?
1456 return partial;
1457 for (extern_type* p = tmp; n; --n) // write it
1458 *to_nxt++ = *p++;
1459 return ok;
1460}
1461
1462int
Howard Hinnantc9834542011-05-31 15:34:58 +00001463codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001464{
Howard Hinnant866569b2011-09-28 23:39:33 +00001465#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001466 if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1467#else
1468 if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0)
1469#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001470 {
1471 // stateless encoding
Howard Hinnant866569b2011-09-28 23:39:33 +00001472#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001473 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1474#else
1475 if (__l == 0 || __mb_cur_max_l(__l) == 1) // there are no known constant length encodings
1476#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001477 return 1; // which take more than 1 char to form a wchar_t
1478 return 0;
1479 }
1480 return -1;
1481}
1482
1483bool
Howard Hinnantc9834542011-05-31 15:34:58 +00001484codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001485{
1486 return false;
1487}
1488
1489int
1490codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1491 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1492{
1493 int nbytes = 0;
1494 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1495 {
Howard Hinnant866569b2011-09-28 23:39:33 +00001496#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001497 size_t n = mbrlen_l(frm, frm_end-frm, &st, __l);
1498#else
1499 size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l);
1500#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001501 switch (n)
1502 {
1503 case 0:
1504 ++nbytes;
1505 ++frm;
1506 break;
1507 case -1:
1508 case -2:
1509 return nbytes;
1510 default:
1511 nbytes += n;
1512 frm += n;
1513 break;
1514 }
1515 }
1516 return nbytes;
1517}
1518
1519int
Howard Hinnantc9834542011-05-31 15:34:58 +00001520codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001521{
Howard Hinnant866569b2011-09-28 23:39:33 +00001522#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00001523 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1524#else
1525 return __l == 0 ? 1 : __mb_cur_max_l(__l);
1526#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001527}
1528
1529// Valid UTF ranges
1530// UTF-32 UTF-16 UTF-8 # of code points
1531// first second first second third fourth
1532// 000000 - 00007F 0000 - 007F 00 - 7F 127
1533// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1534// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1535// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1536// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1537// 00D800 - 00DFFF invalid
1538// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1539// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1540// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1541// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1542
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001543static
1544codecvt_base::result
1545utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1546 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1547 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1548{
1549 frm_nxt = frm;
1550 to_nxt = to;
1551 if (mode & generate_header)
1552 {
1553 if (to_end-to_nxt < 3)
1554 return codecvt_base::partial;
1555 *to_nxt++ = static_cast<uint8_t>(0xEF);
1556 *to_nxt++ = static_cast<uint8_t>(0xBB);
1557 *to_nxt++ = static_cast<uint8_t>(0xBF);
1558 }
1559 for (; frm_nxt < frm_end; ++frm_nxt)
1560 {
1561 uint16_t wc1 = *frm_nxt;
1562 if (wc1 > Maxcode)
1563 return codecvt_base::error;
1564 if (wc1 < 0x0080)
1565 {
1566 if (to_end-to_nxt < 1)
1567 return codecvt_base::partial;
1568 *to_nxt++ = static_cast<uint8_t>(wc1);
1569 }
1570 else if (wc1 < 0x0800)
1571 {
1572 if (to_end-to_nxt < 2)
1573 return codecvt_base::partial;
1574 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1575 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1576 }
1577 else if (wc1 < 0xD800)
1578 {
1579 if (to_end-to_nxt < 3)
1580 return codecvt_base::partial;
1581 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1582 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1583 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1584 }
1585 else if (wc1 < 0xDC00)
1586 {
1587 if (frm_end-frm_nxt < 2)
1588 return codecvt_base::partial;
1589 uint16_t wc2 = frm_nxt[1];
1590 if ((wc2 & 0xFC00) != 0xDC00)
1591 return codecvt_base::error;
1592 if (to_end-to_nxt < 4)
1593 return codecvt_base::partial;
1594 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1595 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1596 return codecvt_base::error;
1597 ++frm_nxt;
1598 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1599 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1600 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1601 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1602 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1603 }
1604 else if (wc1 < 0xE000)
1605 {
1606 return codecvt_base::error;
1607 }
1608 else
1609 {
1610 if (to_end-to_nxt < 3)
1611 return codecvt_base::partial;
1612 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1613 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1614 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1615 }
1616 }
1617 return codecvt_base::ok;
1618}
1619
1620static
1621codecvt_base::result
1622utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1623 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1624 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1625{
1626 frm_nxt = frm;
1627 to_nxt = to;
1628 if (mode & generate_header)
1629 {
1630 if (to_end-to_nxt < 3)
1631 return codecvt_base::partial;
1632 *to_nxt++ = static_cast<uint8_t>(0xEF);
1633 *to_nxt++ = static_cast<uint8_t>(0xBB);
1634 *to_nxt++ = static_cast<uint8_t>(0xBF);
1635 }
1636 for (; frm_nxt < frm_end; ++frm_nxt)
1637 {
1638 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1639 if (wc1 > Maxcode)
1640 return codecvt_base::error;
1641 if (wc1 < 0x0080)
1642 {
1643 if (to_end-to_nxt < 1)
1644 return codecvt_base::partial;
1645 *to_nxt++ = static_cast<uint8_t>(wc1);
1646 }
1647 else if (wc1 < 0x0800)
1648 {
1649 if (to_end-to_nxt < 2)
1650 return codecvt_base::partial;
1651 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1652 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1653 }
1654 else if (wc1 < 0xD800)
1655 {
1656 if (to_end-to_nxt < 3)
1657 return codecvt_base::partial;
1658 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1659 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1660 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1661 }
1662 else if (wc1 < 0xDC00)
1663 {
1664 if (frm_end-frm_nxt < 2)
1665 return codecvt_base::partial;
1666 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1667 if ((wc2 & 0xFC00) != 0xDC00)
1668 return codecvt_base::error;
1669 if (to_end-to_nxt < 4)
1670 return codecvt_base::partial;
1671 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1672 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1673 return codecvt_base::error;
1674 ++frm_nxt;
1675 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1676 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1677 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1678 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1679 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1680 }
1681 else if (wc1 < 0xE000)
1682 {
1683 return codecvt_base::error;
1684 }
1685 else
1686 {
1687 if (to_end-to_nxt < 3)
1688 return codecvt_base::partial;
1689 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1690 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1691 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1692 }
1693 }
1694 return codecvt_base::ok;
1695}
1696
1697static
1698codecvt_base::result
1699utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1700 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1701 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1702{
1703 frm_nxt = frm;
1704 to_nxt = to;
1705 if (mode & consume_header)
1706 {
1707 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1708 frm_nxt[2] == 0xBF)
1709 frm_nxt += 3;
1710 }
1711 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1712 {
1713 uint8_t c1 = *frm_nxt;
1714 if (c1 > Maxcode)
1715 return codecvt_base::error;
1716 if (c1 < 0x80)
1717 {
1718 *to_nxt = static_cast<uint16_t>(c1);
1719 ++frm_nxt;
1720 }
1721 else if (c1 < 0xC2)
1722 {
1723 return codecvt_base::error;
1724 }
1725 else if (c1 < 0xE0)
1726 {
1727 if (frm_end-frm_nxt < 2)
1728 return codecvt_base::partial;
1729 uint8_t c2 = frm_nxt[1];
1730 if ((c2 & 0xC0) != 0x80)
1731 return codecvt_base::error;
1732 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1733 if (t > Maxcode)
1734 return codecvt_base::error;
1735 *to_nxt = t;
1736 frm_nxt += 2;
1737 }
1738 else if (c1 < 0xF0)
1739 {
1740 if (frm_end-frm_nxt < 3)
1741 return codecvt_base::partial;
1742 uint8_t c2 = frm_nxt[1];
1743 uint8_t c3 = frm_nxt[2];
1744 switch (c1)
1745 {
1746 case 0xE0:
1747 if ((c2 & 0xE0) != 0xA0)
1748 return codecvt_base::error;
1749 break;
1750 case 0xED:
1751 if ((c2 & 0xE0) != 0x80)
1752 return codecvt_base::error;
1753 break;
1754 default:
1755 if ((c2 & 0xC0) != 0x80)
1756 return codecvt_base::error;
1757 break;
1758 }
1759 if ((c3 & 0xC0) != 0x80)
1760 return codecvt_base::error;
1761 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1762 | ((c2 & 0x3F) << 6)
1763 | (c3 & 0x3F));
1764 if (t > Maxcode)
1765 return codecvt_base::error;
1766 *to_nxt = t;
1767 frm_nxt += 3;
1768 }
1769 else if (c1 < 0xF5)
1770 {
1771 if (frm_end-frm_nxt < 4)
1772 return codecvt_base::partial;
1773 uint8_t c2 = frm_nxt[1];
1774 uint8_t c3 = frm_nxt[2];
1775 uint8_t c4 = frm_nxt[3];
1776 switch (c1)
1777 {
1778 case 0xF0:
1779 if (!(0x90 <= c2 && c2 <= 0xBF))
1780 return codecvt_base::error;
1781 break;
1782 case 0xF4:
1783 if ((c2 & 0xF0) != 0x80)
1784 return codecvt_base::error;
1785 break;
1786 default:
1787 if ((c2 & 0xC0) != 0x80)
1788 return codecvt_base::error;
1789 break;
1790 }
1791 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1792 return codecvt_base::error;
1793 if (to_end-to_nxt < 2)
1794 return codecvt_base::partial;
1795 if (((((unsigned long)c1 & 7) << 18) +
1796 (((unsigned long)c2 & 0x3F) << 12) +
1797 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1798 return codecvt_base::error;
1799 *to_nxt = static_cast<uint16_t>(
1800 0xD800
1801 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1802 | ((c2 & 0x0F) << 2)
1803 | ((c3 & 0x30) >> 4));
1804 *++to_nxt = static_cast<uint16_t>(
1805 0xDC00
1806 | ((c3 & 0x0F) << 6)
1807 | (c4 & 0x3F));
1808 frm_nxt += 4;
1809 }
1810 else
1811 {
1812 return codecvt_base::error;
1813 }
1814 }
1815 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1816}
1817
1818static
1819codecvt_base::result
1820utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1821 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1822 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1823{
1824 frm_nxt = frm;
1825 to_nxt = to;
1826 if (mode & consume_header)
1827 {
1828 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1829 frm_nxt[2] == 0xBF)
1830 frm_nxt += 3;
1831 }
1832 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1833 {
1834 uint8_t c1 = *frm_nxt;
1835 if (c1 > Maxcode)
1836 return codecvt_base::error;
1837 if (c1 < 0x80)
1838 {
1839 *to_nxt = static_cast<uint32_t>(c1);
1840 ++frm_nxt;
1841 }
1842 else if (c1 < 0xC2)
1843 {
1844 return codecvt_base::error;
1845 }
1846 else if (c1 < 0xE0)
1847 {
1848 if (frm_end-frm_nxt < 2)
1849 return codecvt_base::partial;
1850 uint8_t c2 = frm_nxt[1];
1851 if ((c2 & 0xC0) != 0x80)
1852 return codecvt_base::error;
1853 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1854 if (t > Maxcode)
1855 return codecvt_base::error;
1856 *to_nxt = static_cast<uint32_t>(t);
1857 frm_nxt += 2;
1858 }
1859 else if (c1 < 0xF0)
1860 {
1861 if (frm_end-frm_nxt < 3)
1862 return codecvt_base::partial;
1863 uint8_t c2 = frm_nxt[1];
1864 uint8_t c3 = frm_nxt[2];
1865 switch (c1)
1866 {
1867 case 0xE0:
1868 if ((c2 & 0xE0) != 0xA0)
1869 return codecvt_base::error;
1870 break;
1871 case 0xED:
1872 if ((c2 & 0xE0) != 0x80)
1873 return codecvt_base::error;
1874 break;
1875 default:
1876 if ((c2 & 0xC0) != 0x80)
1877 return codecvt_base::error;
1878 break;
1879 }
1880 if ((c3 & 0xC0) != 0x80)
1881 return codecvt_base::error;
1882 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1883 | ((c2 & 0x3F) << 6)
1884 | (c3 & 0x3F));
1885 if (t > Maxcode)
1886 return codecvt_base::error;
1887 *to_nxt = static_cast<uint32_t>(t);
1888 frm_nxt += 3;
1889 }
1890 else if (c1 < 0xF5)
1891 {
1892 if (frm_end-frm_nxt < 4)
1893 return codecvt_base::partial;
1894 uint8_t c2 = frm_nxt[1];
1895 uint8_t c3 = frm_nxt[2];
1896 uint8_t c4 = frm_nxt[3];
1897 switch (c1)
1898 {
1899 case 0xF0:
1900 if (!(0x90 <= c2 && c2 <= 0xBF))
1901 return codecvt_base::error;
1902 break;
1903 case 0xF4:
1904 if ((c2 & 0xF0) != 0x80)
1905 return codecvt_base::error;
1906 break;
1907 default:
1908 if ((c2 & 0xC0) != 0x80)
1909 return codecvt_base::error;
1910 break;
1911 }
1912 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1913 return codecvt_base::error;
1914 if (to_end-to_nxt < 2)
1915 return codecvt_base::partial;
1916 if (((((unsigned long)c1 & 7) << 18) +
1917 (((unsigned long)c2 & 0x3F) << 12) +
1918 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1919 return codecvt_base::error;
1920 *to_nxt = static_cast<uint32_t>(
1921 0xD800
1922 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1923 | ((c2 & 0x0F) << 2)
1924 | ((c3 & 0x30) >> 4));
1925 *++to_nxt = static_cast<uint32_t>(
1926 0xDC00
1927 | ((c3 & 0x0F) << 6)
1928 | (c4 & 0x3F));
1929 frm_nxt += 4;
1930 }
1931 else
1932 {
1933 return codecvt_base::error;
1934 }
1935 }
1936 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1937}
1938
1939static
1940int
1941utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
1942 size_t mx, unsigned long Maxcode = 0x10FFFF,
1943 codecvt_mode mode = codecvt_mode(0))
1944{
1945 const uint8_t* frm_nxt = frm;
1946 if (mode & consume_header)
1947 {
1948 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1949 frm_nxt[2] == 0xBF)
1950 frm_nxt += 3;
1951 }
1952 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1953 {
1954 uint8_t c1 = *frm_nxt;
1955 if (c1 > Maxcode)
1956 break;
1957 if (c1 < 0x80)
1958 {
1959 ++frm_nxt;
1960 }
1961 else if (c1 < 0xC2)
1962 {
1963 break;
1964 }
1965 else if (c1 < 0xE0)
1966 {
1967 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
1968 break;
1969 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
1970 if (t > Maxcode)
1971 break;
1972 frm_nxt += 2;
1973 }
1974 else if (c1 < 0xF0)
1975 {
1976 if (frm_end-frm_nxt < 3)
1977 break;
1978 uint8_t c2 = frm_nxt[1];
1979 uint8_t c3 = frm_nxt[2];
1980 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1981 | ((c2 & 0x3F) << 6)
1982 | (c3 & 0x3F));
1983 switch (c1)
1984 {
1985 case 0xE0:
1986 if ((c2 & 0xE0) != 0xA0)
1987 return static_cast<int>(frm_nxt - frm);
1988 break;
1989 case 0xED:
1990 if ((c2 & 0xE0) != 0x80)
1991 return static_cast<int>(frm_nxt - frm);
1992 break;
1993 default:
1994 if ((c2 & 0xC0) != 0x80)
1995 return static_cast<int>(frm_nxt - frm);
1996 break;
1997 }
1998 if ((c3 & 0xC0) != 0x80)
1999 break;
2000 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2001 break;
2002 frm_nxt += 3;
2003 }
2004 else if (c1 < 0xF5)
2005 {
2006 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
2007 break;
2008 uint8_t c2 = frm_nxt[1];
2009 uint8_t c3 = frm_nxt[2];
2010 uint8_t c4 = frm_nxt[3];
2011 switch (c1)
2012 {
2013 case 0xF0:
2014 if (!(0x90 <= c2 && c2 <= 0xBF))
2015 return static_cast<int>(frm_nxt - frm);
2016 break;
2017 case 0xF4:
2018 if ((c2 & 0xF0) != 0x80)
2019 return static_cast<int>(frm_nxt - frm);
2020 break;
2021 default:
2022 if ((c2 & 0xC0) != 0x80)
2023 return static_cast<int>(frm_nxt - frm);
2024 break;
2025 }
2026 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2027 break;
2028 if (((((unsigned long)c1 & 7) << 18) +
2029 (((unsigned long)c2 & 0x3F) << 12) +
2030 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
2031 break;
2032 ++nchar16_t;
2033 frm_nxt += 4;
2034 }
2035 else
2036 {
2037 break;
2038 }
2039 }
2040 return static_cast<int>(frm_nxt - frm);
2041}
2042
2043static
2044codecvt_base::result
2045ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2046 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2047 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2048{
2049 frm_nxt = frm;
2050 to_nxt = to;
2051 if (mode & generate_header)
2052 {
2053 if (to_end-to_nxt < 3)
2054 return codecvt_base::partial;
2055 *to_nxt++ = static_cast<uint8_t>(0xEF);
2056 *to_nxt++ = static_cast<uint8_t>(0xBB);
2057 *to_nxt++ = static_cast<uint8_t>(0xBF);
2058 }
2059 for (; frm_nxt < frm_end; ++frm_nxt)
2060 {
2061 uint32_t wc = *frm_nxt;
2062 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2063 return codecvt_base::error;
2064 if (wc < 0x000080)
2065 {
2066 if (to_end-to_nxt < 1)
2067 return codecvt_base::partial;
2068 *to_nxt++ = static_cast<uint8_t>(wc);
2069 }
2070 else if (wc < 0x000800)
2071 {
2072 if (to_end-to_nxt < 2)
2073 return codecvt_base::partial;
2074 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2075 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2076 }
2077 else if (wc < 0x010000)
2078 {
2079 if (to_end-to_nxt < 3)
2080 return codecvt_base::partial;
2081 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2082 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2083 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2084 }
2085 else // if (wc < 0x110000)
2086 {
2087 if (to_end-to_nxt < 4)
2088 return codecvt_base::partial;
2089 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
2090 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
2091 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
2092 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
2093 }
2094 }
2095 return codecvt_base::ok;
2096}
2097
2098static
2099codecvt_base::result
2100utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2101 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2102 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2103{
2104 frm_nxt = frm;
2105 to_nxt = to;
2106 if (mode & consume_header)
2107 {
2108 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2109 frm_nxt[2] == 0xBF)
2110 frm_nxt += 3;
2111 }
2112 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2113 {
2114 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2115 if (c1 < 0x80)
2116 {
2117 if (c1 > Maxcode)
2118 return codecvt_base::error;
2119 *to_nxt = static_cast<uint32_t>(c1);
2120 ++frm_nxt;
2121 }
2122 else if (c1 < 0xC2)
2123 {
2124 return codecvt_base::error;
2125 }
2126 else if (c1 < 0xE0)
2127 {
2128 if (frm_end-frm_nxt < 2)
2129 return codecvt_base::partial;
2130 uint8_t c2 = frm_nxt[1];
2131 if ((c2 & 0xC0) != 0x80)
2132 return codecvt_base::error;
2133 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
2134 | (c2 & 0x3F));
2135 if (t > Maxcode)
2136 return codecvt_base::error;
2137 *to_nxt = t;
2138 frm_nxt += 2;
2139 }
2140 else if (c1 < 0xF0)
2141 {
2142 if (frm_end-frm_nxt < 3)
2143 return codecvt_base::partial;
2144 uint8_t c2 = frm_nxt[1];
2145 uint8_t c3 = frm_nxt[2];
2146 switch (c1)
2147 {
2148 case 0xE0:
2149 if ((c2 & 0xE0) != 0xA0)
2150 return codecvt_base::error;
2151 break;
2152 case 0xED:
2153 if ((c2 & 0xE0) != 0x80)
2154 return codecvt_base::error;
2155 break;
2156 default:
2157 if ((c2 & 0xC0) != 0x80)
2158 return codecvt_base::error;
2159 break;
2160 }
2161 if ((c3 & 0xC0) != 0x80)
2162 return codecvt_base::error;
2163 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
2164 | ((c2 & 0x3F) << 6)
2165 | (c3 & 0x3F));
2166 if (t > Maxcode)
2167 return codecvt_base::error;
2168 *to_nxt = t;
2169 frm_nxt += 3;
2170 }
2171 else if (c1 < 0xF5)
2172 {
2173 if (frm_end-frm_nxt < 4)
2174 return codecvt_base::partial;
2175 uint8_t c2 = frm_nxt[1];
2176 uint8_t c3 = frm_nxt[2];
2177 uint8_t c4 = frm_nxt[3];
2178 switch (c1)
2179 {
2180 case 0xF0:
2181 if (!(0x90 <= c2 && c2 <= 0xBF))
2182 return codecvt_base::error;
2183 break;
2184 case 0xF4:
2185 if ((c2 & 0xF0) != 0x80)
2186 return codecvt_base::error;
2187 break;
2188 default:
2189 if ((c2 & 0xC0) != 0x80)
2190 return codecvt_base::error;
2191 break;
2192 }
2193 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2194 return codecvt_base::error;
2195 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2196 | ((c2 & 0x3F) << 12)
2197 | ((c3 & 0x3F) << 6)
2198 | (c4 & 0x3F));
2199 if (t > Maxcode)
2200 return codecvt_base::error;
2201 *to_nxt = t;
2202 frm_nxt += 4;
2203 }
2204 else
2205 {
2206 return codecvt_base::error;
2207 }
2208 }
2209 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2210}
2211
2212static
2213int
2214utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2215 size_t mx, unsigned long Maxcode = 0x10FFFF,
2216 codecvt_mode mode = codecvt_mode(0))
2217{
2218 const uint8_t* frm_nxt = frm;
2219 if (mode & consume_header)
2220 {
2221 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2222 frm_nxt[2] == 0xBF)
2223 frm_nxt += 3;
2224 }
2225 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2226 {
2227 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2228 if (c1 < 0x80)
2229 {
2230 if (c1 > Maxcode)
2231 break;
2232 ++frm_nxt;
2233 }
2234 else if (c1 < 0xC2)
2235 {
2236 break;
2237 }
2238 else if (c1 < 0xE0)
2239 {
2240 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2241 break;
2242 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2243 break;
2244 frm_nxt += 2;
2245 }
2246 else if (c1 < 0xF0)
2247 {
2248 if (frm_end-frm_nxt < 3)
2249 break;
2250 uint8_t c2 = frm_nxt[1];
2251 uint8_t c3 = frm_nxt[2];
2252 switch (c1)
2253 {
2254 case 0xE0:
2255 if ((c2 & 0xE0) != 0xA0)
2256 return static_cast<int>(frm_nxt - frm);
2257 break;
2258 case 0xED:
2259 if ((c2 & 0xE0) != 0x80)
2260 return static_cast<int>(frm_nxt - frm);
2261 break;
2262 default:
2263 if ((c2 & 0xC0) != 0x80)
2264 return static_cast<int>(frm_nxt - frm);
2265 break;
2266 }
2267 if ((c3 & 0xC0) != 0x80)
2268 break;
2269 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2270 break;
2271 frm_nxt += 3;
2272 }
2273 else if (c1 < 0xF5)
2274 {
2275 if (frm_end-frm_nxt < 4)
2276 break;
2277 uint8_t c2 = frm_nxt[1];
2278 uint8_t c3 = frm_nxt[2];
2279 uint8_t c4 = frm_nxt[3];
2280 switch (c1)
2281 {
2282 case 0xF0:
2283 if (!(0x90 <= c2 && c2 <= 0xBF))
2284 return static_cast<int>(frm_nxt - frm);
2285 break;
2286 case 0xF4:
2287 if ((c2 & 0xF0) != 0x80)
2288 return static_cast<int>(frm_nxt - frm);
2289 break;
2290 default:
2291 if ((c2 & 0xC0) != 0x80)
2292 return static_cast<int>(frm_nxt - frm);
2293 break;
2294 }
2295 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2296 break;
2297 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2298 | ((c2 & 0x3F) << 12)
2299 | ((c3 & 0x3F) << 6)
2300 | (c4 & 0x3F));
2301 if ((((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) |
2302 ((c3 & 0x3F) << 6) | (c4 & 0x3F)) > Maxcode)
2303 break;
2304 frm_nxt += 4;
2305 }
2306 else
2307 {
2308 break;
2309 }
2310 }
2311 return static_cast<int>(frm_nxt - frm);
2312}
2313
2314static
2315codecvt_base::result
2316ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2317 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2318 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2319{
2320 frm_nxt = frm;
2321 to_nxt = to;
2322 if (mode & generate_header)
2323 {
2324 if (to_end-to_nxt < 3)
2325 return codecvt_base::partial;
2326 *to_nxt++ = static_cast<uint8_t>(0xEF);
2327 *to_nxt++ = static_cast<uint8_t>(0xBB);
2328 *to_nxt++ = static_cast<uint8_t>(0xBF);
2329 }
2330 for (; frm_nxt < frm_end; ++frm_nxt)
2331 {
2332 uint16_t wc = *frm_nxt;
2333 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2334 return codecvt_base::error;
2335 if (wc < 0x0080)
2336 {
2337 if (to_end-to_nxt < 1)
2338 return codecvt_base::partial;
2339 *to_nxt++ = static_cast<uint8_t>(wc);
2340 }
2341 else if (wc < 0x0800)
2342 {
2343 if (to_end-to_nxt < 2)
2344 return codecvt_base::partial;
2345 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2346 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2347 }
2348 else // if (wc <= 0xFFFF)
2349 {
2350 if (to_end-to_nxt < 3)
2351 return codecvt_base::partial;
2352 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2353 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2354 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2355 }
2356 }
2357 return codecvt_base::ok;
2358}
2359
2360static
2361codecvt_base::result
2362utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2363 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2364 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2365{
2366 frm_nxt = frm;
2367 to_nxt = to;
2368 if (mode & consume_header)
2369 {
2370 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2371 frm_nxt[2] == 0xBF)
2372 frm_nxt += 3;
2373 }
2374 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2375 {
2376 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2377 if (c1 < 0x80)
2378 {
2379 if (c1 > Maxcode)
2380 return codecvt_base::error;
2381 *to_nxt = static_cast<uint16_t>(c1);
2382 ++frm_nxt;
2383 }
2384 else if (c1 < 0xC2)
2385 {
2386 return codecvt_base::error;
2387 }
2388 else if (c1 < 0xE0)
2389 {
2390 if (frm_end-frm_nxt < 2)
2391 return codecvt_base::partial;
2392 uint8_t c2 = frm_nxt[1];
2393 if ((c2 & 0xC0) != 0x80)
2394 return codecvt_base::error;
2395 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2396 | (c2 & 0x3F));
2397 if (t > Maxcode)
2398 return codecvt_base::error;
2399 *to_nxt = t;
2400 frm_nxt += 2;
2401 }
2402 else if (c1 < 0xF0)
2403 {
2404 if (frm_end-frm_nxt < 3)
2405 return codecvt_base::partial;
2406 uint8_t c2 = frm_nxt[1];
2407 uint8_t c3 = frm_nxt[2];
2408 switch (c1)
2409 {
2410 case 0xE0:
2411 if ((c2 & 0xE0) != 0xA0)
2412 return codecvt_base::error;
2413 break;
2414 case 0xED:
2415 if ((c2 & 0xE0) != 0x80)
2416 return codecvt_base::error;
2417 break;
2418 default:
2419 if ((c2 & 0xC0) != 0x80)
2420 return codecvt_base::error;
2421 break;
2422 }
2423 if ((c3 & 0xC0) != 0x80)
2424 return codecvt_base::error;
2425 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2426 | ((c2 & 0x3F) << 6)
2427 | (c3 & 0x3F));
2428 if (t > Maxcode)
2429 return codecvt_base::error;
2430 *to_nxt = t;
2431 frm_nxt += 3;
2432 }
2433 else
2434 {
2435 return codecvt_base::error;
2436 }
2437 }
2438 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2439}
2440
2441static
2442int
2443utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2444 size_t mx, unsigned long Maxcode = 0x10FFFF,
2445 codecvt_mode mode = codecvt_mode(0))
2446{
2447 const uint8_t* frm_nxt = frm;
2448 if (mode & consume_header)
2449 {
2450 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2451 frm_nxt[2] == 0xBF)
2452 frm_nxt += 3;
2453 }
2454 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2455 {
2456 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2457 if (c1 < 0x80)
2458 {
2459 if (c1 > Maxcode)
2460 break;
2461 ++frm_nxt;
2462 }
2463 else if (c1 < 0xC2)
2464 {
2465 break;
2466 }
2467 else if (c1 < 0xE0)
2468 {
2469 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2470 break;
2471 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2472 break;
2473 frm_nxt += 2;
2474 }
2475 else if (c1 < 0xF0)
2476 {
2477 if (frm_end-frm_nxt < 3)
2478 break;
2479 uint8_t c2 = frm_nxt[1];
2480 uint8_t c3 = frm_nxt[2];
2481 switch (c1)
2482 {
2483 case 0xE0:
2484 if ((c2 & 0xE0) != 0xA0)
2485 return static_cast<int>(frm_nxt - frm);
2486 break;
2487 case 0xED:
2488 if ((c2 & 0xE0) != 0x80)
2489 return static_cast<int>(frm_nxt - frm);
2490 break;
2491 default:
2492 if ((c2 & 0xC0) != 0x80)
2493 return static_cast<int>(frm_nxt - frm);
2494 break;
2495 }
2496 if ((c3 & 0xC0) != 0x80)
2497 break;
2498 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2499 break;
2500 frm_nxt += 3;
2501 }
2502 else
2503 {
2504 break;
2505 }
2506 }
2507 return static_cast<int>(frm_nxt - frm);
2508}
2509
2510static
2511codecvt_base::result
2512ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2513 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2514 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2515{
2516 frm_nxt = frm;
2517 to_nxt = to;
2518 if (mode & generate_header)
2519 {
2520 if (to_end-to_nxt < 2)
2521 return codecvt_base::partial;
2522 *to_nxt++ = static_cast<uint8_t>(0xFE);
2523 *to_nxt++ = static_cast<uint8_t>(0xFF);
2524 }
2525 for (; frm_nxt < frm_end; ++frm_nxt)
2526 {
2527 uint32_t wc = *frm_nxt;
2528 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2529 return codecvt_base::error;
2530 if (wc < 0x010000)
2531 {
2532 if (to_end-to_nxt < 2)
2533 return codecvt_base::partial;
2534 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2535 *to_nxt++ = static_cast<uint8_t>(wc);
2536 }
2537 else
2538 {
2539 if (to_end-to_nxt < 4)
2540 return codecvt_base::partial;
2541 uint16_t t = static_cast<uint16_t>(
2542 0xD800
2543 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2544 | ((wc & 0x00FC00) >> 10));
2545 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2546 *to_nxt++ = static_cast<uint8_t>(t);
2547 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2548 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2549 *to_nxt++ = static_cast<uint8_t>(t);
2550 }
2551 }
2552 return codecvt_base::ok;
2553}
2554
2555static
2556codecvt_base::result
2557utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2558 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2559 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2560{
2561 frm_nxt = frm;
2562 to_nxt = to;
2563 if (mode & consume_header)
2564 {
2565 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2566 frm_nxt += 2;
2567 }
2568 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2569 {
2570 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2571 if ((c1 & 0xFC00) == 0xDC00)
2572 return codecvt_base::error;
2573 if ((c1 & 0xFC00) != 0xD800)
2574 {
2575 if (c1 > Maxcode)
2576 return codecvt_base::error;
2577 *to_nxt = static_cast<uint32_t>(c1);
2578 frm_nxt += 2;
2579 }
2580 else
2581 {
2582 if (frm_end-frm_nxt < 4)
2583 return codecvt_base::partial;
2584 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2585 if ((c2 & 0xFC00) != 0xDC00)
2586 return codecvt_base::error;
2587 uint32_t t = static_cast<uint32_t>(
2588 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2589 | ((c1 & 0x003F) << 10)
2590 | (c2 & 0x03FF));
2591 if (t > Maxcode)
2592 return codecvt_base::error;
2593 *to_nxt = t;
2594 frm_nxt += 4;
2595 }
2596 }
2597 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2598}
2599
2600static
2601int
2602utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2603 size_t mx, unsigned long Maxcode = 0x10FFFF,
2604 codecvt_mode mode = codecvt_mode(0))
2605{
2606 const uint8_t* frm_nxt = frm;
2607 frm_nxt = frm;
2608 if (mode & consume_header)
2609 {
2610 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2611 frm_nxt += 2;
2612 }
2613 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2614 {
2615 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2616 if ((c1 & 0xFC00) == 0xDC00)
2617 break;
2618 if ((c1 & 0xFC00) != 0xD800)
2619 {
2620 if (c1 > Maxcode)
2621 break;
2622 frm_nxt += 2;
2623 }
2624 else
2625 {
2626 if (frm_end-frm_nxt < 4)
2627 break;
2628 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2629 if ((c2 & 0xFC00) != 0xDC00)
2630 break;
2631 uint32_t t = static_cast<uint32_t>(
2632 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2633 | ((c1 & 0x003F) << 10)
2634 | (c2 & 0x03FF));
2635 if (t > Maxcode)
2636 break;
2637 frm_nxt += 4;
2638 }
2639 }
2640 return static_cast<int>(frm_nxt - frm);
2641}
2642
2643static
2644codecvt_base::result
2645ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2646 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2647 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2648{
2649 frm_nxt = frm;
2650 to_nxt = to;
2651 if (mode & generate_header)
2652 {
2653 if (to_end-to_nxt < 2)
2654 return codecvt_base::partial;
2655 *to_nxt++ = static_cast<uint8_t>(0xFF);
2656 *to_nxt++ = static_cast<uint8_t>(0xFE);
2657 }
2658 for (; frm_nxt < frm_end; ++frm_nxt)
2659 {
2660 uint32_t wc = *frm_nxt;
2661 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2662 return codecvt_base::error;
2663 if (wc < 0x010000)
2664 {
2665 if (to_end-to_nxt < 2)
2666 return codecvt_base::partial;
2667 *to_nxt++ = static_cast<uint8_t>(wc);
2668 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2669 }
2670 else
2671 {
2672 if (to_end-to_nxt < 4)
2673 return codecvt_base::partial;
2674 uint16_t t = static_cast<uint16_t>(
2675 0xD800
2676 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2677 | ((wc & 0x00FC00) >> 10));
2678 *to_nxt++ = static_cast<uint8_t>(t);
2679 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2680 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2681 *to_nxt++ = static_cast<uint8_t>(t);
2682 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2683 }
2684 }
2685 return codecvt_base::ok;
2686}
2687
2688static
2689codecvt_base::result
2690utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2691 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2692 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2693{
2694 frm_nxt = frm;
2695 to_nxt = to;
2696 if (mode & consume_header)
2697 {
2698 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2699 frm_nxt += 2;
2700 }
2701 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2702 {
2703 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2704 if ((c1 & 0xFC00) == 0xDC00)
2705 return codecvt_base::error;
2706 if ((c1 & 0xFC00) != 0xD800)
2707 {
2708 if (c1 > Maxcode)
2709 return codecvt_base::error;
2710 *to_nxt = static_cast<uint32_t>(c1);
2711 frm_nxt += 2;
2712 }
2713 else
2714 {
2715 if (frm_end-frm_nxt < 4)
2716 return codecvt_base::partial;
2717 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2718 if ((c2 & 0xFC00) != 0xDC00)
2719 return codecvt_base::error;
2720 uint32_t t = static_cast<uint32_t>(
2721 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2722 | ((c1 & 0x003F) << 10)
2723 | (c2 & 0x03FF));
2724 if (t > Maxcode)
2725 return codecvt_base::error;
2726 *to_nxt = t;
2727 frm_nxt += 4;
2728 }
2729 }
2730 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2731}
2732
2733static
2734int
2735utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2736 size_t mx, unsigned long Maxcode = 0x10FFFF,
2737 codecvt_mode mode = codecvt_mode(0))
2738{
2739 const uint8_t* frm_nxt = frm;
2740 frm_nxt = frm;
2741 if (mode & consume_header)
2742 {
2743 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2744 frm_nxt += 2;
2745 }
2746 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2747 {
2748 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2749 if ((c1 & 0xFC00) == 0xDC00)
2750 break;
2751 if ((c1 & 0xFC00) != 0xD800)
2752 {
2753 if (c1 > Maxcode)
2754 break;
2755 frm_nxt += 2;
2756 }
2757 else
2758 {
2759 if (frm_end-frm_nxt < 4)
2760 break;
2761 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2762 if ((c2 & 0xFC00) != 0xDC00)
2763 break;
2764 uint32_t t = static_cast<uint32_t>(
2765 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2766 | ((c1 & 0x003F) << 10)
2767 | (c2 & 0x03FF));
2768 if (t > Maxcode)
2769 break;
2770 frm_nxt += 4;
2771 }
2772 }
2773 return static_cast<int>(frm_nxt - frm);
2774}
2775
2776static
2777codecvt_base::result
2778ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2779 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2780 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2781{
2782 frm_nxt = frm;
2783 to_nxt = to;
2784 if (mode & generate_header)
2785 {
2786 if (to_end-to_nxt < 2)
2787 return codecvt_base::partial;
2788 *to_nxt++ = static_cast<uint8_t>(0xFE);
2789 *to_nxt++ = static_cast<uint8_t>(0xFF);
2790 }
2791 for (; frm_nxt < frm_end; ++frm_nxt)
2792 {
2793 uint16_t wc = *frm_nxt;
2794 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2795 return codecvt_base::error;
2796 if (to_end-to_nxt < 2)
2797 return codecvt_base::partial;
2798 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2799 *to_nxt++ = static_cast<uint8_t>(wc);
2800 }
2801 return codecvt_base::ok;
2802}
2803
2804static
2805codecvt_base::result
2806utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2807 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2808 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2809{
2810 frm_nxt = frm;
2811 to_nxt = to;
2812 if (mode & consume_header)
2813 {
2814 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2815 frm_nxt += 2;
2816 }
2817 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2818 {
2819 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2820 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2821 return codecvt_base::error;
2822 *to_nxt = c1;
2823 frm_nxt += 2;
2824 }
2825 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2826}
2827
2828static
2829int
2830utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2831 size_t mx, unsigned long Maxcode = 0x10FFFF,
2832 codecvt_mode mode = codecvt_mode(0))
2833{
2834 const uint8_t* frm_nxt = frm;
2835 frm_nxt = frm;
2836 if (mode & consume_header)
2837 {
2838 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2839 frm_nxt += 2;
2840 }
2841 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2842 {
2843 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2844 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2845 break;
2846 frm_nxt += 2;
2847 }
2848 return static_cast<int>(frm_nxt - frm);
2849}
2850
2851static
2852codecvt_base::result
2853ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2854 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2855 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2856{
2857 frm_nxt = frm;
2858 to_nxt = to;
2859 if (mode & generate_header)
2860 {
2861 if (to_end-to_nxt < 2)
2862 return codecvt_base::partial;
2863 *to_nxt++ = static_cast<uint8_t>(0xFF);
2864 *to_nxt++ = static_cast<uint8_t>(0xFE);
2865 }
2866 for (; frm_nxt < frm_end; ++frm_nxt)
2867 {
2868 uint16_t wc = *frm_nxt;
2869 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2870 return codecvt_base::error;
2871 if (to_end-to_nxt < 2)
2872 return codecvt_base::partial;
2873 *to_nxt++ = static_cast<uint8_t>(wc);
2874 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2875 }
2876 return codecvt_base::ok;
2877}
2878
2879static
2880codecvt_base::result
2881utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2882 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2883 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2884{
2885 frm_nxt = frm;
2886 to_nxt = to;
2887 if (mode & consume_header)
2888 {
2889 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2890 frm_nxt += 2;
2891 }
2892 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2893 {
2894 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2895 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2896 return codecvt_base::error;
2897 *to_nxt = c1;
2898 frm_nxt += 2;
2899 }
2900 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2901}
2902
2903static
2904int
2905utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2906 size_t mx, unsigned long Maxcode = 0x10FFFF,
2907 codecvt_mode mode = codecvt_mode(0))
2908{
2909 const uint8_t* frm_nxt = frm;
2910 frm_nxt = frm;
2911 if (mode & consume_header)
2912 {
2913 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2914 frm_nxt += 2;
2915 }
2916 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2917 {
2918 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2919 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2920 break;
2921 frm_nxt += 2;
2922 }
2923 return static_cast<int>(frm_nxt - frm);
2924}
2925
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002926// template <> class codecvt<char16_t, char, mbstate_t>
2927
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002928locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002929
2930codecvt<char16_t, char, mbstate_t>::~codecvt()
2931{
2932}
2933
2934codecvt<char16_t, char, mbstate_t>::result
2935codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002936 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002937 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2938{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002939 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2940 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2941 const uint16_t* _frm_nxt = _frm;
2942 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2943 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2944 uint8_t* _to_nxt = _to;
2945 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2946 frm_nxt = frm + (_frm_nxt - _frm);
2947 to_nxt = to + (_to_nxt - _to);
2948 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002949}
2950
2951codecvt<char16_t, char, mbstate_t>::result
2952codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002953 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002954 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2955{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002956 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2957 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2958 const uint8_t* _frm_nxt = _frm;
2959 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2960 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2961 uint16_t* _to_nxt = _to;
2962 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2963 frm_nxt = frm + (_frm_nxt - _frm);
2964 to_nxt = to + (_to_nxt - _to);
2965 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002966}
2967
2968codecvt<char16_t, char, mbstate_t>::result
2969codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
2970 extern_type* to, extern_type*, extern_type*& to_nxt) const
2971{
2972 to_nxt = to;
2973 return noconv;
2974}
2975
2976int
Howard Hinnantc9834542011-05-31 15:34:58 +00002977codecvt<char16_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002978{
2979 return 0;
2980}
2981
2982bool
Howard Hinnantc9834542011-05-31 15:34:58 +00002983codecvt<char16_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002984{
2985 return false;
2986}
2987
2988int
2989codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
2990 const extern_type* frm, const extern_type* frm_end, size_t mx) const
2991{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002992 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2993 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2994 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002995}
2996
2997int
Howard Hinnantc9834542011-05-31 15:34:58 +00002998codecvt<char16_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002999{
3000 return 4;
3001}
3002
3003// template <> class codecvt<char32_t, char, mbstate_t>
3004
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003005locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003006
3007codecvt<char32_t, char, mbstate_t>::~codecvt()
3008{
3009}
3010
3011codecvt<char32_t, char, mbstate_t>::result
3012codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003013 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003014 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3015{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003016 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3017 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3018 const uint32_t* _frm_nxt = _frm;
3019 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3020 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3021 uint8_t* _to_nxt = _to;
3022 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3023 frm_nxt = frm + (_frm_nxt - _frm);
3024 to_nxt = to + (_to_nxt - _to);
3025 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003026}
3027
3028codecvt<char32_t, char, mbstate_t>::result
3029codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003030 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003031 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3032{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003033 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3034 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3035 const uint8_t* _frm_nxt = _frm;
3036 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3037 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3038 uint32_t* _to_nxt = _to;
3039 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
3040 frm_nxt = frm + (_frm_nxt - _frm);
3041 to_nxt = to + (_to_nxt - _to);
3042 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003043}
3044
3045codecvt<char32_t, char, mbstate_t>::result
3046codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
3047 extern_type* to, extern_type*, extern_type*& to_nxt) const
3048{
3049 to_nxt = to;
3050 return noconv;
3051}
3052
3053int
Howard Hinnantc9834542011-05-31 15:34:58 +00003054codecvt<char32_t, char, mbstate_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003055{
3056 return 0;
3057}
3058
3059bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003060codecvt<char32_t, char, mbstate_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003061{
3062 return false;
3063}
3064
3065int
3066codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
3067 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3068{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003069 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3070 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3071 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003072}
3073
3074int
Howard Hinnantc9834542011-05-31 15:34:58 +00003075codecvt<char32_t, char, mbstate_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003076{
3077 return 4;
3078}
3079
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003080// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003081
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003082__codecvt_utf8<wchar_t>::result
3083__codecvt_utf8<wchar_t>::do_out(state_type&,
3084 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003085 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3086{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003087 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3088 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3089 const uint32_t* _frm_nxt = _frm;
3090 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3091 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3092 uint8_t* _to_nxt = _to;
3093 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3094 _Maxcode_, _Mode_);
3095 frm_nxt = frm + (_frm_nxt - _frm);
3096 to_nxt = to + (_to_nxt - _to);
3097 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003098}
3099
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003100__codecvt_utf8<wchar_t>::result
3101__codecvt_utf8<wchar_t>::do_in(state_type&,
3102 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003103 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3104{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003105 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3106 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3107 const uint8_t* _frm_nxt = _frm;
3108 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3109 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3110 uint32_t* _to_nxt = _to;
3111 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3112 _Maxcode_, _Mode_);
3113 frm_nxt = frm + (_frm_nxt - _frm);
3114 to_nxt = to + (_to_nxt - _to);
3115 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003116}
3117
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003118__codecvt_utf8<wchar_t>::result
3119__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003120 extern_type* to, extern_type*, extern_type*& to_nxt) const
3121{
3122 to_nxt = to;
3123 return noconv;
3124}
3125
3126int
Howard Hinnantc9834542011-05-31 15:34:58 +00003127__codecvt_utf8<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003128{
3129 return 0;
3130}
3131
3132bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003133__codecvt_utf8<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003134{
3135 return false;
3136}
3137
3138int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003139__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003140 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3141{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003142 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3143 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3144 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003145}
3146
3147int
Howard Hinnantc9834542011-05-31 15:34:58 +00003148__codecvt_utf8<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003149{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003150 if (_Mode_ & consume_header)
3151 return 7;
3152 return 4;
3153}
3154
3155// __codecvt_utf8<char16_t>
3156
3157__codecvt_utf8<char16_t>::result
3158__codecvt_utf8<char16_t>::do_out(state_type&,
3159 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3160 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3161{
3162 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3163 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3164 const uint16_t* _frm_nxt = _frm;
3165 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3166 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3167 uint8_t* _to_nxt = _to;
3168 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3169 _Maxcode_, _Mode_);
3170 frm_nxt = frm + (_frm_nxt - _frm);
3171 to_nxt = to + (_to_nxt - _to);
3172 return r;
3173}
3174
3175__codecvt_utf8<char16_t>::result
3176__codecvt_utf8<char16_t>::do_in(state_type&,
3177 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3178 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3179{
3180 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3181 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3182 const uint8_t* _frm_nxt = _frm;
3183 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3184 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3185 uint16_t* _to_nxt = _to;
3186 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3187 _Maxcode_, _Mode_);
3188 frm_nxt = frm + (_frm_nxt - _frm);
3189 to_nxt = to + (_to_nxt - _to);
3190 return r;
3191}
3192
3193__codecvt_utf8<char16_t>::result
3194__codecvt_utf8<char16_t>::do_unshift(state_type&,
3195 extern_type* to, extern_type*, extern_type*& to_nxt) const
3196{
3197 to_nxt = to;
3198 return noconv;
3199}
3200
3201int
Howard Hinnantc9834542011-05-31 15:34:58 +00003202__codecvt_utf8<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003203{
3204 return 0;
3205}
3206
3207bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003208__codecvt_utf8<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003209{
3210 return false;
3211}
3212
3213int
3214__codecvt_utf8<char16_t>::do_length(state_type&,
3215 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3216{
3217 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3218 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3219 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3220}
3221
3222int
Howard Hinnantc9834542011-05-31 15:34:58 +00003223__codecvt_utf8<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003224{
3225 if (_Mode_ & consume_header)
3226 return 6;
3227 return 3;
3228}
3229
3230// __codecvt_utf8<char32_t>
3231
3232__codecvt_utf8<char32_t>::result
3233__codecvt_utf8<char32_t>::do_out(state_type&,
3234 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3235 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3236{
3237 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3238 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3239 const uint32_t* _frm_nxt = _frm;
3240 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3241 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3242 uint8_t* _to_nxt = _to;
3243 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3244 _Maxcode_, _Mode_);
3245 frm_nxt = frm + (_frm_nxt - _frm);
3246 to_nxt = to + (_to_nxt - _to);
3247 return r;
3248}
3249
3250__codecvt_utf8<char32_t>::result
3251__codecvt_utf8<char32_t>::do_in(state_type&,
3252 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3253 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3254{
3255 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3256 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3257 const uint8_t* _frm_nxt = _frm;
3258 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3259 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3260 uint32_t* _to_nxt = _to;
3261 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3262 _Maxcode_, _Mode_);
3263 frm_nxt = frm + (_frm_nxt - _frm);
3264 to_nxt = to + (_to_nxt - _to);
3265 return r;
3266}
3267
3268__codecvt_utf8<char32_t>::result
3269__codecvt_utf8<char32_t>::do_unshift(state_type&,
3270 extern_type* to, extern_type*, extern_type*& to_nxt) const
3271{
3272 to_nxt = to;
3273 return noconv;
3274}
3275
3276int
Howard Hinnantc9834542011-05-31 15:34:58 +00003277__codecvt_utf8<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003278{
3279 return 0;
3280}
3281
3282bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003283__codecvt_utf8<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003284{
3285 return false;
3286}
3287
3288int
3289__codecvt_utf8<char32_t>::do_length(state_type&,
3290 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3291{
3292 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3293 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3294 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3295}
3296
3297int
Howard Hinnantc9834542011-05-31 15:34:58 +00003298__codecvt_utf8<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003299{
3300 if (_Mode_ & consume_header)
3301 return 7;
3302 return 4;
3303}
3304
3305// __codecvt_utf16<wchar_t, false>
3306
3307__codecvt_utf16<wchar_t, false>::result
3308__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3309 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3310 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3311{
3312 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3313 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3314 const uint32_t* _frm_nxt = _frm;
3315 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3316 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3317 uint8_t* _to_nxt = _to;
3318 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3319 _Maxcode_, _Mode_);
3320 frm_nxt = frm + (_frm_nxt - _frm);
3321 to_nxt = to + (_to_nxt - _to);
3322 return r;
3323}
3324
3325__codecvt_utf16<wchar_t, false>::result
3326__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3327 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3328 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3329{
3330 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3331 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3332 const uint8_t* _frm_nxt = _frm;
3333 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3334 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3335 uint32_t* _to_nxt = _to;
3336 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3337 _Maxcode_, _Mode_);
3338 frm_nxt = frm + (_frm_nxt - _frm);
3339 to_nxt = to + (_to_nxt - _to);
3340 return r;
3341}
3342
3343__codecvt_utf16<wchar_t, false>::result
3344__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3345 extern_type* to, extern_type*, extern_type*& to_nxt) const
3346{
3347 to_nxt = to;
3348 return noconv;
3349}
3350
3351int
Howard Hinnantc9834542011-05-31 15:34:58 +00003352__codecvt_utf16<wchar_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003353{
3354 return 0;
3355}
3356
3357bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003358__codecvt_utf16<wchar_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003359{
3360 return false;
3361}
3362
3363int
3364__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3365 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3366{
3367 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3368 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3369 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3370}
3371
3372int
Howard Hinnantc9834542011-05-31 15:34:58 +00003373__codecvt_utf16<wchar_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003374{
3375 if (_Mode_ & consume_header)
3376 return 6;
3377 return 4;
3378}
3379
3380// __codecvt_utf16<wchar_t, true>
3381
3382__codecvt_utf16<wchar_t, true>::result
3383__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3384 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3385 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3386{
3387 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3388 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3389 const uint32_t* _frm_nxt = _frm;
3390 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3391 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3392 uint8_t* _to_nxt = _to;
3393 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3394 _Maxcode_, _Mode_);
3395 frm_nxt = frm + (_frm_nxt - _frm);
3396 to_nxt = to + (_to_nxt - _to);
3397 return r;
3398}
3399
3400__codecvt_utf16<wchar_t, true>::result
3401__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3402 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3403 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3404{
3405 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3406 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3407 const uint8_t* _frm_nxt = _frm;
3408 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3409 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3410 uint32_t* _to_nxt = _to;
3411 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3412 _Maxcode_, _Mode_);
3413 frm_nxt = frm + (_frm_nxt - _frm);
3414 to_nxt = to + (_to_nxt - _to);
3415 return r;
3416}
3417
3418__codecvt_utf16<wchar_t, true>::result
3419__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3420 extern_type* to, extern_type*, extern_type*& to_nxt) const
3421{
3422 to_nxt = to;
3423 return noconv;
3424}
3425
3426int
Howard Hinnantc9834542011-05-31 15:34:58 +00003427__codecvt_utf16<wchar_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003428{
3429 return 0;
3430}
3431
3432bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003433__codecvt_utf16<wchar_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003434{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003435 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003436}
3437
3438int
3439__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3440 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3441{
3442 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3443 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3444 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3445}
3446
3447int
Howard Hinnantc9834542011-05-31 15:34:58 +00003448__codecvt_utf16<wchar_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003449{
3450 if (_Mode_ & consume_header)
3451 return 6;
3452 return 4;
3453}
3454
3455// __codecvt_utf16<char16_t, false>
3456
3457__codecvt_utf16<char16_t, false>::result
3458__codecvt_utf16<char16_t, false>::do_out(state_type&,
3459 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3460 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3461{
3462 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3463 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3464 const uint16_t* _frm_nxt = _frm;
3465 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3466 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3467 uint8_t* _to_nxt = _to;
3468 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3469 _Maxcode_, _Mode_);
3470 frm_nxt = frm + (_frm_nxt - _frm);
3471 to_nxt = to + (_to_nxt - _to);
3472 return r;
3473}
3474
3475__codecvt_utf16<char16_t, false>::result
3476__codecvt_utf16<char16_t, false>::do_in(state_type&,
3477 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3478 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3479{
3480 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3481 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3482 const uint8_t* _frm_nxt = _frm;
3483 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3484 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3485 uint16_t* _to_nxt = _to;
3486 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3487 _Maxcode_, _Mode_);
3488 frm_nxt = frm + (_frm_nxt - _frm);
3489 to_nxt = to + (_to_nxt - _to);
3490 return r;
3491}
3492
3493__codecvt_utf16<char16_t, false>::result
3494__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3495 extern_type* to, extern_type*, extern_type*& to_nxt) const
3496{
3497 to_nxt = to;
3498 return noconv;
3499}
3500
3501int
Howard Hinnantc9834542011-05-31 15:34:58 +00003502__codecvt_utf16<char16_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003503{
3504 return 0;
3505}
3506
3507bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003508__codecvt_utf16<char16_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003509{
3510 return false;
3511}
3512
3513int
3514__codecvt_utf16<char16_t, false>::do_length(state_type&,
3515 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3516{
3517 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3518 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3519 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3520}
3521
3522int
Howard Hinnantc9834542011-05-31 15:34:58 +00003523__codecvt_utf16<char16_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003524{
3525 if (_Mode_ & consume_header)
3526 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003527 return 2;
3528}
3529
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003530// __codecvt_utf16<char16_t, true>
3531
3532__codecvt_utf16<char16_t, true>::result
3533__codecvt_utf16<char16_t, true>::do_out(state_type&,
3534 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3535 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3536{
3537 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3538 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3539 const uint16_t* _frm_nxt = _frm;
3540 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3541 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3542 uint8_t* _to_nxt = _to;
3543 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3544 _Maxcode_, _Mode_);
3545 frm_nxt = frm + (_frm_nxt - _frm);
3546 to_nxt = to + (_to_nxt - _to);
3547 return r;
3548}
3549
3550__codecvt_utf16<char16_t, true>::result
3551__codecvt_utf16<char16_t, true>::do_in(state_type&,
3552 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3553 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3554{
3555 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3556 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3557 const uint8_t* _frm_nxt = _frm;
3558 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3559 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3560 uint16_t* _to_nxt = _to;
3561 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3562 _Maxcode_, _Mode_);
3563 frm_nxt = frm + (_frm_nxt - _frm);
3564 to_nxt = to + (_to_nxt - _to);
3565 return r;
3566}
3567
3568__codecvt_utf16<char16_t, true>::result
3569__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3570 extern_type* to, extern_type*, extern_type*& to_nxt) const
3571{
3572 to_nxt = to;
3573 return noconv;
3574}
3575
3576int
Howard Hinnantc9834542011-05-31 15:34:58 +00003577__codecvt_utf16<char16_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003578{
3579 return 0;
3580}
3581
3582bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003583__codecvt_utf16<char16_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003584{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003585 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003586}
3587
3588int
3589__codecvt_utf16<char16_t, true>::do_length(state_type&,
3590 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3591{
3592 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3593 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3594 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3595}
3596
3597int
Howard Hinnantc9834542011-05-31 15:34:58 +00003598__codecvt_utf16<char16_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003599{
3600 if (_Mode_ & consume_header)
3601 return 4;
3602 return 2;
3603}
3604
3605// __codecvt_utf16<char32_t, false>
3606
3607__codecvt_utf16<char32_t, false>::result
3608__codecvt_utf16<char32_t, false>::do_out(state_type&,
3609 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3610 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3611{
3612 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3613 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3614 const uint32_t* _frm_nxt = _frm;
3615 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3616 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3617 uint8_t* _to_nxt = _to;
3618 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3619 _Maxcode_, _Mode_);
3620 frm_nxt = frm + (_frm_nxt - _frm);
3621 to_nxt = to + (_to_nxt - _to);
3622 return r;
3623}
3624
3625__codecvt_utf16<char32_t, false>::result
3626__codecvt_utf16<char32_t, false>::do_in(state_type&,
3627 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3628 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3629{
3630 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3631 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3632 const uint8_t* _frm_nxt = _frm;
3633 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3634 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3635 uint32_t* _to_nxt = _to;
3636 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3637 _Maxcode_, _Mode_);
3638 frm_nxt = frm + (_frm_nxt - _frm);
3639 to_nxt = to + (_to_nxt - _to);
3640 return r;
3641}
3642
3643__codecvt_utf16<char32_t, false>::result
3644__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3645 extern_type* to, extern_type*, extern_type*& to_nxt) const
3646{
3647 to_nxt = to;
3648 return noconv;
3649}
3650
3651int
Howard Hinnantc9834542011-05-31 15:34:58 +00003652__codecvt_utf16<char32_t, false>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003653{
3654 return 0;
3655}
3656
3657bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003658__codecvt_utf16<char32_t, false>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003659{
3660 return false;
3661}
3662
3663int
3664__codecvt_utf16<char32_t, false>::do_length(state_type&,
3665 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3666{
3667 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3668 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3669 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3670}
3671
3672int
Howard Hinnantc9834542011-05-31 15:34:58 +00003673__codecvt_utf16<char32_t, false>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003674{
3675 if (_Mode_ & consume_header)
3676 return 6;
3677 return 4;
3678}
3679
3680// __codecvt_utf16<char32_t, true>
3681
3682__codecvt_utf16<char32_t, true>::result
3683__codecvt_utf16<char32_t, true>::do_out(state_type&,
3684 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3685 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3686{
3687 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3688 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3689 const uint32_t* _frm_nxt = _frm;
3690 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3691 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3692 uint8_t* _to_nxt = _to;
3693 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3694 _Maxcode_, _Mode_);
3695 frm_nxt = frm + (_frm_nxt - _frm);
3696 to_nxt = to + (_to_nxt - _to);
3697 return r;
3698}
3699
3700__codecvt_utf16<char32_t, true>::result
3701__codecvt_utf16<char32_t, true>::do_in(state_type&,
3702 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3703 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3704{
3705 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3706 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3707 const uint8_t* _frm_nxt = _frm;
3708 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3709 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3710 uint32_t* _to_nxt = _to;
3711 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3712 _Maxcode_, _Mode_);
3713 frm_nxt = frm + (_frm_nxt - _frm);
3714 to_nxt = to + (_to_nxt - _to);
3715 return r;
3716}
3717
3718__codecvt_utf16<char32_t, true>::result
3719__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3720 extern_type* to, extern_type*, extern_type*& to_nxt) const
3721{
3722 to_nxt = to;
3723 return noconv;
3724}
3725
3726int
Howard Hinnantc9834542011-05-31 15:34:58 +00003727__codecvt_utf16<char32_t, true>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003728{
3729 return 0;
3730}
3731
3732bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003733__codecvt_utf16<char32_t, true>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003734{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003735 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003736}
3737
3738int
3739__codecvt_utf16<char32_t, true>::do_length(state_type&,
3740 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3741{
3742 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3743 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3744 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3745}
3746
3747int
Howard Hinnantc9834542011-05-31 15:34:58 +00003748__codecvt_utf16<char32_t, true>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003749{
3750 if (_Mode_ & consume_header)
3751 return 6;
3752 return 4;
3753}
3754
3755// __codecvt_utf8_utf16<wchar_t>
3756
3757__codecvt_utf8_utf16<wchar_t>::result
3758__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3759 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3760 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3761{
3762 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3763 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3764 const uint32_t* _frm_nxt = _frm;
3765 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3766 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3767 uint8_t* _to_nxt = _to;
3768 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3769 _Maxcode_, _Mode_);
3770 frm_nxt = frm + (_frm_nxt - _frm);
3771 to_nxt = to + (_to_nxt - _to);
3772 return r;
3773}
3774
3775__codecvt_utf8_utf16<wchar_t>::result
3776__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3777 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3778 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3779{
3780 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3781 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3782 const uint8_t* _frm_nxt = _frm;
3783 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3784 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3785 uint32_t* _to_nxt = _to;
3786 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3787 _Maxcode_, _Mode_);
3788 frm_nxt = frm + (_frm_nxt - _frm);
3789 to_nxt = to + (_to_nxt - _to);
3790 return r;
3791}
3792
3793__codecvt_utf8_utf16<wchar_t>::result
3794__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3795 extern_type* to, extern_type*, extern_type*& to_nxt) const
3796{
3797 to_nxt = to;
3798 return noconv;
3799}
3800
3801int
Howard Hinnantc9834542011-05-31 15:34:58 +00003802__codecvt_utf8_utf16<wchar_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003803{
3804 return 0;
3805}
3806
3807bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003808__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003809{
3810 return false;
3811}
3812
3813int
3814__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3815 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3816{
3817 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3818 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3819 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3820}
3821
3822int
Howard Hinnantc9834542011-05-31 15:34:58 +00003823__codecvt_utf8_utf16<wchar_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003824{
3825 if (_Mode_ & consume_header)
3826 return 7;
3827 return 4;
3828}
3829
3830// __codecvt_utf8_utf16<char16_t>
3831
3832__codecvt_utf8_utf16<char16_t>::result
3833__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3834 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3835 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3836{
3837 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3838 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3839 const uint16_t* _frm_nxt = _frm;
3840 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3841 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3842 uint8_t* _to_nxt = _to;
3843 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3844 _Maxcode_, _Mode_);
3845 frm_nxt = frm + (_frm_nxt - _frm);
3846 to_nxt = to + (_to_nxt - _to);
3847 return r;
3848}
3849
3850__codecvt_utf8_utf16<char16_t>::result
3851__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3852 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3853 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3854{
3855 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3856 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3857 const uint8_t* _frm_nxt = _frm;
3858 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3859 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3860 uint16_t* _to_nxt = _to;
3861 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3862 _Maxcode_, _Mode_);
3863 frm_nxt = frm + (_frm_nxt - _frm);
3864 to_nxt = to + (_to_nxt - _to);
3865 return r;
3866}
3867
3868__codecvt_utf8_utf16<char16_t>::result
3869__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3870 extern_type* to, extern_type*, extern_type*& to_nxt) const
3871{
3872 to_nxt = to;
3873 return noconv;
3874}
3875
3876int
Howard Hinnantc9834542011-05-31 15:34:58 +00003877__codecvt_utf8_utf16<char16_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003878{
3879 return 0;
3880}
3881
3882bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003883__codecvt_utf8_utf16<char16_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003884{
3885 return false;
3886}
3887
3888int
3889__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3890 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3891{
3892 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3893 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3894 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3895}
3896
3897int
Howard Hinnantc9834542011-05-31 15:34:58 +00003898__codecvt_utf8_utf16<char16_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003899{
3900 if (_Mode_ & consume_header)
3901 return 7;
3902 return 4;
3903}
3904
3905// __codecvt_utf8_utf16<char32_t>
3906
3907__codecvt_utf8_utf16<char32_t>::result
3908__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3909 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3910 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3911{
3912 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3913 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3914 const uint32_t* _frm_nxt = _frm;
3915 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3916 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3917 uint8_t* _to_nxt = _to;
3918 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3919 _Maxcode_, _Mode_);
3920 frm_nxt = frm + (_frm_nxt - _frm);
3921 to_nxt = to + (_to_nxt - _to);
3922 return r;
3923}
3924
3925__codecvt_utf8_utf16<char32_t>::result
3926__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3927 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3928 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3929{
3930 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3931 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3932 const uint8_t* _frm_nxt = _frm;
3933 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3934 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3935 uint32_t* _to_nxt = _to;
3936 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3937 _Maxcode_, _Mode_);
3938 frm_nxt = frm + (_frm_nxt - _frm);
3939 to_nxt = to + (_to_nxt - _to);
3940 return r;
3941}
3942
3943__codecvt_utf8_utf16<char32_t>::result
3944__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
3945 extern_type* to, extern_type*, extern_type*& to_nxt) const
3946{
3947 to_nxt = to;
3948 return noconv;
3949}
3950
3951int
Howard Hinnantc9834542011-05-31 15:34:58 +00003952__codecvt_utf8_utf16<char32_t>::do_encoding() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003953{
3954 return 0;
3955}
3956
3957bool
Howard Hinnantc9834542011-05-31 15:34:58 +00003958__codecvt_utf8_utf16<char32_t>::do_always_noconv() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003959{
3960 return false;
3961}
3962
3963int
3964__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
3965 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3966{
3967 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3968 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3969 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3970}
3971
3972int
Howard Hinnantc9834542011-05-31 15:34:58 +00003973__codecvt_utf8_utf16<char32_t>::do_max_length() const _NOEXCEPT
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003974{
3975 if (_Mode_ & consume_header)
3976 return 7;
3977 return 4;
3978}
3979
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003980// __narrow_to_utf8<16>
3981
3982__narrow_to_utf8<16>::~__narrow_to_utf8()
3983{
3984}
3985
3986// __narrow_to_utf8<32>
3987
3988__narrow_to_utf8<32>::~__narrow_to_utf8()
3989{
3990}
3991
3992// __widen_from_utf8<16>
3993
3994__widen_from_utf8<16>::~__widen_from_utf8()
3995{
3996}
3997
3998// __widen_from_utf8<32>
3999
4000__widen_from_utf8<32>::~__widen_from_utf8()
4001{
4002}
4003
4004// numpunct<char> && numpunct<wchar_t>
4005
4006locale::id numpunct< char >::id;
4007locale::id numpunct<wchar_t>::id;
4008
4009numpunct<char>::numpunct(size_t refs)
4010 : locale::facet(refs),
4011 __decimal_point_('.'),
4012 __thousands_sep_(',')
4013{
4014}
4015
4016numpunct<wchar_t>::numpunct(size_t refs)
4017 : locale::facet(refs),
4018 __decimal_point_(L'.'),
4019 __thousands_sep_(L',')
4020{
4021}
4022
4023numpunct<char>::~numpunct()
4024{
4025}
4026
4027numpunct<wchar_t>::~numpunct()
4028{
4029}
4030
4031 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
4032wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
4033
4034 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
4035wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
4036
4037string numpunct< char >::do_grouping() const {return __grouping_;}
4038string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
4039
4040 string numpunct< char >::do_truename() const {return "true";}
4041wstring numpunct<wchar_t>::do_truename() const {return L"true";}
4042
4043 string numpunct< char >::do_falsename() const {return "false";}
4044wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
4045
4046// numpunct_byname<char>
4047
4048numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
4049 : numpunct<char>(refs)
4050{
4051 __init(nm);
4052}
4053
4054numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
4055 : numpunct<char>(refs)
4056{
4057 __init(nm.c_str());
4058}
4059
4060numpunct_byname<char>::~numpunct_byname()
4061{
4062}
4063
4064void
4065numpunct_byname<char>::__init(const char* nm)
4066{
4067 if (strcmp(nm, "C") != 0)
4068 {
Sean Huntf3907e62011-07-15 05:40:33 +00004069 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004070#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004071 if (loc == 0)
4072 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4073 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004074#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004075#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004076 lconv* lc = localeconv_l(loc.get());
4077#else
4078 lconv* lc = __localeconv_l(loc.get());
4079#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004080 if (*lc->decimal_point)
4081 __decimal_point_ = *lc->decimal_point;
4082 if (*lc->thousands_sep)
4083 __thousands_sep_ = *lc->thousands_sep;
4084 __grouping_ = lc->grouping;
Sean Huntcb05a082011-07-07 22:45:07 +00004085 // localization for truename and falsename is not available
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004086 }
4087}
4088
4089// numpunct_byname<wchar_t>
4090
4091numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
4092 : numpunct<wchar_t>(refs)
4093{
4094 __init(nm);
4095}
4096
4097numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
4098 : numpunct<wchar_t>(refs)
4099{
4100 __init(nm.c_str());
4101}
4102
4103numpunct_byname<wchar_t>::~numpunct_byname()
4104{
4105}
4106
4107void
4108numpunct_byname<wchar_t>::__init(const char* nm)
4109{
4110 if (strcmp(nm, "C") != 0)
4111 {
Sean Huntf3907e62011-07-15 05:40:33 +00004112 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00004113#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004114 if (loc == 0)
4115 throw runtime_error("numpunct_byname<char>::numpunct_byname"
4116 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004117#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00004118#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004119 lconv* lc = localeconv_l(loc.get());
4120#else
4121 lconv* lc = __localeconv_l(loc.get());
4122#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004123 if (*lc->decimal_point)
4124 __decimal_point_ = *lc->decimal_point;
4125 if (*lc->thousands_sep)
4126 __thousands_sep_ = *lc->thousands_sep;
4127 __grouping_ = lc->grouping;
4128 // locallization for truename and falsename is not available
4129 }
4130}
4131
4132// num_get helpers
4133
4134int
4135__num_get_base::__get_base(ios_base& iob)
4136{
4137 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
4138 if (__basefield == ios_base::oct)
4139 return 8;
4140 else if (__basefield == ios_base::hex)
4141 return 16;
4142 else if (__basefield == 0)
4143 return 0;
4144 return 10;
4145}
4146
4147const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
4148
4149void
4150__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
4151 ios_base::iostate& __err)
4152{
4153 if (__grouping.size() != 0)
4154 {
4155 reverse(__g, __g_end);
4156 const char* __ig = __grouping.data();
4157 const char* __eg = __ig + __grouping.size();
4158 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
4159 {
4160 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4161 {
4162 if (*__ig != *__r)
4163 {
4164 __err = ios_base::failbit;
4165 return;
4166 }
4167 }
4168 if (__eg - __ig > 1)
4169 ++__ig;
4170 }
4171 if (0 < *__ig && *__ig < numeric_limits<char>::max())
4172 {
4173 if (*__ig < __g_end[-1] || __g_end[-1] == 0)
4174 __err = ios_base::failbit;
4175 }
4176 }
4177}
4178
4179void
4180__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
4181 ios_base::fmtflags __flags)
4182{
4183 if (__flags & ios_base::showpos)
4184 *__fmtp++ = '+';
4185 if (__flags & ios_base::showbase)
4186 *__fmtp++ = '#';
4187 while(*__len)
4188 *__fmtp++ = *__len++;
4189 if ((__flags & ios_base::basefield) == ios_base::oct)
4190 *__fmtp = 'o';
4191 else if ((__flags & ios_base::basefield) == ios_base::hex)
4192 {
4193 if (__flags & ios_base::uppercase)
4194 *__fmtp = 'X';
4195 else
4196 *__fmtp = 'x';
4197 }
4198 else if (__signd)
4199 *__fmtp = 'd';
4200 else
4201 *__fmtp = 'u';
4202}
4203
4204bool
4205__num_put_base::__format_float(char* __fmtp, const char* __len,
4206 ios_base::fmtflags __flags)
4207{
4208 bool specify_precision = true;
4209 if (__flags & ios_base::showpos)
4210 *__fmtp++ = '+';
4211 if (__flags & ios_base::showpoint)
4212 *__fmtp++ = '#';
4213 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4214 bool uppercase = __flags & ios_base::uppercase;
4215 if (floatfield == (ios_base::fixed | ios_base::scientific))
4216 specify_precision = false;
4217 else
4218 {
4219 *__fmtp++ = '.';
4220 *__fmtp++ = '*';
4221 }
4222 while(*__len)
4223 *__fmtp++ = *__len++;
4224 if (floatfield == ios_base::fixed)
4225 {
4226 if (uppercase)
4227 *__fmtp = 'F';
4228 else
4229 *__fmtp = 'f';
4230 }
4231 else if (floatfield == ios_base::scientific)
4232 {
4233 if (uppercase)
4234 *__fmtp = 'E';
4235 else
4236 *__fmtp = 'e';
4237 }
4238 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4239 {
4240 if (uppercase)
4241 *__fmtp = 'A';
4242 else
4243 *__fmtp = 'a';
4244 }
4245 else
4246 {
4247 if (uppercase)
4248 *__fmtp = 'G';
4249 else
4250 *__fmtp = 'g';
4251 }
4252 return specify_precision;
4253}
4254
4255char*
4256__num_put_base::__identify_padding(char* __nb, char* __ne,
4257 const ios_base& __iob)
4258{
4259 switch (__iob.flags() & ios_base::adjustfield)
4260 {
4261 case ios_base::internal:
4262 if (__nb[0] == '-' || __nb[0] == '+')
4263 return __nb+1;
4264 if (__ne - __nb >= 2 && __nb[0] == '0'
4265 && (__nb[1] == 'x' || __nb[1] == 'X'))
4266 return __nb+2;
4267 break;
4268 case ios_base::left:
4269 return __ne;
4270 case ios_base::right:
4271 default:
4272 break;
4273 }
4274 return __nb;
4275}
4276
4277// time_get
4278
4279static
4280string*
4281init_weeks()
4282{
4283 static string weeks[14];
4284 weeks[0] = "Sunday";
4285 weeks[1] = "Monday";
4286 weeks[2] = "Tuesday";
4287 weeks[3] = "Wednesday";
4288 weeks[4] = "Thursday";
4289 weeks[5] = "Friday";
4290 weeks[6] = "Saturday";
4291 weeks[7] = "Sun";
4292 weeks[8] = "Mon";
4293 weeks[9] = "Tue";
4294 weeks[10] = "Wed";
4295 weeks[11] = "Thu";
4296 weeks[12] = "Fri";
4297 weeks[13] = "Sat";
4298 return weeks;
4299}
4300
4301static
4302wstring*
4303init_wweeks()
4304{
4305 static wstring weeks[14];
4306 weeks[0] = L"Sunday";
4307 weeks[1] = L"Monday";
4308 weeks[2] = L"Tuesday";
4309 weeks[3] = L"Wednesday";
4310 weeks[4] = L"Thursday";
4311 weeks[5] = L"Friday";
4312 weeks[6] = L"Saturday";
4313 weeks[7] = L"Sun";
4314 weeks[8] = L"Mon";
4315 weeks[9] = L"Tue";
4316 weeks[10] = L"Wed";
4317 weeks[11] = L"Thu";
4318 weeks[12] = L"Fri";
4319 weeks[13] = L"Sat";
4320 return weeks;
4321}
4322
4323template <>
4324const string*
4325__time_get_c_storage<char>::__weeks() const
4326{
4327 static const string* weeks = init_weeks();
4328 return weeks;
4329}
4330
4331template <>
4332const wstring*
4333__time_get_c_storage<wchar_t>::__weeks() const
4334{
4335 static const wstring* weeks = init_wweeks();
4336 return weeks;
4337}
4338
4339static
4340string*
4341init_months()
4342{
4343 static string months[24];
4344 months[0] = "January";
4345 months[1] = "February";
4346 months[2] = "March";
4347 months[3] = "April";
4348 months[4] = "May";
4349 months[5] = "June";
4350 months[6] = "July";
4351 months[7] = "August";
4352 months[8] = "September";
4353 months[9] = "October";
4354 months[10] = "November";
4355 months[11] = "December";
4356 months[12] = "Jan";
4357 months[13] = "Feb";
4358 months[14] = "Mar";
4359 months[15] = "Apr";
4360 months[16] = "May";
4361 months[17] = "Jun";
4362 months[18] = "Jul";
4363 months[19] = "Aug";
4364 months[20] = "Sep";
4365 months[21] = "Oct";
4366 months[22] = "Nov";
4367 months[23] = "Dec";
4368 return months;
4369}
4370
4371static
4372wstring*
4373init_wmonths()
4374{
4375 static wstring months[24];
4376 months[0] = L"January";
4377 months[1] = L"February";
4378 months[2] = L"March";
4379 months[3] = L"April";
4380 months[4] = L"May";
4381 months[5] = L"June";
4382 months[6] = L"July";
4383 months[7] = L"August";
4384 months[8] = L"September";
4385 months[9] = L"October";
4386 months[10] = L"November";
4387 months[11] = L"December";
4388 months[12] = L"Jan";
4389 months[13] = L"Feb";
4390 months[14] = L"Mar";
4391 months[15] = L"Apr";
4392 months[16] = L"May";
4393 months[17] = L"Jun";
4394 months[18] = L"Jul";
4395 months[19] = L"Aug";
4396 months[20] = L"Sep";
4397 months[21] = L"Oct";
4398 months[22] = L"Nov";
4399 months[23] = L"Dec";
4400 return months;
4401}
4402
4403template <>
4404const string*
4405__time_get_c_storage<char>::__months() const
4406{
4407 static const string* months = init_months();
4408 return months;
4409}
4410
4411template <>
4412const wstring*
4413__time_get_c_storage<wchar_t>::__months() const
4414{
4415 static const wstring* months = init_wmonths();
4416 return months;
4417}
4418
4419static
4420string*
4421init_am_pm()
4422{
4423 static string am_pm[24];
4424 am_pm[0] = "AM";
4425 am_pm[1] = "PM";
4426 return am_pm;
4427}
4428
4429static
4430wstring*
4431init_wam_pm()
4432{
4433 static wstring am_pm[24];
4434 am_pm[0] = L"AM";
4435 am_pm[1] = L"PM";
4436 return am_pm;
4437}
4438
4439template <>
4440const string*
4441__time_get_c_storage<char>::__am_pm() const
4442{
4443 static const string* am_pm = init_am_pm();
4444 return am_pm;
4445}
4446
4447template <>
4448const wstring*
4449__time_get_c_storage<wchar_t>::__am_pm() const
4450{
4451 static const wstring* am_pm = init_wam_pm();
4452 return am_pm;
4453}
4454
4455template <>
4456const string&
4457__time_get_c_storage<char>::__x() const
4458{
4459 static string s("%m/%d/%y");
4460 return s;
4461}
4462
4463template <>
4464const wstring&
4465__time_get_c_storage<wchar_t>::__x() const
4466{
4467 static wstring s(L"%m/%d/%y");
4468 return s;
4469}
4470
4471template <>
4472const string&
4473__time_get_c_storage<char>::__X() const
4474{
4475 static string s("%H:%M:%S");
4476 return s;
4477}
4478
4479template <>
4480const wstring&
4481__time_get_c_storage<wchar_t>::__X() const
4482{
4483 static wstring s(L"%H:%M:%S");
4484 return s;
4485}
4486
4487template <>
4488const string&
4489__time_get_c_storage<char>::__c() const
4490{
4491 static string s("%a %b %d %H:%M:%S %Y");
4492 return s;
4493}
4494
4495template <>
4496const wstring&
4497__time_get_c_storage<wchar_t>::__c() const
4498{
4499 static wstring s(L"%a %b %d %H:%M:%S %Y");
4500 return s;
4501}
4502
4503template <>
4504const string&
4505__time_get_c_storage<char>::__r() const
4506{
4507 static string s("%I:%M:%S %p");
4508 return s;
4509}
4510
4511template <>
4512const wstring&
4513__time_get_c_storage<wchar_t>::__r() const
4514{
4515 static wstring s(L"%I:%M:%S %p");
4516 return s;
4517}
4518
4519// time_get_byname
4520
4521__time_get::__time_get(const char* nm)
4522 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4523{
Howard Hinnantd4444702010-08-11 17:04:31 +00004524#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004525 if (__loc_ == 0)
4526 throw runtime_error("time_get_byname"
4527 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004528#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004529}
4530
4531__time_get::__time_get(const string& nm)
4532 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4533{
Howard Hinnantd4444702010-08-11 17:04:31 +00004534#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004535 if (__loc_ == 0)
4536 throw runtime_error("time_get_byname"
4537 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004538#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004539}
4540
4541__time_get::~__time_get()
4542{
4543 freelocale(__loc_);
4544}
4545
4546template <>
4547string
4548__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4549{
4550 tm t;
4551 t.tm_sec = 59;
4552 t.tm_min = 55;
4553 t.tm_hour = 23;
4554 t.tm_mday = 31;
4555 t.tm_mon = 11;
4556 t.tm_year = 161;
4557 t.tm_wday = 6;
4558 t.tm_yday = 364;
4559 t.tm_isdst = -1;
4560 char buf[100];
4561 char f[3] = {0};
4562 f[0] = '%';
4563 f[1] = fmt;
4564 size_t n = strftime_l(buf, 100, f, &t, __loc_);
4565 char* bb = buf;
4566 char* be = buf + n;
4567 string result;
4568 while (bb != be)
4569 {
4570 if (ct.is(ctype_base::space, *bb))
4571 {
4572 result.push_back(' ');
4573 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4574 ;
4575 continue;
4576 }
4577 char* w = bb;
4578 ios_base::iostate err = ios_base::goodbit;
4579 int i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
4580 ct, err, false)
4581 - this->__weeks_;
4582 if (i < 14)
4583 {
4584 result.push_back('%');
4585 if (i < 7)
4586 result.push_back('A');
4587 else
4588 result.push_back('a');
4589 bb = w;
4590 continue;
4591 }
4592 w = bb;
4593 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4594 ct, err, false)
4595 - this->__months_;
4596 if (i < 24)
4597 {
4598 result.push_back('%');
4599 if (i < 12)
4600 result.push_back('B');
4601 else
4602 result.push_back('b');
4603 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4604 result.back() = 'm';
4605 bb = w;
4606 continue;
4607 }
4608 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4609 {
4610 w = bb;
4611 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4612 ct, err, false) - this->__am_pm_;
4613 if (i < 2)
4614 {
4615 result.push_back('%');
4616 result.push_back('p');
4617 bb = w;
4618 continue;
4619 }
4620 }
4621 w = bb;
4622 if (ct.is(ctype_base::digit, *bb))
4623 {
4624 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4625 {
4626 case 6:
4627 result.push_back('%');
4628 result.push_back('w');
4629 break;
4630 case 7:
4631 result.push_back('%');
4632 result.push_back('u');
4633 break;
4634 case 11:
4635 result.push_back('%');
4636 result.push_back('I');
4637 break;
4638 case 12:
4639 result.push_back('%');
4640 result.push_back('m');
4641 break;
4642 case 23:
4643 result.push_back('%');
4644 result.push_back('H');
4645 break;
4646 case 31:
4647 result.push_back('%');
4648 result.push_back('d');
4649 break;
4650 case 55:
4651 result.push_back('%');
4652 result.push_back('M');
4653 break;
4654 case 59:
4655 result.push_back('%');
4656 result.push_back('S');
4657 break;
4658 case 61:
4659 result.push_back('%');
4660 result.push_back('y');
4661 break;
4662 case 364:
4663 result.push_back('%');
4664 result.push_back('j');
4665 break;
4666 case 2061:
4667 result.push_back('%');
4668 result.push_back('Y');
4669 break;
4670 default:
4671 for (; w != bb; ++w)
4672 result.push_back(*w);
4673 break;
4674 }
4675 continue;
4676 }
4677 if (*bb == '%')
4678 {
4679 result.push_back('%');
4680 result.push_back('%');
4681 ++bb;
4682 continue;
4683 }
4684 result.push_back(*bb);
4685 ++bb;
4686 }
4687 return result;
4688}
4689
4690template <>
4691wstring
4692__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4693{
4694 tm t;
4695 t.tm_sec = 59;
4696 t.tm_min = 55;
4697 t.tm_hour = 23;
4698 t.tm_mday = 31;
4699 t.tm_mon = 11;
4700 t.tm_year = 161;
4701 t.tm_wday = 6;
4702 t.tm_yday = 364;
4703 t.tm_isdst = -1;
4704 char buf[100];
4705 char f[3] = {0};
4706 f[0] = '%';
4707 f[1] = fmt;
4708 size_t be = strftime_l(buf, 100, f, &t, __loc_);
4709 wchar_t wbuf[100];
4710 wchar_t* wbb = wbuf;
4711 mbstate_t mb = {0};
4712 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004713#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004714 size_t i = mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4715#else
4716 size_t i = __mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4717#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004718 if (i == -1)
4719 __throw_runtime_error("locale not supported");
4720 wchar_t* wbe = wbb + i;
4721 wstring result;
4722 while (wbb != wbe)
4723 {
4724 if (ct.is(ctype_base::space, *wbb))
4725 {
4726 result.push_back(L' ');
4727 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4728 ;
4729 continue;
4730 }
4731 wchar_t* w = wbb;
4732 ios_base::iostate err = ios_base::goodbit;
4733 int i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
4734 ct, err, false)
4735 - this->__weeks_;
4736 if (i < 14)
4737 {
4738 result.push_back(L'%');
4739 if (i < 7)
4740 result.push_back(L'A');
4741 else
4742 result.push_back(L'a');
4743 wbb = w;
4744 continue;
4745 }
4746 w = wbb;
4747 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4748 ct, err, false)
4749 - this->__months_;
4750 if (i < 24)
4751 {
4752 result.push_back(L'%');
4753 if (i < 12)
4754 result.push_back(L'B');
4755 else
4756 result.push_back(L'b');
4757 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4758 result.back() = L'm';
4759 wbb = w;
4760 continue;
4761 }
4762 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4763 {
4764 w = wbb;
4765 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4766 ct, err, false) - this->__am_pm_;
4767 if (i < 2)
4768 {
4769 result.push_back(L'%');
4770 result.push_back(L'p');
4771 wbb = w;
4772 continue;
4773 }
4774 }
4775 w = wbb;
4776 if (ct.is(ctype_base::digit, *wbb))
4777 {
4778 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4779 {
4780 case 6:
4781 result.push_back(L'%');
4782 result.push_back(L'w');
4783 break;
4784 case 7:
4785 result.push_back(L'%');
4786 result.push_back(L'u');
4787 break;
4788 case 11:
4789 result.push_back(L'%');
4790 result.push_back(L'I');
4791 break;
4792 case 12:
4793 result.push_back(L'%');
4794 result.push_back(L'm');
4795 break;
4796 case 23:
4797 result.push_back(L'%');
4798 result.push_back(L'H');
4799 break;
4800 case 31:
4801 result.push_back(L'%');
4802 result.push_back(L'd');
4803 break;
4804 case 55:
4805 result.push_back(L'%');
4806 result.push_back(L'M');
4807 break;
4808 case 59:
4809 result.push_back(L'%');
4810 result.push_back(L'S');
4811 break;
4812 case 61:
4813 result.push_back(L'%');
4814 result.push_back(L'y');
4815 break;
4816 case 364:
4817 result.push_back(L'%');
4818 result.push_back(L'j');
4819 break;
4820 case 2061:
4821 result.push_back(L'%');
4822 result.push_back(L'Y');
4823 break;
4824 default:
4825 for (; w != wbb; ++w)
4826 result.push_back(*w);
4827 break;
4828 }
4829 continue;
4830 }
4831 if (ct.narrow(*wbb, 0) == '%')
4832 {
4833 result.push_back(L'%');
4834 result.push_back(L'%');
4835 ++wbb;
4836 continue;
4837 }
4838 result.push_back(*wbb);
4839 ++wbb;
4840 }
4841 return result;
4842}
4843
4844template <>
4845void
4846__time_get_storage<char>::init(const ctype<char>& ct)
4847{
4848 tm t;
4849 char buf[100];
4850 // __weeks_
4851 for (int i = 0; i < 7; ++i)
4852 {
4853 t.tm_wday = i;
4854 strftime_l(buf, 100, "%A", &t, __loc_);
4855 __weeks_[i] = buf;
4856 strftime_l(buf, 100, "%a", &t, __loc_);
4857 __weeks_[i+7] = buf;
4858 }
4859 // __months_
4860 for (int i = 0; i < 12; ++i)
4861 {
4862 t.tm_mon = i;
4863 strftime_l(buf, 100, "%B", &t, __loc_);
4864 __months_[i] = buf;
4865 strftime_l(buf, 100, "%b", &t, __loc_);
4866 __months_[i+12] = buf;
4867 }
4868 // __am_pm_
4869 t.tm_hour = 1;
4870 strftime_l(buf, 100, "%p", &t, __loc_);
4871 __am_pm_[0] = buf;
4872 t.tm_hour = 13;
4873 strftime_l(buf, 100, "%p", &t, __loc_);
4874 __am_pm_[1] = buf;
4875 __c_ = __analyze('c', ct);
4876 __r_ = __analyze('r', ct);
4877 __x_ = __analyze('x', ct);
4878 __X_ = __analyze('X', ct);
4879}
4880
4881template <>
4882void
4883__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4884{
4885 tm t = {0};
4886 char buf[100];
4887 size_t be;
4888 wchar_t wbuf[100];
4889 wchar_t* wbe;
4890 mbstate_t mb = {0};
4891 // __weeks_
4892 for (int i = 0; i < 7; ++i)
4893 {
4894 t.tm_wday = i;
4895 be = strftime_l(buf, 100, "%A", &t, __loc_);
4896 mb = mbstate_t();
4897 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004898#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004899 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4900#else
4901 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4902#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004903 if (j == -1)
4904 __throw_runtime_error("locale not supported");
4905 wbe = wbuf + j;
4906 __weeks_[i].assign(wbuf, wbe);
4907 be = strftime_l(buf, 100, "%a", &t, __loc_);
4908 mb = mbstate_t();
4909 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004910#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004911 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4912#else
4913 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4914#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004915 if (j == -1)
4916 __throw_runtime_error("locale not supported");
4917 wbe = wbuf + j;
4918 __weeks_[i+7].assign(wbuf, wbe);
4919 }
4920 // __months_
4921 for (int i = 0; i < 12; ++i)
4922 {
4923 t.tm_mon = i;
4924 be = strftime_l(buf, 100, "%B", &t, __loc_);
4925 mb = mbstate_t();
4926 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004927#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004928 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4929#else
4930 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4931#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004932 if (j == -1)
4933 __throw_runtime_error("locale not supported");
4934 wbe = wbuf + j;
4935 __months_[i].assign(wbuf, wbe);
4936 be = strftime_l(buf, 100, "%b", &t, __loc_);
4937 mb = mbstate_t();
4938 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004939#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004940 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4941#else
4942 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4943#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004944 if (j == -1)
4945 __throw_runtime_error("locale not supported");
4946 wbe = wbuf + j;
4947 __months_[i+12].assign(wbuf, wbe);
4948 }
4949 // __am_pm_
4950 t.tm_hour = 1;
4951 be = strftime_l(buf, 100, "%p", &t, __loc_);
4952 mb = mbstate_t();
4953 const char* bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004954#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004955 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4956#else
4957 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4958#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004959 if (j == -1)
4960 __throw_runtime_error("locale not supported");
4961 wbe = wbuf + j;
4962 __am_pm_[0].assign(wbuf, wbe);
4963 t.tm_hour = 13;
4964 be = strftime_l(buf, 100, "%p", &t, __loc_);
4965 mb = mbstate_t();
4966 bb = buf;
Howard Hinnant866569b2011-09-28 23:39:33 +00004967#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00004968 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4969#else
4970 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4971#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004972 if (j == -1)
4973 __throw_runtime_error("locale not supported");
4974 wbe = wbuf + j;
4975 __am_pm_[1].assign(wbuf, wbe);
4976 __c_ = __analyze('c', ct);
4977 __r_ = __analyze('r', ct);
4978 __x_ = __analyze('x', ct);
4979 __X_ = __analyze('X', ct);
4980}
4981
4982template <class CharT>
4983struct _LIBCPP_HIDDEN __time_get_temp
4984 : public ctype_byname<CharT>
4985{
4986 explicit __time_get_temp(const char* nm)
4987 : ctype_byname<CharT>(nm, 1) {}
4988 explicit __time_get_temp(const string& nm)
4989 : ctype_byname<CharT>(nm, 1) {}
4990};
4991
4992template <>
4993__time_get_storage<char>::__time_get_storage(const char* __nm)
4994 : __time_get(__nm)
4995{
4996 const __time_get_temp<char> ct(__nm);
4997 init(ct);
4998}
4999
5000template <>
5001__time_get_storage<char>::__time_get_storage(const string& __nm)
5002 : __time_get(__nm)
5003{
5004 const __time_get_temp<char> ct(__nm);
5005 init(ct);
5006}
5007
5008template <>
5009__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
5010 : __time_get(__nm)
5011{
5012 const __time_get_temp<wchar_t> ct(__nm);
5013 init(ct);
5014}
5015
5016template <>
5017__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
5018 : __time_get(__nm)
5019{
5020 const __time_get_temp<wchar_t> ct(__nm);
5021 init(ct);
5022}
5023
5024template <>
5025time_base::dateorder
5026__time_get_storage<char>::__do_date_order() const
5027{
5028 unsigned i;
5029 for (i = 0; i < __x_.size(); ++i)
5030 if (__x_[i] == '%')
5031 break;
5032 ++i;
5033 switch (__x_[i])
5034 {
5035 case 'y':
5036 case 'Y':
5037 for (++i; i < __x_.size(); ++i)
5038 if (__x_[i] == '%')
5039 break;
5040 if (i == __x_.size())
5041 break;
5042 ++i;
5043 switch (__x_[i])
5044 {
5045 case 'm':
5046 for (++i; i < __x_.size(); ++i)
5047 if (__x_[i] == '%')
5048 break;
5049 if (i == __x_.size())
5050 break;
5051 ++i;
5052 if (__x_[i] == 'd')
5053 return time_base::ymd;
5054 break;
5055 case 'd':
5056 for (++i; i < __x_.size(); ++i)
5057 if (__x_[i] == '%')
5058 break;
5059 if (i == __x_.size())
5060 break;
5061 ++i;
5062 if (__x_[i] == 'm')
5063 return time_base::ydm;
5064 break;
5065 }
5066 break;
5067 case 'm':
5068 for (++i; i < __x_.size(); ++i)
5069 if (__x_[i] == '%')
5070 break;
5071 if (i == __x_.size())
5072 break;
5073 ++i;
5074 if (__x_[i] == 'd')
5075 {
5076 for (++i; i < __x_.size(); ++i)
5077 if (__x_[i] == '%')
5078 break;
5079 if (i == __x_.size())
5080 break;
5081 ++i;
5082 if (__x_[i] == 'y' || __x_[i] == 'Y')
5083 return time_base::mdy;
5084 break;
5085 }
5086 break;
5087 case 'd':
5088 for (++i; i < __x_.size(); ++i)
5089 if (__x_[i] == '%')
5090 break;
5091 if (i == __x_.size())
5092 break;
5093 ++i;
5094 if (__x_[i] == 'm')
5095 {
5096 for (++i; i < __x_.size(); ++i)
5097 if (__x_[i] == '%')
5098 break;
5099 if (i == __x_.size())
5100 break;
5101 ++i;
5102 if (__x_[i] == 'y' || __x_[i] == 'Y')
5103 return time_base::dmy;
5104 break;
5105 }
5106 break;
5107 }
5108 return time_base::no_order;
5109}
5110
5111template <>
5112time_base::dateorder
5113__time_get_storage<wchar_t>::__do_date_order() const
5114{
5115 unsigned i;
5116 for (i = 0; i < __x_.size(); ++i)
5117 if (__x_[i] == L'%')
5118 break;
5119 ++i;
5120 switch (__x_[i])
5121 {
5122 case L'y':
5123 case L'Y':
5124 for (++i; i < __x_.size(); ++i)
5125 if (__x_[i] == L'%')
5126 break;
5127 if (i == __x_.size())
5128 break;
5129 ++i;
5130 switch (__x_[i])
5131 {
5132 case L'm':
5133 for (++i; i < __x_.size(); ++i)
5134 if (__x_[i] == L'%')
5135 break;
5136 if (i == __x_.size())
5137 break;
5138 ++i;
5139 if (__x_[i] == L'd')
5140 return time_base::ymd;
5141 break;
5142 case L'd':
5143 for (++i; i < __x_.size(); ++i)
5144 if (__x_[i] == L'%')
5145 break;
5146 if (i == __x_.size())
5147 break;
5148 ++i;
5149 if (__x_[i] == L'm')
5150 return time_base::ydm;
5151 break;
5152 }
5153 break;
5154 case L'm':
5155 for (++i; i < __x_.size(); ++i)
5156 if (__x_[i] == L'%')
5157 break;
5158 if (i == __x_.size())
5159 break;
5160 ++i;
5161 if (__x_[i] == L'd')
5162 {
5163 for (++i; i < __x_.size(); ++i)
5164 if (__x_[i] == L'%')
5165 break;
5166 if (i == __x_.size())
5167 break;
5168 ++i;
5169 if (__x_[i] == L'y' || __x_[i] == L'Y')
5170 return time_base::mdy;
5171 break;
5172 }
5173 break;
5174 case L'd':
5175 for (++i; i < __x_.size(); ++i)
5176 if (__x_[i] == L'%')
5177 break;
5178 if (i == __x_.size())
5179 break;
5180 ++i;
5181 if (__x_[i] == L'm')
5182 {
5183 for (++i; i < __x_.size(); ++i)
5184 if (__x_[i] == L'%')
5185 break;
5186 if (i == __x_.size())
5187 break;
5188 ++i;
5189 if (__x_[i] == L'y' || __x_[i] == L'Y')
5190 return time_base::dmy;
5191 break;
5192 }
5193 break;
5194 }
5195 return time_base::no_order;
5196}
5197
5198// time_put
5199
5200__time_put::__time_put(const char* nm)
5201 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
5202{
Howard Hinnantd4444702010-08-11 17:04:31 +00005203#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005204 if (__loc_ == 0)
5205 throw runtime_error("time_put_byname"
5206 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005207#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005208}
5209
5210__time_put::__time_put(const string& nm)
5211 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
5212{
Howard Hinnantd4444702010-08-11 17:04:31 +00005213#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005214 if (__loc_ == 0)
5215 throw runtime_error("time_put_byname"
5216 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005217#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005218}
5219
5220__time_put::~__time_put()
5221{
5222 if (__loc_)
5223 freelocale(__loc_);
5224}
5225
5226void
5227__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
5228 char __fmt, char __mod) const
5229{
5230 char fmt[] = {'%', __fmt, __mod, 0};
5231 if (__mod != 0)
5232 swap(fmt[1], fmt[2]);
5233 size_t n = strftime_l(__nb, __ne-__nb, fmt, __tm, __loc_);
5234 __ne = __nb + n;
5235}
5236
5237void
5238__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5239 char __fmt, char __mod) const
5240{
5241 char __nar[100];
5242 char* __ne = __nar + 100;
5243 __do_put(__nar, __ne, __tm, __fmt, __mod);
5244 mbstate_t mb = {0};
5245 const char* __nb = __nar;
Howard Hinnant866569b2011-09-28 23:39:33 +00005246#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005247 size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5248#else
5249 size_t j = __mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5250#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005251 if (j == -1)
5252 __throw_runtime_error("locale not supported");
5253 __we = __wb + j;
5254}
5255
5256// moneypunct_byname
5257
5258static
5259void
5260__init_pat(money_base::pattern& pat, char cs_precedes, char sep_by_space, char sign_posn)
5261{
5262 const char sign = static_cast<char>(money_base::sign);
5263 const char space = static_cast<char>(money_base::space);
5264 const char none = static_cast<char>(money_base::none);
5265 const char symbol = static_cast<char>(money_base::symbol);
5266 const char value = static_cast<char>(money_base::value);
5267 switch (cs_precedes)
5268 {
5269 case 0:
5270 switch (sign_posn)
5271 {
5272 case 0:
5273 pat.field[0] = sign;
5274 pat.field[1] = value;
5275 pat.field[3] = symbol;
5276 switch (sep_by_space)
5277 {
5278 case 0:
5279 pat.field[2] = none;
5280 return;
5281 case 1:
5282 case 2:
5283 pat.field[2] = space;
5284 return;
5285 default:
5286 break;
5287 }
5288 break;
5289 case 1:
5290 pat.field[0] = sign;
5291 pat.field[3] = symbol;
5292 switch (sep_by_space)
5293 {
5294 case 0:
5295 pat.field[1] = value;
5296 pat.field[2] = none;
5297 return;
5298 case 1:
5299 pat.field[1] = value;
5300 pat.field[2] = space;
5301 return;
5302 case 2:
5303 pat.field[1] = space;
5304 pat.field[2] = value;
5305 return;
5306 default:
5307 break;
5308 }
5309 break;
5310 case 2:
5311 pat.field[0] = value;
5312 pat.field[3] = sign;
5313 switch (sep_by_space)
5314 {
5315 case 0:
5316 pat.field[1] = none;
5317 pat.field[2] = symbol;
5318 return;
5319 case 1:
5320 pat.field[1] = space;
5321 pat.field[2] = symbol;
5322 return;
5323 case 2:
5324 pat.field[1] = symbol;
5325 pat.field[2] = space;
5326 return;
5327 default:
5328 break;
5329 }
5330 break;
5331 case 3:
5332 pat.field[0] = value;
5333 pat.field[3] = symbol;
5334 switch (sep_by_space)
5335 {
5336 case 0:
5337 pat.field[1] = none;
5338 pat.field[2] = sign;
5339 return;
5340 case 1:
5341 pat.field[1] = space;
5342 pat.field[2] = sign;
5343 return;
5344 case 2:
5345 pat.field[1] = sign;
5346 pat.field[2] = space;
5347 return;
5348 default:
5349 break;
5350 }
5351 break;
5352 case 4:
5353 pat.field[0] = value;
5354 pat.field[3] = sign;
5355 switch (sep_by_space)
5356 {
5357 case 0:
5358 pat.field[1] = none;
5359 pat.field[2] = symbol;
5360 return;
5361 case 1:
5362 pat.field[1] = space;
5363 pat.field[2] = symbol;
5364 return;
5365 case 2:
5366 pat.field[1] = symbol;
5367 pat.field[2] = space;
5368 return;
5369 default:
5370 break;
5371 }
5372 break;
5373 default:
5374 break;
5375 }
5376 break;
5377 case 1:
5378 switch (sign_posn)
5379 {
5380 case 0:
5381 pat.field[0] = sign;
5382 pat.field[1] = symbol;
5383 pat.field[3] = value;
5384 switch (sep_by_space)
5385 {
5386 case 0:
5387 pat.field[2] = none;
5388 return;
5389 case 1:
5390 case 2:
5391 pat.field[2] = space;
5392 return;
5393 default:
5394 break;
5395 }
5396 break;
5397 case 1:
5398 pat.field[0] = sign;
5399 pat.field[3] = value;
5400 switch (sep_by_space)
5401 {
5402 case 0:
5403 pat.field[1] = symbol;
5404 pat.field[2] = none;
5405 return;
5406 case 1:
5407 pat.field[1] = symbol;
5408 pat.field[2] = space;
5409 return;
5410 case 2:
5411 pat.field[1] = space;
5412 pat.field[2] = symbol;
5413 return;
5414 default:
5415 break;
5416 }
5417 break;
5418 case 2:
5419 pat.field[0] = symbol;
5420 pat.field[3] = sign;
5421 switch (sep_by_space)
5422 {
5423 case 0:
5424 pat.field[1] = none;
5425 pat.field[2] = value;
5426 return;
5427 case 1:
5428 pat.field[1] = space;
5429 pat.field[2] = value;
5430 return;
5431 case 2:
5432 pat.field[1] = value;
5433 pat.field[2] = space;
5434 return;
5435 default:
5436 break;
5437 }
5438 break;
5439 case 3:
5440 pat.field[0] = sign;
5441 pat.field[3] = value;
5442 switch (sep_by_space)
5443 {
5444 case 0:
5445 pat.field[1] = symbol;
5446 pat.field[2] = none;
5447 return;
5448 case 1:
5449 pat.field[1] = symbol;
5450 pat.field[2] = space;
5451 return;
5452 case 2:
5453 pat.field[1] = space;
5454 pat.field[2] = symbol;
5455 return;
5456 default:
5457 break;
5458 }
5459 break;
5460 case 4:
5461 pat.field[0] = symbol;
5462 pat.field[3] = value;
5463 switch (sep_by_space)
5464 {
5465 case 0:
5466 pat.field[1] = sign;
5467 pat.field[2] = none;
5468 return;
5469 case 1:
5470 pat.field[1] = sign;
5471 pat.field[2] = space;
5472 return;
5473 case 2:
5474 pat.field[1] = space;
5475 pat.field[2] = sign;
5476 return;
5477 default:
5478 break;
5479 }
5480 break;
5481 default:
5482 break;
5483 }
5484 break;
5485 default:
5486 break;
5487 }
5488 pat.field[0] = symbol;
5489 pat.field[1] = sign;
5490 pat.field[2] = none;
5491 pat.field[3] = value;
5492}
5493
5494template<>
5495void
5496moneypunct_byname<char, false>::init(const char* nm)
5497{
5498 typedef moneypunct<char, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005499 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005500#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005501 if (loc == 0)
5502 throw runtime_error("moneypunct_byname"
5503 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005504#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005505#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005506 lconv* lc = localeconv_l(loc.get());
5507#else
5508 lconv* lc = __localeconv_l(loc.get());
5509#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005510 if (*lc->mon_decimal_point)
5511 __decimal_point_ = *lc->mon_decimal_point;
5512 else
5513 __decimal_point_ = base::do_decimal_point();
5514 if (*lc->mon_thousands_sep)
5515 __thousands_sep_ = *lc->mon_thousands_sep;
5516 else
5517 __thousands_sep_ = base::do_thousands_sep();
5518 __grouping_ = lc->mon_grouping;
5519 __curr_symbol_ = lc->currency_symbol;
5520 if (lc->frac_digits != CHAR_MAX)
5521 __frac_digits_ = lc->frac_digits;
5522 else
5523 __frac_digits_ = base::do_frac_digits();
5524 if (lc->p_sign_posn == 0)
5525 __positive_sign_ = "()";
5526 else
5527 __positive_sign_ = lc->positive_sign;
5528 if (lc->n_sign_posn == 0)
5529 __negative_sign_ = "()";
5530 else
5531 __negative_sign_ = lc->negative_sign;
5532 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5533 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5534}
5535
5536template<>
5537void
5538moneypunct_byname<char, true>::init(const char* nm)
5539{
5540 typedef moneypunct<char, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005541 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005542#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005543 if (loc == 0)
5544 throw runtime_error("moneypunct_byname"
5545 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005546#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005547#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005548 lconv* lc = localeconv_l(loc.get());
5549#else
5550 lconv* lc = __localeconv_l(loc.get());
5551#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005552 if (*lc->mon_decimal_point)
5553 __decimal_point_ = *lc->mon_decimal_point;
5554 else
5555 __decimal_point_ = base::do_decimal_point();
5556 if (*lc->mon_thousands_sep)
5557 __thousands_sep_ = *lc->mon_thousands_sep;
5558 else
5559 __thousands_sep_ = base::do_thousands_sep();
5560 __grouping_ = lc->mon_grouping;
5561 __curr_symbol_ = lc->int_curr_symbol;
5562 if (lc->int_frac_digits != CHAR_MAX)
5563 __frac_digits_ = lc->int_frac_digits;
5564 else
5565 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005566#if _WIN32
5567 if (lc->p_sign_posn == 0)
5568#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005569 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005570#endif //_WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005571 __positive_sign_ = "()";
5572 else
5573 __positive_sign_ = lc->positive_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005574#if _WIN32
5575 if(lc->n_sign_posn == 0)
5576#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005577 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005578#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005579 __negative_sign_ = "()";
5580 else
5581 __negative_sign_ = lc->negative_sign;
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005582#if _WIN32
5583 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5584 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5585#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005586 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5587 __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 +00005588#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005589}
5590
5591template<>
5592void
5593moneypunct_byname<wchar_t, false>::init(const char* nm)
5594{
5595 typedef moneypunct<wchar_t, false> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005596 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005597#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005598 if (loc == 0)
5599 throw runtime_error("moneypunct_byname"
5600 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005601#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005602#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005603 lconv* lc = localeconv_l(loc.get());
5604#else
5605 lconv* lc = __localeconv_l(loc.get());
5606#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005607 if (*lc->mon_decimal_point)
5608 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5609 else
5610 __decimal_point_ = base::do_decimal_point();
5611 if (*lc->mon_thousands_sep)
5612 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5613 else
5614 __thousands_sep_ = base::do_thousands_sep();
5615 __grouping_ = lc->mon_grouping;
5616 wchar_t wbuf[100];
5617 mbstate_t mb = {0};
5618 const char* bb = lc->currency_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005619#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005620 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5621#else
5622 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5623#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005624 if (j == -1)
5625 __throw_runtime_error("locale not supported");
5626 wchar_t* wbe = wbuf + j;
5627 __curr_symbol_.assign(wbuf, wbe);
5628 if (lc->frac_digits != CHAR_MAX)
5629 __frac_digits_ = lc->frac_digits;
5630 else
5631 __frac_digits_ = base::do_frac_digits();
5632 if (lc->p_sign_posn == 0)
5633 __positive_sign_ = L"()";
5634 else
5635 {
5636 mb = mbstate_t();
5637 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005638#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005639 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5640#else
5641 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5642#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005643 if (j == -1)
5644 __throw_runtime_error("locale not supported");
5645 wbe = wbuf + j;
5646 __positive_sign_.assign(wbuf, wbe);
5647 }
5648 if (lc->n_sign_posn == 0)
5649 __negative_sign_ = L"()";
5650 else
5651 {
5652 mb = mbstate_t();
5653 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005654#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005655 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5656#else
5657 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5658#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005659 if (j == -1)
5660 __throw_runtime_error("locale not supported");
5661 wbe = wbuf + j;
5662 __negative_sign_.assign(wbuf, wbe);
5663 }
5664 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5665 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5666}
5667
5668template<>
5669void
5670moneypunct_byname<wchar_t, true>::init(const char* nm)
5671{
5672 typedef moneypunct<wchar_t, true> base;
Sean Huntf3907e62011-07-15 05:40:33 +00005673 __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005674#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005675 if (loc == 0)
5676 throw runtime_error("moneypunct_byname"
5677 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005678#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant866569b2011-09-28 23:39:33 +00005679#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005680 lconv* lc = localeconv_l(loc.get());
5681#else
5682 lconv* lc = __localeconv_l(loc.get());
5683#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005684 if (*lc->mon_decimal_point)
5685 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5686 else
5687 __decimal_point_ = base::do_decimal_point();
5688 if (*lc->mon_thousands_sep)
5689 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5690 else
5691 __thousands_sep_ = base::do_thousands_sep();
5692 __grouping_ = lc->mon_grouping;
5693 wchar_t wbuf[100];
5694 mbstate_t mb = {0};
5695 const char* bb = lc->int_curr_symbol;
Howard Hinnant866569b2011-09-28 23:39:33 +00005696#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005697 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5698#else
5699 size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5700#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005701 if (j == -1)
5702 __throw_runtime_error("locale not supported");
5703 wchar_t* wbe = wbuf + j;
5704 __curr_symbol_.assign(wbuf, wbe);
5705 if (lc->int_frac_digits != CHAR_MAX)
5706 __frac_digits_ = lc->int_frac_digits;
5707 else
5708 __frac_digits_ = base::do_frac_digits();
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005709#if _WIN32
5710 if (lc->p_sign_posn == 0)
5711#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005712 if (lc->int_p_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005713#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005714 __positive_sign_ = L"()";
5715 else
5716 {
5717 mb = mbstate_t();
5718 bb = lc->positive_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005719#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005720 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5721#else
5722 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5723#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005724 if (j == -1)
5725 __throw_runtime_error("locale not supported");
5726 wbe = wbuf + j;
5727 __positive_sign_.assign(wbuf, wbe);
5728 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005729#if _WIN32
5730 if (lc->n_sign_posn == 0)
5731#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005732 if (lc->int_n_sign_posn == 0)
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005733#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005734 __negative_sign_ = L"()";
5735 else
5736 {
5737 mb = mbstate_t();
5738 bb = lc->negative_sign;
Howard Hinnant866569b2011-09-28 23:39:33 +00005739#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
Sean Huntf3907e62011-07-15 05:40:33 +00005740 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5741#else
5742 j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5743#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005744 if (j == -1)
5745 __throw_runtime_error("locale not supported");
5746 wbe = wbuf + j;
5747 __negative_sign_.assign(wbuf, wbe);
5748 }
Howard Hinnant6cd05ee2011-09-23 16:11:27 +00005749#if _WIN32
5750 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5751 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5752#else // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005753 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5754 __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 +00005755#endif // _WIN32
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005756}
5757
5758void __do_nothing(void*) {}
5759
5760void __throw_runtime_error(const char* msg)
5761{
Howard Hinnantd4444702010-08-11 17:04:31 +00005762#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005763 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00005764#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005765}
5766
5767template class collate<char>;
5768template class collate<wchar_t>;
5769
5770template class num_get<char>;
5771template class num_get<wchar_t>;
5772
5773template class __num_get<char>;
5774template class __num_get<wchar_t>;
5775
5776template class num_put<char>;
5777template class num_put<wchar_t>;
5778
5779template class __num_put<char>;
5780template class __num_put<wchar_t>;
5781
5782template class time_get<char>;
5783template class time_get<wchar_t>;
5784
5785template class time_get_byname<char>;
5786template class time_get_byname<wchar_t>;
5787
5788template class time_put<char>;
5789template class time_put<wchar_t>;
5790
5791template class time_put_byname<char>;
5792template class time_put_byname<wchar_t>;
5793
5794template class moneypunct<char, false>;
5795template class moneypunct<char, true>;
5796template class moneypunct<wchar_t, false>;
5797template class moneypunct<wchar_t, true>;
5798
5799template class moneypunct_byname<char, false>;
5800template class moneypunct_byname<char, true>;
5801template class moneypunct_byname<wchar_t, false>;
5802template class moneypunct_byname<wchar_t, true>;
5803
5804template class money_get<char>;
5805template class money_get<wchar_t>;
5806
5807template class __money_get<char>;
5808template class __money_get<wchar_t>;
5809
5810template class money_put<char>;
5811template class money_put<wchar_t>;
5812
5813template class __money_put<char>;
5814template class __money_put<wchar_t>;
5815
5816template class messages<char>;
5817template class messages<wchar_t>;
5818
5819template class messages_byname<char>;
5820template class messages_byname<wchar_t>;
5821
5822template class codecvt_byname<char, char, mbstate_t>;
5823template class codecvt_byname<wchar_t, char, mbstate_t>;
5824template class codecvt_byname<char16_t, char, mbstate_t>;
5825template class codecvt_byname<char32_t, char, mbstate_t>;
5826
5827template class __vector_base_common<true>;
5828
5829_LIBCPP_END_NAMESPACE_STD