blob: 344f8df3009db441d9b180f55cf5cc197865353d [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"
17#include "clocale"
18#include "cstring"
19#include "cwctype"
20#include "__sso_allocator"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000021#include <langinfo.h>
22#include <stdlib.h>
23
Howard Hinnantadff4892010-05-24 17:49:41 +000024// FIXME: Locales are hard.
25#if __APPLE__
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000026_LIBCPP_BEGIN_NAMESPACE_STD
27
28namespace {
29
30struct release
31{
32 void operator()(locale::facet* p) {p->__release_shared();}
33};
34
35template <class T, class A0>
36inline
37T&
38make(A0 a0)
39{
40 static typename aligned_storage<sizeof(T)>::type buf;
41 ::new (&buf) T(a0);
42 return *(T*)&buf;
43}
44
45template <class T, class A0, class A1>
46inline
47T&
48make(A0 a0, A1 a1)
49{
50 static typename aligned_storage<sizeof(T)>::type buf;
51 ::new (&buf) T(a0, a1);
52 return *(T*)&buf;
53}
54
55template <class T, class A0, class A1, class A2>
56inline
57T&
58make(A0 a0, A1 a1, A2 a2)
59{
60 static typename aligned_storage<sizeof(T)>::type buf;
61 ::new (&buf) T(a0, a1, a2);
62 return *(T*)&buf;
63}
64
65}
66
67class _LIBCPP_HIDDEN locale::__imp
68 : public facet
69{
70 enum {N = 28};
71 string name_;
72 vector<facet*, __sso_allocator<facet*, N> > facets_;
73public:
74 explicit __imp(size_t refs = 0);
75 explicit __imp(const string& name, size_t refs = 0);
76 __imp(const __imp&);
77 __imp(const __imp&, const string&, locale::category c);
78 __imp(const __imp& other, const __imp& one, locale::category c);
79 __imp(const __imp&, facet* f, long id);
80 ~__imp();
81
82 const string& name() const {return name_;}
83 bool has_facet(long id) const {return id < facets_.size() && facets_[id];}
84 const locale::facet* use_facet(long id) const;
85
86 static const locale& make_classic();
87 static locale& make_global();
88private:
89 void install(facet* f, long id);
90 template <class F> void install(F* f) {install(f, f->id.__get());}
91 template <class F> void install_from(const __imp& other);
92};
93
94locale::__imp::__imp(size_t refs)
95 : facet(refs),
96 name_("C"),
97 facets_(N)
98{
99 facets_.clear();
100 install(&make<_STD::collate<char> >(1));
101 install(&make<_STD::collate<wchar_t> >(1));
102 install(&make<_STD::ctype<char> >((ctype_base::mask*)0, false, 1));
103 install(&make<_STD::ctype<wchar_t> >(1));
104 install(&make<codecvt<char, char, mbstate_t> >(1));
105 install(&make<codecvt<wchar_t, char, mbstate_t> >(1));
106 install(&make<codecvt<char16_t, char, mbstate_t> >(1));
107 install(&make<codecvt<char32_t, char, mbstate_t> >(1));
108 install(&make<numpunct<char> >(1));
109 install(&make<numpunct<wchar_t> >(1));
110 install(&make<num_get<char> >(1));
111 install(&make<num_get<wchar_t> >(1));
112 install(&make<num_put<char> >(1));
113 install(&make<num_put<wchar_t> >(1));
114 install(&make<moneypunct<char, false> >(1));
115 install(&make<moneypunct<char, true> >(1));
116 install(&make<moneypunct<wchar_t, false> >(1));
117 install(&make<moneypunct<wchar_t, true> >(1));
118 install(&make<money_get<char> >(1));
119 install(&make<money_get<wchar_t> >(1));
120 install(&make<money_put<char> >(1));
121 install(&make<money_put<wchar_t> >(1));
122 install(&make<time_get<char> >(1));
123 install(&make<time_get<wchar_t> >(1));
124 install(&make<time_put<char> >(1));
125 install(&make<time_put<wchar_t> >(1));
126 install(&make<_STD::messages<char> >(1));
127 install(&make<_STD::messages<wchar_t> >(1));
128}
129
130locale::__imp::__imp(const string& name, size_t refs)
131 : facet(refs),
132 name_(name),
133 facets_(N)
134{
Howard Hinnantd4444702010-08-11 17:04:31 +0000135#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000136 try
137 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000138#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000139 facets_ = locale::classic().__locale_->facets_;
140 for (unsigned i = 0; i < facets_.size(); ++i)
141 if (facets_[i])
142 facets_[i]->__add_shared();
143 install(new collate_byname<char>(name_));
144 install(new collate_byname<wchar_t>(name_));
145 install(new ctype_byname<char>(name_));
146 install(new ctype_byname<wchar_t>(name_));
147 install(new codecvt_byname<char, char, mbstate_t>(name_));
148 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
149 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
150 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
151 install(new numpunct_byname<char>(name_));
152 install(new numpunct_byname<wchar_t>(name_));
153 install(new moneypunct_byname<char, false>(name_));
154 install(new moneypunct_byname<char, true>(name_));
155 install(new moneypunct_byname<wchar_t, false>(name_));
156 install(new moneypunct_byname<wchar_t, true>(name_));
157 install(new time_get_byname<char>(name_));
158 install(new time_get_byname<wchar_t>(name_));
159 install(new time_put_byname<char>(name_));
160 install(new time_put_byname<wchar_t>(name_));
161 install(new messages_byname<char>(name_));
162 install(new messages_byname<wchar_t>(name_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000163#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000164 }
165 catch (...)
166 {
167 for (unsigned i = 0; i < facets_.size(); ++i)
168 if (facets_[i])
169 facets_[i]->__release_shared();
170 throw;
171 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000172#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000173}
174
175locale::__imp::__imp(const __imp& other)
176 : name_(other.name_),
177 facets_(max<size_t>(N, other.facets_.size()))
178{
179 facets_ = other.facets_;
180 for (unsigned i = 0; i < facets_.size(); ++i)
181 if (facets_[i])
182 facets_[i]->__add_shared();
183}
184
185locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
186 : name_("*"),
187 facets_(N)
188{
189 facets_ = other.facets_;
190 for (unsigned i = 0; i < facets_.size(); ++i)
191 if (facets_[i])
192 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000193#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000194 try
195 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000196#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000197 if (c & locale::collate)
198 {
199 install(new collate_byname<char>(name));
200 install(new collate_byname<wchar_t>(name));
201 }
202 if (c & locale::ctype)
203 {
204 install(new ctype_byname<char>(name));
205 install(new ctype_byname<wchar_t>(name));
206 install(new codecvt_byname<char, char, mbstate_t>(name));
207 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
208 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
209 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
210 }
211 if (c & locale::monetary)
212 {
213 install(new moneypunct_byname<char, false>(name));
214 install(new moneypunct_byname<char, true>(name));
215 install(new moneypunct_byname<wchar_t, false>(name));
216 install(new moneypunct_byname<wchar_t, true>(name));
217 }
218 if (c & locale::numeric)
219 {
220 install(new numpunct_byname<char>(name));
221 install(new numpunct_byname<wchar_t>(name));
222 }
223 if (c & locale::time)
224 {
225 install(new time_get_byname<char>(name));
226 install(new time_get_byname<wchar_t>(name));
227 install(new time_put_byname<char>(name));
228 install(new time_put_byname<wchar_t>(name));
229 }
230 if (c & locale::messages)
231 {
232 install(new messages_byname<char>(name));
233 install(new messages_byname<wchar_t>(name));
234 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000235#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000236 }
237 catch (...)
238 {
239 for (unsigned i = 0; i < facets_.size(); ++i)
240 if (facets_[i])
241 facets_[i]->__release_shared();
242 throw;
243 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000244#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000245}
246
247template<class F>
248inline
249void
250locale::__imp::install_from(const locale::__imp& one)
251{
252 long id = F::id.__get();
253 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
254}
255
256locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
257 : name_("*"),
258 facets_(N)
259{
260 facets_ = other.facets_;
261 for (unsigned i = 0; i < facets_.size(); ++i)
262 if (facets_[i])
263 facets_[i]->__add_shared();
Howard Hinnantd4444702010-08-11 17:04:31 +0000264#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000265 try
266 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000267#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000268 if (c & locale::collate)
269 {
270 install_from<_STD::collate<char> >(one);
271 install_from<_STD::collate<wchar_t> >(one);
272 }
273 if (c & locale::ctype)
274 {
275 install_from<_STD::ctype<char> >(one);
276 install_from<_STD::ctype<wchar_t> >(one);
277 install_from<_STD::codecvt<char, char, mbstate_t> >(one);
278 install_from<_STD::codecvt<char16_t, char, mbstate_t> >(one);
279 install_from<_STD::codecvt<char32_t, char, mbstate_t> >(one);
280 install_from<_STD::codecvt<wchar_t, char, mbstate_t> >(one);
281 }
282 if (c & locale::monetary)
283 {
284 install_from<moneypunct<char, false> >(one);
285 install_from<moneypunct<char, true> >(one);
286 install_from<moneypunct<wchar_t, false> >(one);
287 install_from<moneypunct<wchar_t, true> >(one);
288 install_from<money_get<char> >(one);
289 install_from<money_get<wchar_t> >(one);
290 install_from<money_put<char> >(one);
291 install_from<money_put<wchar_t> >(one);
292 }
293 if (c & locale::numeric)
294 {
295 install_from<numpunct<char> >(one);
296 install_from<numpunct<wchar_t> >(one);
297 install_from<num_get<char> >(one);
298 install_from<num_get<wchar_t> >(one);
299 install_from<num_put<char> >(one);
300 install_from<num_put<wchar_t> >(one);
301 }
302 if (c & locale::time)
303 {
304 install_from<time_get<char> >(one);
305 install_from<time_get<wchar_t> >(one);
306 install_from<time_put<char> >(one);
307 install_from<time_put<wchar_t> >(one);
308 }
309 if (c & locale::messages)
310 {
311 install_from<_STD::messages<char> >(one);
312 install_from<_STD::messages<wchar_t> >(one);
313 }
Howard Hinnantd4444702010-08-11 17:04:31 +0000314#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000315 }
316 catch (...)
317 {
318 for (unsigned i = 0; i < facets_.size(); ++i)
319 if (facets_[i])
320 facets_[i]->__release_shared();
321 throw;
322 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000323#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000324}
325
326locale::__imp::__imp(const __imp& other, facet* f, long id)
327 : name_("*"),
328 facets_(max<size_t>(N, other.facets_.size()+1))
329{
330 f->__add_shared();
331 unique_ptr<facet, release> hold(f);
332 facets_ = other.facets_;
333 for (unsigned i = 0; i < other.facets_.size(); ++i)
334 if (facets_[i])
335 facets_[i]->__add_shared();
336 install(hold.get(), id);
337}
338
339locale::__imp::~__imp()
340{
341 for (unsigned i = 0; i < facets_.size(); ++i)
342 if (facets_[i])
343 facets_[i]->__release_shared();
344}
345
346void
347locale::__imp::install(facet* f, long id)
348{
349 f->__add_shared();
350 unique_ptr<facet, release> hold(f);
351 if (id >= facets_.size())
352 facets_.resize(id+1);
353 if (facets_[id])
354 facets_[id]->__release_shared();
355 facets_[id] = hold.release();
356}
357
358const locale::facet*
359locale::__imp::use_facet(long id) const
360{
Howard Hinnantd4444702010-08-11 17:04:31 +0000361#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000362 if (!has_facet(id))
363 throw bad_cast();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000364#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000365 return facets_[id];
366}
367
368// locale
369
370const locale&
371locale::__imp::make_classic()
372{
373 // only one thread can get in here and it only gets in once
374 static aligned_storage<sizeof(locale)>::type buf;
375 locale* c = (locale*)&buf;
376 c->__locale_ = &make<__imp>(1);
377 return *c;
378}
379
380const locale&
381locale::classic()
382{
383 static const locale& c = __imp::make_classic();
384 return c;
385}
386
387locale&
388locale::__imp::make_global()
389{
390 // only one thread can get in here and it only gets in once
391 static aligned_storage<sizeof(locale)>::type buf;
392 locale* g = (locale*)&buf;
393 ::new (&buf) locale(locale::classic());
394 return *(locale*)&buf;
395}
396
397locale&
398locale::__global()
399{
400 static locale& g = __imp::make_global();
401 return g;
402}
403
404locale::locale() throw()
405 : __locale_(__global().__locale_)
406{
407 __locale_->__add_shared();
408}
409
410locale::locale(const locale& l) throw()
411 : __locale_(l.__locale_)
412{
413 __locale_->__add_shared();
414}
415
416locale::~locale() throw()
417{
418 __locale_->__release_shared();
419}
420
421const locale&
422locale::operator=(const locale& other) throw()
423{
424 other.__locale_->__add_shared();
425 __locale_->__release_shared();
426 __locale_ = other.__locale_;
427 return *this;
428}
429
430locale::locale(const char* name)
Howard Hinnantd4444702010-08-11 17:04:31 +0000431#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000432 : __locale_(name ? new __imp(name)
433 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000434#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000435 : __locale_(new __imp(name))
436#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000437{
438 __locale_->__add_shared();
439}
440
441locale::locale(const string& name)
442 : __locale_(new __imp(name))
443{
444 __locale_->__add_shared();
445}
446
447locale::locale(const locale& other, const char* name, category c)
Howard Hinnantd4444702010-08-11 17:04:31 +0000448#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000449 : __locale_(name ? new __imp(*other.__locale_, name, c)
450 : throw runtime_error("locale constructed with null"))
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000451#else // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantd4444702010-08-11 17:04:31 +0000452 : __locale_(new __imp(*other.__locale_, name, c))
453#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000454{
455 __locale_->__add_shared();
456}
457
458locale::locale(const locale& other, const string& name, category c)
459 : __locale_(new __imp(*other.__locale_, name, c))
460{
461 __locale_->__add_shared();
462}
463
464locale::locale(const locale& other, const locale& one, category c)
465 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
466{
467 __locale_->__add_shared();
468}
469
470string
471locale::name() const
472{
473 return __locale_->name();
474}
475
476void
477locale::__install_ctor(const locale& other, facet* f, long id)
478{
479 if (f)
480 __locale_ = new __imp(*other.__locale_, f, id);
481 else
482 __locale_ = other.__locale_;
483 __locale_->__add_shared();
484}
485
486locale
487locale::global(const locale& loc)
488{
489 locale& g = __global();
490 locale r = g;
491 g = loc;
492 if (g.name() != "*")
493 setlocale(LC_ALL, g.name().c_str());
494 return r;
495}
496
497bool
498locale::has_facet(id& x) const
499{
500 return __locale_->has_facet(x.__get());
501}
502
503const locale::facet*
504locale::use_facet(id& x) const
505{
506 return __locale_->use_facet(x.__get());
507}
508
509bool
510locale::operator==(const locale& y) const
511{
512 return (__locale_ == y.__locale_)
513 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
514}
515
516// locale::facet
517
518locale::facet::~facet()
519{
520}
521
522void
523locale::facet::__on_zero_shared()
524{
525 delete this;
526}
527
528// locale::id
529
530int32_t locale::id::__next_id = 0;
531
532namespace
533{
534
535class __fake_bind
536{
537 locale::id* id_;
538 void (locale::id::* pmf_)();
539public:
540 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
541 : id_(id), pmf_(pmf) {}
542
543 void operator()() const
544 {
545 (id_->*pmf_)();
546 }
547};
548
549}
550
551long
552locale::id::__get()
553{
554 call_once(__flag_, __fake_bind(&locale::id::__init, this));
555 return __id_ - 1;
556}
557
558void
559locale::id::__init()
560{
Howard Hinnantadff4892010-05-24 17:49:41 +0000561 __id_ = __sync_add_and_fetch(&__next_id, 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000562}
563
564// template <> class collate_byname<char>
565
566collate_byname<char>::collate_byname(const char* n, size_t refs)
567 : collate<char>(refs),
568 __l(newlocale(LC_ALL_MASK, n, 0))
569{
Howard Hinnantd4444702010-08-11 17:04:31 +0000570#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000571 if (__l == 0)
572 throw runtime_error("collate_byname<char>::collate_byname"
573 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000574#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000575}
576
577collate_byname<char>::collate_byname(const string& name, size_t refs)
578 : collate<char>(refs),
579 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
580{
Howard Hinnantd4444702010-08-11 17:04:31 +0000581#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000582 if (__l == 0)
583 throw runtime_error("collate_byname<char>::collate_byname"
584 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000585#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000586}
587
588collate_byname<char>::~collate_byname()
589{
590 freelocale(__l);
591}
592
593int
594collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
595 const char_type* __lo2, const char_type* __hi2) const
596{
597 string_type lhs(__lo1, __hi1);
598 string_type rhs(__lo2, __hi2);
599 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
600 if (r < 0)
601 return -1;
602 if (r > 0)
603 return 1;
604 return r;
605}
606
607collate_byname<char>::string_type
608collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
609{
610 const string_type in(lo, hi);
611 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
612 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
613 return out;
614}
615
616// template <> class collate_byname<wchar_t>
617
618collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
619 : collate<wchar_t>(refs),
620 __l(newlocale(LC_ALL_MASK, n, 0))
621{
Howard Hinnantd4444702010-08-11 17:04:31 +0000622#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000623 if (__l == 0)
624 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
625 " failed to construct for " + string(n));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000626#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000627}
628
629collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
630 : collate<wchar_t>(refs),
631 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
632{
Howard Hinnantd4444702010-08-11 17:04:31 +0000633#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000634 if (__l == 0)
635 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
636 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000637#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000638}
639
640collate_byname<wchar_t>::~collate_byname()
641{
642 freelocale(__l);
643}
644
645int
646collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
647 const char_type* __lo2, const char_type* __hi2) const
648{
649 string_type lhs(__lo1, __hi1);
650 string_type rhs(__lo2, __hi2);
651 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
652 if (r < 0)
653 return -1;
654 if (r > 0)
655 return 1;
656 return r;
657}
658
659collate_byname<wchar_t>::string_type
660collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
661{
662 const string_type in(lo, hi);
663 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
664 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
665 return out;
666}
667
668// template <> class ctype<wchar_t>;
669
670locale::id ctype<wchar_t>::id;
671
672ctype<wchar_t>::~ctype()
673{
674}
675
676bool
677ctype<wchar_t>::do_is(mask m, char_type c) const
678{
679 return isascii(c) ? _DefaultRuneLocale.__runetype[c] & m : false;
680}
681
682const wchar_t*
683ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
684{
685 for (; low != high; ++low, ++vec)
686 *vec = static_cast<mask>(isascii(*low) ? _DefaultRuneLocale.__runetype[*low] : 0);
687 return low;
688}
689
690const wchar_t*
691ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
692{
693 for (; low != high; ++low)
694 if (isascii(*low) && (_DefaultRuneLocale.__runetype[*low] & m))
695 break;
696 return low;
697}
698
699const wchar_t*
700ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
701{
702 for (; low != high; ++low)
703 if (!(isascii(*low) && (_DefaultRuneLocale.__runetype[*low] & m)))
704 break;
705 return low;
706}
707
708wchar_t
709ctype<wchar_t>::do_toupper(char_type c) const
710{
711 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
712}
713
714const wchar_t*
715ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
716{
717 for (; low != high; ++low)
718 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
719 return low;
720}
721
722wchar_t
723ctype<wchar_t>::do_tolower(char_type c) const
724{
725 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
726}
727
728const wchar_t*
729ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
730{
731 for (; low != high; ++low)
732 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
733 return low;
734}
735
736wchar_t
737ctype<wchar_t>::do_widen(char c) const
738{
739 return c;
740}
741
742const char*
743ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
744{
745 for (; low != high; ++low, ++dest)
746 *dest = *low;
747 return low;
748}
749
750char
751ctype<wchar_t>::do_narrow(char_type c, char dfault) const
752{
753 if (isascii(c))
754 return static_cast<char>(c);
755 return dfault;
756}
757
758const wchar_t*
759ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
760{
761 for (; low != high; ++low, ++dest)
762 if (isascii(*low))
763 *dest = *low;
764 else
765 *dest = dfault;
766 return low;
767}
768
769// template <> class ctype<char>;
770
771locale::id ctype<char>::id;
772
773ctype<char>::ctype(const mask* tab, bool del, size_t refs)
774 : locale::facet(refs),
775 __tab_(tab),
776 __del_(del)
777{
778 if (__tab_ == 0)
779 __tab_ = _DefaultRuneLocale.__runetype;
780}
781
782ctype<char>::~ctype()
783{
784 if (__tab_ && __del_)
785 delete [] __tab_;
786}
787
788char
789ctype<char>::do_toupper(char_type c) const
790{
791 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
792}
793
794const char*
795ctype<char>::do_toupper(char_type* low, const char_type* high) const
796{
797 for (; low != high; ++low)
798 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
799 return low;
800}
801
802char
803ctype<char>::do_tolower(char_type c) const
804{
805 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
806}
807
808const char*
809ctype<char>::do_tolower(char_type* low, const char_type* high) const
810{
811 for (; low != high; ++low)
812 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
813 return low;
814}
815
816char
817ctype<char>::do_widen(char c) const
818{
819 return c;
820}
821
822const char*
823ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
824{
825 for (; low != high; ++low, ++dest)
826 *dest = *low;
827 return low;
828}
829
830char
831ctype<char>::do_narrow(char_type c, char dfault) const
832{
833 if (isascii(c))
834 return static_cast<char>(c);
835 return dfault;
836}
837
838const char*
839ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
840{
841 for (; low != high; ++low, ++dest)
842 if (isascii(*low))
843 *dest = *low;
844 else
845 *dest = dfault;
846 return low;
847}
848
849const ctype<char>::mask*
850ctype<char>::classic_table() throw()
851{
852 return _DefaultRuneLocale.__runetype;
853}
854
855// template <> class ctype_byname<char>
856
857ctype_byname<char>::ctype_byname(const char* name, size_t refs)
858 : ctype<char>(0, false, refs),
859 __l(newlocale(LC_ALL_MASK, name, 0))
860{
Howard Hinnantd4444702010-08-11 17:04:31 +0000861#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000862 if (__l == 0)
863 throw runtime_error("ctype_byname<char>::ctype_byname"
864 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000865#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000866}
867
868ctype_byname<char>::ctype_byname(const string& name, size_t refs)
869 : ctype<char>(0, false, refs),
870 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
871{
Howard Hinnantd4444702010-08-11 17:04:31 +0000872#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000873 if (__l == 0)
874 throw runtime_error("ctype_byname<char>::ctype_byname"
875 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000876#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000877}
878
879ctype_byname<char>::~ctype_byname()
880{
881 freelocale(__l);
882}
883
884char
885ctype_byname<char>::do_toupper(char_type c) const
886{
887 return toupper_l(c, __l);
888}
889
890const char*
891ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
892{
893 for (; low != high; ++low)
894 *low = toupper_l(*low, __l);
895 return low;
896}
897
898char
899ctype_byname<char>::do_tolower(char_type c) const
900{
901 return tolower_l(c, __l);
902}
903
904const char*
905ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
906{
907 for (; low != high; ++low)
908 *low = tolower_l(*low, __l);
909 return low;
910}
911
912// template <> class ctype_byname<wchar_t>
913
914ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
915 : ctype<wchar_t>(refs),
916 __l(newlocale(LC_ALL_MASK, name, 0))
917{
Howard Hinnantd4444702010-08-11 17:04:31 +0000918#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000919 if (__l == 0)
920 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
921 " failed to construct for " + string(name));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000922#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000923}
924
925ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
926 : ctype<wchar_t>(refs),
927 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
928{
Howard Hinnantd4444702010-08-11 17:04:31 +0000929#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000930 if (__l == 0)
931 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
932 " failed to construct for " + name);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000933#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000934}
935
936ctype_byname<wchar_t>::~ctype_byname()
937{
938 freelocale(__l);
939}
940
941bool
942ctype_byname<wchar_t>::do_is(mask m, char_type c) const
943{
944 return static_cast<bool>(iswctype_l(c, m, __l));
945}
946
947const wchar_t*
948ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
949{
950 for (; low != high; ++low, ++vec)
951 {
952 if (isascii(*low))
953 *vec = static_cast<mask>(_DefaultRuneLocale.__runetype[*low]);
954 else
955 {
956 *vec = 0;
957 if (iswspace_l(*low, __l))
958 *vec |= space;
959 if (iswprint_l(*low, __l))
960 *vec |= print;
961 if (iswcntrl_l(*low, __l))
962 *vec |= cntrl;
963 if (iswupper_l(*low, __l))
964 *vec |= upper;
965 if (iswlower_l(*low, __l))
966 *vec |= lower;
967 if (iswalpha_l(*low, __l))
968 *vec |= alpha;
969 if (iswdigit_l(*low, __l))
970 *vec |= digit;
971 if (iswpunct_l(*low, __l))
972 *vec |= punct;
973 if (iswxdigit_l(*low, __l))
974 *vec |= xdigit;
975 }
976 }
977 return low;
978}
979
980const wchar_t*
981ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
982{
983 for (; low != high; ++low)
984 if (iswctype_l(*low, m, __l))
985 break;
986 return low;
987}
988
989const wchar_t*
990ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
991{
992 for (; low != high; ++low)
993 if (!iswctype_l(*low, m, __l))
994 break;
995 return low;
996}
997
998wchar_t
999ctype_byname<wchar_t>::do_toupper(char_type c) const
1000{
1001 return towupper_l(c, __l);
1002}
1003
1004const wchar_t*
1005ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
1006{
1007 for (; low != high; ++low)
1008 *low = towupper_l(*low, __l);
1009 return low;
1010}
1011
1012wchar_t
1013ctype_byname<wchar_t>::do_tolower(char_type c) const
1014{
1015 return towlower_l(c, __l);
1016}
1017
1018const wchar_t*
1019ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
1020{
1021 for (; low != high; ++low)
1022 *low = towlower_l(*low, __l);
1023 return low;
1024}
1025
1026wchar_t
1027ctype_byname<wchar_t>::do_widen(char c) const
1028{
1029 return btowc_l(c, __l);
1030}
1031
1032const char*
1033ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
1034{
1035 for (; low != high; ++low, ++dest)
1036 *dest = btowc_l(*low, __l);
1037 return low;
1038}
1039
1040char
1041ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1042{
1043 int r = wctob_l(c, __l);
1044 return r != WEOF ? static_cast<char>(r) : dfault;
1045}
1046
1047const wchar_t*
1048ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1049{
1050 for (; low != high; ++low, ++dest)
1051 {
1052 int r = wctob_l(*low, __l);
1053 *dest = r != WEOF ? static_cast<char>(r) : dfault;
1054 }
1055 return low;
1056}
1057
1058// template <> class codecvt<char, char, mbstate_t>
1059
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001060locale::id codecvt<char, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001061
1062codecvt<char, char, mbstate_t>::~codecvt()
1063{
1064}
1065
1066codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001067codecvt<char, char, mbstate_t>::do_out(state_type&,
1068 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001069 extern_type* to, extern_type*, extern_type*& to_nxt) const
1070{
1071 frm_nxt = frm;
1072 to_nxt = to;
1073 return noconv;
1074}
1075
1076codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001077codecvt<char, char, mbstate_t>::do_in(state_type&,
1078 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001079 intern_type* to, intern_type*, intern_type*& to_nxt) const
1080{
1081 frm_nxt = frm;
1082 to_nxt = to;
1083 return noconv;
1084}
1085
1086codecvt<char, char, mbstate_t>::result
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001087codecvt<char, char, mbstate_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001088 extern_type* to, extern_type*, extern_type*& to_nxt) const
1089{
1090 to_nxt = to;
1091 return noconv;
1092}
1093
1094int
1095codecvt<char, char, mbstate_t>::do_encoding() const throw()
1096{
1097 return 1;
1098}
1099
1100bool
1101codecvt<char, char, mbstate_t>::do_always_noconv() const throw()
1102{
1103 return true;
1104}
1105
1106int
1107codecvt<char, char, mbstate_t>::do_length(state_type&,
1108 const extern_type* frm, const extern_type* end, size_t mx) const
1109{
1110 return static_cast<int>(min<size_t>(mx, end-frm));
1111}
1112
1113int
1114codecvt<char, char, mbstate_t>::do_max_length() const throw()
1115{
1116 return 1;
1117}
1118
1119// template <> class codecvt<wchar_t, char, mbstate_t>
1120
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001121locale::id codecvt<wchar_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001122
1123codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1124 : locale::facet(refs),
1125 __l(0)
1126{
1127}
1128
1129codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1130 : locale::facet(refs),
1131 __l(newlocale(LC_ALL_MASK, nm, 0))
1132{
Howard Hinnantd4444702010-08-11 17:04:31 +00001133#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001134 if (__l == 0)
1135 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1136 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001137#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001138}
1139
1140codecvt<wchar_t, char, mbstate_t>::~codecvt()
1141{
1142 if (__l != 0)
1143 freelocale(__l);
1144}
1145
1146codecvt<wchar_t, char, mbstate_t>::result
1147codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001148 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001149 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1150{
1151 // look for first internal null in frm
1152 const intern_type* fend = frm;
1153 for (; fend != frm_end; ++fend)
1154 if (*fend == 0)
1155 break;
1156 // loop over all null-terminated sequences in frm
1157 to_nxt = to;
1158 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1159 {
1160 // save state in case needed to reover to_nxt on error
1161 mbstate_t save_state = st;
1162 size_t n = wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1163 if (n == size_t(-1))
1164 {
1165 // need to recover to_nxt
1166 for (to_nxt = to; frm != frm_nxt; ++frm)
1167 {
1168 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1169 if (n == size_t(-1))
1170 break;
1171 to_nxt += n;
1172 }
1173 frm_nxt = frm;
1174 return error;
1175 }
1176 if (n == 0)
1177 return partial;
1178 to_nxt += n;
1179 if (to_nxt == to_end)
1180 break;
1181 if (fend != frm_end) // set up next null terminated sequence
1182 {
1183 // Try to write the terminating null
1184 extern_type tmp[MB_LEN_MAX];
1185 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1186 if (n == size_t(-1)) // on error
1187 return error;
1188 if (n > to_end-to_nxt) // is there room?
1189 return partial;
1190 for (extern_type* p = tmp; n; --n) // write it
1191 *to_nxt++ = *p++;
1192 ++frm_nxt;
1193 // look for next null in frm
1194 for (fend = frm_nxt; fend != frm_end; ++fend)
1195 if (*fend == 0)
1196 break;
1197 }
1198 }
1199 return frm_nxt == frm_end ? ok : partial;
1200}
1201
1202codecvt<wchar_t, char, mbstate_t>::result
1203codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00001204 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001205 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1206{
1207 // look for first internal null in frm
1208 const extern_type* fend = frm;
1209 for (; fend != frm_end; ++fend)
1210 if (*fend == 0)
1211 break;
1212 // loop over all null-terminated sequences in frm
1213 to_nxt = to;
1214 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1215 {
1216 // save state in case needed to reover to_nxt on error
1217 mbstate_t save_state = st;
1218 size_t n = mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1219 if (n == size_t(-1))
1220 {
1221 // need to recover to_nxt
1222 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1223 {
1224 n = mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1225 switch (n)
1226 {
1227 case 0:
1228 ++frm;
1229 break;
1230 case -1:
1231 frm_nxt = frm;
1232 return error;
1233 case -2:
1234 frm_nxt = frm;
1235 return partial;
1236 default:
1237 frm += n;
1238 break;
1239 }
1240 }
1241 frm_nxt = frm;
1242 return frm_nxt == frm_end ? ok : partial;
1243 }
1244 if (n == 0)
1245 return error;
1246 to_nxt += n;
1247 if (to_nxt == to_end)
1248 break;
1249 if (fend != frm_end) // set up next null terminated sequence
1250 {
1251 // Try to write the terminating null
1252 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1253 if (n != 0) // on error
1254 return error;
1255 ++to_nxt;
1256 ++frm_nxt;
1257 // look for next null in frm
1258 for (fend = frm_nxt; fend != frm_end; ++fend)
1259 if (*fend == 0)
1260 break;
1261 }
1262 }
1263 return frm_nxt == frm_end ? ok : partial;
1264}
1265
1266codecvt<wchar_t, char, mbstate_t>::result
1267codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1268 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1269{
1270 to_nxt = to;
1271 extern_type tmp[MB_LEN_MAX];
1272 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1273 if (n == size_t(-1) || n == 0) // on error
1274 return error;
1275 --n;
1276 if (n > to_end-to_nxt) // is there room?
1277 return partial;
1278 for (extern_type* p = tmp; n; --n) // write it
1279 *to_nxt++ = *p++;
1280 return ok;
1281}
1282
1283int
1284codecvt<wchar_t, char, mbstate_t>::do_encoding() const throw()
1285{
1286 if (mbtowc_l(0, 0, MB_LEN_MAX, __l) == 0)
1287 {
1288 // stateless encoding
1289 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1290 return 1; // which take more than 1 char to form a wchar_t
1291 return 0;
1292 }
1293 return -1;
1294}
1295
1296bool
1297codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const throw()
1298{
1299 return false;
1300}
1301
1302int
1303codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1304 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1305{
1306 int nbytes = 0;
1307 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1308 {
1309 size_t n = mbrlen_l(frm, frm_end-frm, &st, __l);
1310 switch (n)
1311 {
1312 case 0:
1313 ++nbytes;
1314 ++frm;
1315 break;
1316 case -1:
1317 case -2:
1318 return nbytes;
1319 default:
1320 nbytes += n;
1321 frm += n;
1322 break;
1323 }
1324 }
1325 return nbytes;
1326}
1327
1328int
1329codecvt<wchar_t, char, mbstate_t>::do_max_length() const throw()
1330{
1331 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1332}
1333
1334// Valid UTF ranges
1335// UTF-32 UTF-16 UTF-8 # of code points
1336// first second first second third fourth
1337// 000000 - 00007F 0000 - 007F 00 - 7F 127
1338// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1339// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1340// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1341// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1342// 00D800 - 00DFFF invalid
1343// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1344// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1345// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1346// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1347
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00001348static
1349codecvt_base::result
1350utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
1351 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1352 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1353{
1354 frm_nxt = frm;
1355 to_nxt = to;
1356 if (mode & generate_header)
1357 {
1358 if (to_end-to_nxt < 3)
1359 return codecvt_base::partial;
1360 *to_nxt++ = static_cast<uint8_t>(0xEF);
1361 *to_nxt++ = static_cast<uint8_t>(0xBB);
1362 *to_nxt++ = static_cast<uint8_t>(0xBF);
1363 }
1364 for (; frm_nxt < frm_end; ++frm_nxt)
1365 {
1366 uint16_t wc1 = *frm_nxt;
1367 if (wc1 > Maxcode)
1368 return codecvt_base::error;
1369 if (wc1 < 0x0080)
1370 {
1371 if (to_end-to_nxt < 1)
1372 return codecvt_base::partial;
1373 *to_nxt++ = static_cast<uint8_t>(wc1);
1374 }
1375 else if (wc1 < 0x0800)
1376 {
1377 if (to_end-to_nxt < 2)
1378 return codecvt_base::partial;
1379 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1380 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1381 }
1382 else if (wc1 < 0xD800)
1383 {
1384 if (to_end-to_nxt < 3)
1385 return codecvt_base::partial;
1386 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1387 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1388 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1389 }
1390 else if (wc1 < 0xDC00)
1391 {
1392 if (frm_end-frm_nxt < 2)
1393 return codecvt_base::partial;
1394 uint16_t wc2 = frm_nxt[1];
1395 if ((wc2 & 0xFC00) != 0xDC00)
1396 return codecvt_base::error;
1397 if (to_end-to_nxt < 4)
1398 return codecvt_base::partial;
1399 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1400 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1401 return codecvt_base::error;
1402 ++frm_nxt;
1403 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1404 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1405 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1406 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1407 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1408 }
1409 else if (wc1 < 0xE000)
1410 {
1411 return codecvt_base::error;
1412 }
1413 else
1414 {
1415 if (to_end-to_nxt < 3)
1416 return codecvt_base::partial;
1417 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1418 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1419 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1420 }
1421 }
1422 return codecvt_base::ok;
1423}
1424
1425static
1426codecvt_base::result
1427utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1428 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1429 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1430{
1431 frm_nxt = frm;
1432 to_nxt = to;
1433 if (mode & generate_header)
1434 {
1435 if (to_end-to_nxt < 3)
1436 return codecvt_base::partial;
1437 *to_nxt++ = static_cast<uint8_t>(0xEF);
1438 *to_nxt++ = static_cast<uint8_t>(0xBB);
1439 *to_nxt++ = static_cast<uint8_t>(0xBF);
1440 }
1441 for (; frm_nxt < frm_end; ++frm_nxt)
1442 {
1443 uint16_t wc1 = static_cast<uint16_t>(*frm_nxt);
1444 if (wc1 > Maxcode)
1445 return codecvt_base::error;
1446 if (wc1 < 0x0080)
1447 {
1448 if (to_end-to_nxt < 1)
1449 return codecvt_base::partial;
1450 *to_nxt++ = static_cast<uint8_t>(wc1);
1451 }
1452 else if (wc1 < 0x0800)
1453 {
1454 if (to_end-to_nxt < 2)
1455 return codecvt_base::partial;
1456 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6));
1457 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F));
1458 }
1459 else if (wc1 < 0xD800)
1460 {
1461 if (to_end-to_nxt < 3)
1462 return codecvt_base::partial;
1463 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1464 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1465 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1466 }
1467 else if (wc1 < 0xDC00)
1468 {
1469 if (frm_end-frm_nxt < 2)
1470 return codecvt_base::partial;
1471 uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]);
1472 if ((wc2 & 0xFC00) != 0xDC00)
1473 return codecvt_base::error;
1474 if (to_end-to_nxt < 4)
1475 return codecvt_base::partial;
1476 if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) +
1477 (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode)
1478 return codecvt_base::error;
1479 ++frm_nxt;
1480 uint8_t z = ((wc1 & 0x03C0) >> 6) + 1;
1481 *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2));
1482 *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1483 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1484 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F));
1485 }
1486 else if (wc1 < 0xE000)
1487 {
1488 return codecvt_base::error;
1489 }
1490 else
1491 {
1492 if (to_end-to_nxt < 3)
1493 return codecvt_base::partial;
1494 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12));
1495 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6));
1496 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F));
1497 }
1498 }
1499 return codecvt_base::ok;
1500}
1501
1502static
1503codecvt_base::result
1504utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1505 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
1506 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1507{
1508 frm_nxt = frm;
1509 to_nxt = to;
1510 if (mode & consume_header)
1511 {
1512 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1513 frm_nxt[2] == 0xBF)
1514 frm_nxt += 3;
1515 }
1516 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1517 {
1518 uint8_t c1 = *frm_nxt;
1519 if (c1 > Maxcode)
1520 return codecvt_base::error;
1521 if (c1 < 0x80)
1522 {
1523 *to_nxt = static_cast<uint16_t>(c1);
1524 ++frm_nxt;
1525 }
1526 else if (c1 < 0xC2)
1527 {
1528 return codecvt_base::error;
1529 }
1530 else if (c1 < 0xE0)
1531 {
1532 if (frm_end-frm_nxt < 2)
1533 return codecvt_base::partial;
1534 uint8_t c2 = frm_nxt[1];
1535 if ((c2 & 0xC0) != 0x80)
1536 return codecvt_base::error;
1537 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1538 if (t > Maxcode)
1539 return codecvt_base::error;
1540 *to_nxt = t;
1541 frm_nxt += 2;
1542 }
1543 else if (c1 < 0xF0)
1544 {
1545 if (frm_end-frm_nxt < 3)
1546 return codecvt_base::partial;
1547 uint8_t c2 = frm_nxt[1];
1548 uint8_t c3 = frm_nxt[2];
1549 switch (c1)
1550 {
1551 case 0xE0:
1552 if ((c2 & 0xE0) != 0xA0)
1553 return codecvt_base::error;
1554 break;
1555 case 0xED:
1556 if ((c2 & 0xE0) != 0x80)
1557 return codecvt_base::error;
1558 break;
1559 default:
1560 if ((c2 & 0xC0) != 0x80)
1561 return codecvt_base::error;
1562 break;
1563 }
1564 if ((c3 & 0xC0) != 0x80)
1565 return codecvt_base::error;
1566 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1567 | ((c2 & 0x3F) << 6)
1568 | (c3 & 0x3F));
1569 if (t > Maxcode)
1570 return codecvt_base::error;
1571 *to_nxt = t;
1572 frm_nxt += 3;
1573 }
1574 else if (c1 < 0xF5)
1575 {
1576 if (frm_end-frm_nxt < 4)
1577 return codecvt_base::partial;
1578 uint8_t c2 = frm_nxt[1];
1579 uint8_t c3 = frm_nxt[2];
1580 uint8_t c4 = frm_nxt[3];
1581 switch (c1)
1582 {
1583 case 0xF0:
1584 if (!(0x90 <= c2 && c2 <= 0xBF))
1585 return codecvt_base::error;
1586 break;
1587 case 0xF4:
1588 if ((c2 & 0xF0) != 0x80)
1589 return codecvt_base::error;
1590 break;
1591 default:
1592 if ((c2 & 0xC0) != 0x80)
1593 return codecvt_base::error;
1594 break;
1595 }
1596 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1597 return codecvt_base::error;
1598 if (to_end-to_nxt < 2)
1599 return codecvt_base::partial;
1600 if (((((unsigned long)c1 & 7) << 18) +
1601 (((unsigned long)c2 & 0x3F) << 12) +
1602 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1603 return codecvt_base::error;
1604 *to_nxt = static_cast<uint16_t>(
1605 0xD800
1606 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1607 | ((c2 & 0x0F) << 2)
1608 | ((c3 & 0x30) >> 4));
1609 *++to_nxt = static_cast<uint16_t>(
1610 0xDC00
1611 | ((c3 & 0x0F) << 6)
1612 | (c4 & 0x3F));
1613 frm_nxt += 4;
1614 }
1615 else
1616 {
1617 return codecvt_base::error;
1618 }
1619 }
1620 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1621}
1622
1623static
1624codecvt_base::result
1625utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1626 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1627 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1628{
1629 frm_nxt = frm;
1630 to_nxt = to;
1631 if (mode & consume_header)
1632 {
1633 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1634 frm_nxt[2] == 0xBF)
1635 frm_nxt += 3;
1636 }
1637 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1638 {
1639 uint8_t c1 = *frm_nxt;
1640 if (c1 > Maxcode)
1641 return codecvt_base::error;
1642 if (c1 < 0x80)
1643 {
1644 *to_nxt = static_cast<uint32_t>(c1);
1645 ++frm_nxt;
1646 }
1647 else if (c1 < 0xC2)
1648 {
1649 return codecvt_base::error;
1650 }
1651 else if (c1 < 0xE0)
1652 {
1653 if (frm_end-frm_nxt < 2)
1654 return codecvt_base::partial;
1655 uint8_t c2 = frm_nxt[1];
1656 if ((c2 & 0xC0) != 0x80)
1657 return codecvt_base::error;
1658 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F));
1659 if (t > Maxcode)
1660 return codecvt_base::error;
1661 *to_nxt = static_cast<uint32_t>(t);
1662 frm_nxt += 2;
1663 }
1664 else if (c1 < 0xF0)
1665 {
1666 if (frm_end-frm_nxt < 3)
1667 return codecvt_base::partial;
1668 uint8_t c2 = frm_nxt[1];
1669 uint8_t c3 = frm_nxt[2];
1670 switch (c1)
1671 {
1672 case 0xE0:
1673 if ((c2 & 0xE0) != 0xA0)
1674 return codecvt_base::error;
1675 break;
1676 case 0xED:
1677 if ((c2 & 0xE0) != 0x80)
1678 return codecvt_base::error;
1679 break;
1680 default:
1681 if ((c2 & 0xC0) != 0x80)
1682 return codecvt_base::error;
1683 break;
1684 }
1685 if ((c3 & 0xC0) != 0x80)
1686 return codecvt_base::error;
1687 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1688 | ((c2 & 0x3F) << 6)
1689 | (c3 & 0x3F));
1690 if (t > Maxcode)
1691 return codecvt_base::error;
1692 *to_nxt = static_cast<uint32_t>(t);
1693 frm_nxt += 3;
1694 }
1695 else if (c1 < 0xF5)
1696 {
1697 if (frm_end-frm_nxt < 4)
1698 return codecvt_base::partial;
1699 uint8_t c2 = frm_nxt[1];
1700 uint8_t c3 = frm_nxt[2];
1701 uint8_t c4 = frm_nxt[3];
1702 switch (c1)
1703 {
1704 case 0xF0:
1705 if (!(0x90 <= c2 && c2 <= 0xBF))
1706 return codecvt_base::error;
1707 break;
1708 case 0xF4:
1709 if ((c2 & 0xF0) != 0x80)
1710 return codecvt_base::error;
1711 break;
1712 default:
1713 if ((c2 & 0xC0) != 0x80)
1714 return codecvt_base::error;
1715 break;
1716 }
1717 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1718 return codecvt_base::error;
1719 if (to_end-to_nxt < 2)
1720 return codecvt_base::partial;
1721 if (((((unsigned long)c1 & 7) << 18) +
1722 (((unsigned long)c2 & 0x3F) << 12) +
1723 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1724 return codecvt_base::error;
1725 *to_nxt = static_cast<uint32_t>(
1726 0xD800
1727 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1728 | ((c2 & 0x0F) << 2)
1729 | ((c3 & 0x30) >> 4));
1730 *++to_nxt = static_cast<uint32_t>(
1731 0xDC00
1732 | ((c3 & 0x0F) << 6)
1733 | (c4 & 0x3F));
1734 frm_nxt += 4;
1735 }
1736 else
1737 {
1738 return codecvt_base::error;
1739 }
1740 }
1741 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
1742}
1743
1744static
1745int
1746utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end,
1747 size_t mx, unsigned long Maxcode = 0x10FFFF,
1748 codecvt_mode mode = codecvt_mode(0))
1749{
1750 const uint8_t* frm_nxt = frm;
1751 if (mode & consume_header)
1752 {
1753 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1754 frm_nxt[2] == 0xBF)
1755 frm_nxt += 3;
1756 }
1757 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1758 {
1759 uint8_t c1 = *frm_nxt;
1760 if (c1 > Maxcode)
1761 break;
1762 if (c1 < 0x80)
1763 {
1764 ++frm_nxt;
1765 }
1766 else if (c1 < 0xC2)
1767 {
1768 break;
1769 }
1770 else if (c1 < 0xE0)
1771 {
1772 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
1773 break;
1774 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F));
1775 if (t > Maxcode)
1776 break;
1777 frm_nxt += 2;
1778 }
1779 else if (c1 < 0xF0)
1780 {
1781 if (frm_end-frm_nxt < 3)
1782 break;
1783 uint8_t c2 = frm_nxt[1];
1784 uint8_t c3 = frm_nxt[2];
1785 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
1786 | ((c2 & 0x3F) << 6)
1787 | (c3 & 0x3F));
1788 switch (c1)
1789 {
1790 case 0xE0:
1791 if ((c2 & 0xE0) != 0xA0)
1792 return static_cast<int>(frm_nxt - frm);
1793 break;
1794 case 0xED:
1795 if ((c2 & 0xE0) != 0x80)
1796 return static_cast<int>(frm_nxt - frm);
1797 break;
1798 default:
1799 if ((c2 & 0xC0) != 0x80)
1800 return static_cast<int>(frm_nxt - frm);
1801 break;
1802 }
1803 if ((c3 & 0xC0) != 0x80)
1804 break;
1805 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
1806 break;
1807 frm_nxt += 3;
1808 }
1809 else if (c1 < 0xF5)
1810 {
1811 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
1812 break;
1813 uint8_t c2 = frm_nxt[1];
1814 uint8_t c3 = frm_nxt[2];
1815 uint8_t c4 = frm_nxt[3];
1816 switch (c1)
1817 {
1818 case 0xF0:
1819 if (!(0x90 <= c2 && c2 <= 0xBF))
1820 return static_cast<int>(frm_nxt - frm);
1821 break;
1822 case 0xF4:
1823 if ((c2 & 0xF0) != 0x80)
1824 return static_cast<int>(frm_nxt - frm);
1825 break;
1826 default:
1827 if ((c2 & 0xC0) != 0x80)
1828 return static_cast<int>(frm_nxt - frm);
1829 break;
1830 }
1831 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1832 break;
1833 if (((((unsigned long)c1 & 7) << 18) +
1834 (((unsigned long)c2 & 0x3F) << 12) +
1835 (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode)
1836 break;
1837 ++nchar16_t;
1838 frm_nxt += 4;
1839 }
1840 else
1841 {
1842 break;
1843 }
1844 }
1845 return static_cast<int>(frm_nxt - frm);
1846}
1847
1848static
1849codecvt_base::result
1850ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
1851 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
1852 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1853{
1854 frm_nxt = frm;
1855 to_nxt = to;
1856 if (mode & generate_header)
1857 {
1858 if (to_end-to_nxt < 3)
1859 return codecvt_base::partial;
1860 *to_nxt++ = static_cast<uint8_t>(0xEF);
1861 *to_nxt++ = static_cast<uint8_t>(0xBB);
1862 *to_nxt++ = static_cast<uint8_t>(0xBF);
1863 }
1864 for (; frm_nxt < frm_end; ++frm_nxt)
1865 {
1866 uint32_t wc = *frm_nxt;
1867 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
1868 return codecvt_base::error;
1869 if (wc < 0x000080)
1870 {
1871 if (to_end-to_nxt < 1)
1872 return codecvt_base::partial;
1873 *to_nxt++ = static_cast<uint8_t>(wc);
1874 }
1875 else if (wc < 0x000800)
1876 {
1877 if (to_end-to_nxt < 2)
1878 return codecvt_base::partial;
1879 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
1880 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
1881 }
1882 else if (wc < 0x010000)
1883 {
1884 if (to_end-to_nxt < 3)
1885 return codecvt_base::partial;
1886 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
1887 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
1888 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
1889 }
1890 else // if (wc < 0x110000)
1891 {
1892 if (to_end-to_nxt < 4)
1893 return codecvt_base::partial;
1894 *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18));
1895 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12));
1896 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6));
1897 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F));
1898 }
1899 }
1900 return codecvt_base::ok;
1901}
1902
1903static
1904codecvt_base::result
1905utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
1906 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
1907 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
1908{
1909 frm_nxt = frm;
1910 to_nxt = to;
1911 if (mode & consume_header)
1912 {
1913 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
1914 frm_nxt[2] == 0xBF)
1915 frm_nxt += 3;
1916 }
1917 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1918 {
1919 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
1920 if (c1 < 0x80)
1921 {
1922 if (c1 > Maxcode)
1923 return codecvt_base::error;
1924 *to_nxt = static_cast<uint32_t>(c1);
1925 ++frm_nxt;
1926 }
1927 else if (c1 < 0xC2)
1928 {
1929 return codecvt_base::error;
1930 }
1931 else if (c1 < 0xE0)
1932 {
1933 if (frm_end-frm_nxt < 2)
1934 return codecvt_base::partial;
1935 uint8_t c2 = frm_nxt[1];
1936 if ((c2 & 0xC0) != 0x80)
1937 return codecvt_base::error;
1938 uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6)
1939 | (c2 & 0x3F));
1940 if (t > Maxcode)
1941 return codecvt_base::error;
1942 *to_nxt = t;
1943 frm_nxt += 2;
1944 }
1945 else if (c1 < 0xF0)
1946 {
1947 if (frm_end-frm_nxt < 3)
1948 return codecvt_base::partial;
1949 uint8_t c2 = frm_nxt[1];
1950 uint8_t c3 = frm_nxt[2];
1951 switch (c1)
1952 {
1953 case 0xE0:
1954 if ((c2 & 0xE0) != 0xA0)
1955 return codecvt_base::error;
1956 break;
1957 case 0xED:
1958 if ((c2 & 0xE0) != 0x80)
1959 return codecvt_base::error;
1960 break;
1961 default:
1962 if ((c2 & 0xC0) != 0x80)
1963 return codecvt_base::error;
1964 break;
1965 }
1966 if ((c3 & 0xC0) != 0x80)
1967 return codecvt_base::error;
1968 uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12)
1969 | ((c2 & 0x3F) << 6)
1970 | (c3 & 0x3F));
1971 if (t > Maxcode)
1972 return codecvt_base::error;
1973 *to_nxt = t;
1974 frm_nxt += 3;
1975 }
1976 else if (c1 < 0xF5)
1977 {
1978 if (frm_end-frm_nxt < 4)
1979 return codecvt_base::partial;
1980 uint8_t c2 = frm_nxt[1];
1981 uint8_t c3 = frm_nxt[2];
1982 uint8_t c4 = frm_nxt[3];
1983 switch (c1)
1984 {
1985 case 0xF0:
1986 if (!(0x90 <= c2 && c2 <= 0xBF))
1987 return codecvt_base::error;
1988 break;
1989 case 0xF4:
1990 if ((c2 & 0xF0) != 0x80)
1991 return codecvt_base::error;
1992 break;
1993 default:
1994 if ((c2 & 0xC0) != 0x80)
1995 return codecvt_base::error;
1996 break;
1997 }
1998 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1999 return codecvt_base::error;
2000 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2001 | ((c2 & 0x3F) << 12)
2002 | ((c3 & 0x3F) << 6)
2003 | (c4 & 0x3F));
2004 if (t > Maxcode)
2005 return codecvt_base::error;
2006 *to_nxt = t;
2007 frm_nxt += 4;
2008 }
2009 else
2010 {
2011 return codecvt_base::error;
2012 }
2013 }
2014 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2015}
2016
2017static
2018int
2019utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2020 size_t mx, unsigned long Maxcode = 0x10FFFF,
2021 codecvt_mode mode = codecvt_mode(0))
2022{
2023 const uint8_t* frm_nxt = frm;
2024 if (mode & consume_header)
2025 {
2026 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2027 frm_nxt[2] == 0xBF)
2028 frm_nxt += 3;
2029 }
2030 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2031 {
2032 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2033 if (c1 < 0x80)
2034 {
2035 if (c1 > Maxcode)
2036 break;
2037 ++frm_nxt;
2038 }
2039 else if (c1 < 0xC2)
2040 {
2041 break;
2042 }
2043 else if (c1 < 0xE0)
2044 {
2045 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2046 break;
2047 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2048 break;
2049 frm_nxt += 2;
2050 }
2051 else if (c1 < 0xF0)
2052 {
2053 if (frm_end-frm_nxt < 3)
2054 break;
2055 uint8_t c2 = frm_nxt[1];
2056 uint8_t c3 = frm_nxt[2];
2057 switch (c1)
2058 {
2059 case 0xE0:
2060 if ((c2 & 0xE0) != 0xA0)
2061 return static_cast<int>(frm_nxt - frm);
2062 break;
2063 case 0xED:
2064 if ((c2 & 0xE0) != 0x80)
2065 return static_cast<int>(frm_nxt - frm);
2066 break;
2067 default:
2068 if ((c2 & 0xC0) != 0x80)
2069 return static_cast<int>(frm_nxt - frm);
2070 break;
2071 }
2072 if ((c3 & 0xC0) != 0x80)
2073 break;
2074 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2075 break;
2076 frm_nxt += 3;
2077 }
2078 else if (c1 < 0xF5)
2079 {
2080 if (frm_end-frm_nxt < 4)
2081 break;
2082 uint8_t c2 = frm_nxt[1];
2083 uint8_t c3 = frm_nxt[2];
2084 uint8_t c4 = frm_nxt[3];
2085 switch (c1)
2086 {
2087 case 0xF0:
2088 if (!(0x90 <= c2 && c2 <= 0xBF))
2089 return static_cast<int>(frm_nxt - frm);
2090 break;
2091 case 0xF4:
2092 if ((c2 & 0xF0) != 0x80)
2093 return static_cast<int>(frm_nxt - frm);
2094 break;
2095 default:
2096 if ((c2 & 0xC0) != 0x80)
2097 return static_cast<int>(frm_nxt - frm);
2098 break;
2099 }
2100 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
2101 break;
2102 uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18)
2103 | ((c2 & 0x3F) << 12)
2104 | ((c3 & 0x3F) << 6)
2105 | (c4 & 0x3F));
2106 if ((((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) |
2107 ((c3 & 0x3F) << 6) | (c4 & 0x3F)) > Maxcode)
2108 break;
2109 frm_nxt += 4;
2110 }
2111 else
2112 {
2113 break;
2114 }
2115 }
2116 return static_cast<int>(frm_nxt - frm);
2117}
2118
2119static
2120codecvt_base::result
2121ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2122 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2123 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2124{
2125 frm_nxt = frm;
2126 to_nxt = to;
2127 if (mode & generate_header)
2128 {
2129 if (to_end-to_nxt < 3)
2130 return codecvt_base::partial;
2131 *to_nxt++ = static_cast<uint8_t>(0xEF);
2132 *to_nxt++ = static_cast<uint8_t>(0xBB);
2133 *to_nxt++ = static_cast<uint8_t>(0xBF);
2134 }
2135 for (; frm_nxt < frm_end; ++frm_nxt)
2136 {
2137 uint16_t wc = *frm_nxt;
2138 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2139 return codecvt_base::error;
2140 if (wc < 0x0080)
2141 {
2142 if (to_end-to_nxt < 1)
2143 return codecvt_base::partial;
2144 *to_nxt++ = static_cast<uint8_t>(wc);
2145 }
2146 else if (wc < 0x0800)
2147 {
2148 if (to_end-to_nxt < 2)
2149 return codecvt_base::partial;
2150 *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6));
2151 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F));
2152 }
2153 else // if (wc <= 0xFFFF)
2154 {
2155 if (to_end-to_nxt < 3)
2156 return codecvt_base::partial;
2157 *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12));
2158 *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6));
2159 *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F));
2160 }
2161 }
2162 return codecvt_base::ok;
2163}
2164
2165static
2166codecvt_base::result
2167utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2168 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2169 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2170{
2171 frm_nxt = frm;
2172 to_nxt = to;
2173 if (mode & consume_header)
2174 {
2175 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2176 frm_nxt[2] == 0xBF)
2177 frm_nxt += 3;
2178 }
2179 for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
2180 {
2181 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2182 if (c1 < 0x80)
2183 {
2184 if (c1 > Maxcode)
2185 return codecvt_base::error;
2186 *to_nxt = static_cast<uint16_t>(c1);
2187 ++frm_nxt;
2188 }
2189 else if (c1 < 0xC2)
2190 {
2191 return codecvt_base::error;
2192 }
2193 else if (c1 < 0xE0)
2194 {
2195 if (frm_end-frm_nxt < 2)
2196 return codecvt_base::partial;
2197 uint8_t c2 = frm_nxt[1];
2198 if ((c2 & 0xC0) != 0x80)
2199 return codecvt_base::error;
2200 uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6)
2201 | (c2 & 0x3F));
2202 if (t > Maxcode)
2203 return codecvt_base::error;
2204 *to_nxt = t;
2205 frm_nxt += 2;
2206 }
2207 else if (c1 < 0xF0)
2208 {
2209 if (frm_end-frm_nxt < 3)
2210 return codecvt_base::partial;
2211 uint8_t c2 = frm_nxt[1];
2212 uint8_t c3 = frm_nxt[2];
2213 switch (c1)
2214 {
2215 case 0xE0:
2216 if ((c2 & 0xE0) != 0xA0)
2217 return codecvt_base::error;
2218 break;
2219 case 0xED:
2220 if ((c2 & 0xE0) != 0x80)
2221 return codecvt_base::error;
2222 break;
2223 default:
2224 if ((c2 & 0xC0) != 0x80)
2225 return codecvt_base::error;
2226 break;
2227 }
2228 if ((c3 & 0xC0) != 0x80)
2229 return codecvt_base::error;
2230 uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12)
2231 | ((c2 & 0x3F) << 6)
2232 | (c3 & 0x3F));
2233 if (t > Maxcode)
2234 return codecvt_base::error;
2235 *to_nxt = t;
2236 frm_nxt += 3;
2237 }
2238 else
2239 {
2240 return codecvt_base::error;
2241 }
2242 }
2243 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2244}
2245
2246static
2247int
2248utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2249 size_t mx, unsigned long Maxcode = 0x10FFFF,
2250 codecvt_mode mode = codecvt_mode(0))
2251{
2252 const uint8_t* frm_nxt = frm;
2253 if (mode & consume_header)
2254 {
2255 if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB &&
2256 frm_nxt[2] == 0xBF)
2257 frm_nxt += 3;
2258 }
2259 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
2260 {
2261 uint8_t c1 = static_cast<uint8_t>(*frm_nxt);
2262 if (c1 < 0x80)
2263 {
2264 if (c1 > Maxcode)
2265 break;
2266 ++frm_nxt;
2267 }
2268 else if (c1 < 0xC2)
2269 {
2270 break;
2271 }
2272 else if (c1 < 0xE0)
2273 {
2274 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
2275 break;
2276 if ((((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)) > Maxcode)
2277 break;
2278 frm_nxt += 2;
2279 }
2280 else if (c1 < 0xF0)
2281 {
2282 if (frm_end-frm_nxt < 3)
2283 break;
2284 uint8_t c2 = frm_nxt[1];
2285 uint8_t c3 = frm_nxt[2];
2286 switch (c1)
2287 {
2288 case 0xE0:
2289 if ((c2 & 0xE0) != 0xA0)
2290 return static_cast<int>(frm_nxt - frm);
2291 break;
2292 case 0xED:
2293 if ((c2 & 0xE0) != 0x80)
2294 return static_cast<int>(frm_nxt - frm);
2295 break;
2296 default:
2297 if ((c2 & 0xC0) != 0x80)
2298 return static_cast<int>(frm_nxt - frm);
2299 break;
2300 }
2301 if ((c3 & 0xC0) != 0x80)
2302 break;
2303 if ((((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F)) > Maxcode)
2304 break;
2305 frm_nxt += 3;
2306 }
2307 else
2308 {
2309 break;
2310 }
2311 }
2312 return static_cast<int>(frm_nxt - frm);
2313}
2314
2315static
2316codecvt_base::result
2317ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2318 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2319 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2320{
2321 frm_nxt = frm;
2322 to_nxt = to;
2323 if (mode & generate_header)
2324 {
2325 if (to_end-to_nxt < 2)
2326 return codecvt_base::partial;
2327 *to_nxt++ = static_cast<uint8_t>(0xFE);
2328 *to_nxt++ = static_cast<uint8_t>(0xFF);
2329 }
2330 for (; frm_nxt < frm_end; ++frm_nxt)
2331 {
2332 uint32_t wc = *frm_nxt;
2333 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2334 return codecvt_base::error;
2335 if (wc < 0x010000)
2336 {
2337 if (to_end-to_nxt < 2)
2338 return codecvt_base::partial;
2339 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2340 *to_nxt++ = static_cast<uint8_t>(wc);
2341 }
2342 else
2343 {
2344 if (to_end-to_nxt < 4)
2345 return codecvt_base::partial;
2346 uint16_t t = static_cast<uint16_t>(
2347 0xD800
2348 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2349 | ((wc & 0x00FC00) >> 10));
2350 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2351 *to_nxt++ = static_cast<uint8_t>(t);
2352 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2353 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2354 *to_nxt++ = static_cast<uint8_t>(t);
2355 }
2356 }
2357 return codecvt_base::ok;
2358}
2359
2360static
2361codecvt_base::result
2362utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2363 uint32_t* to, uint32_t* to_end, uint32_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 >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2371 frm_nxt += 2;
2372 }
2373 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2374 {
2375 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2376 if ((c1 & 0xFC00) == 0xDC00)
2377 return codecvt_base::error;
2378 if ((c1 & 0xFC00) != 0xD800)
2379 {
2380 if (c1 > Maxcode)
2381 return codecvt_base::error;
2382 *to_nxt = static_cast<uint32_t>(c1);
2383 frm_nxt += 2;
2384 }
2385 else
2386 {
2387 if (frm_end-frm_nxt < 4)
2388 return codecvt_base::partial;
2389 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2390 if ((c2 & 0xFC00) != 0xDC00)
2391 return codecvt_base::error;
2392 uint32_t t = static_cast<uint32_t>(
2393 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2394 | ((c1 & 0x003F) << 10)
2395 | (c2 & 0x03FF));
2396 if (t > Maxcode)
2397 return codecvt_base::error;
2398 *to_nxt = t;
2399 frm_nxt += 4;
2400 }
2401 }
2402 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2403}
2404
2405static
2406int
2407utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2408 size_t mx, unsigned long Maxcode = 0x10FFFF,
2409 codecvt_mode mode = codecvt_mode(0))
2410{
2411 const uint8_t* frm_nxt = frm;
2412 frm_nxt = frm;
2413 if (mode & consume_header)
2414 {
2415 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2416 frm_nxt += 2;
2417 }
2418 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2419 {
2420 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2421 if ((c1 & 0xFC00) == 0xDC00)
2422 break;
2423 if ((c1 & 0xFC00) != 0xD800)
2424 {
2425 if (c1 > Maxcode)
2426 break;
2427 frm_nxt += 2;
2428 }
2429 else
2430 {
2431 if (frm_end-frm_nxt < 4)
2432 break;
2433 uint16_t c2 = frm_nxt[2] << 8 | frm_nxt[3];
2434 if ((c2 & 0xFC00) != 0xDC00)
2435 break;
2436 uint32_t t = static_cast<uint32_t>(
2437 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2438 | ((c1 & 0x003F) << 10)
2439 | (c2 & 0x03FF));
2440 if (t > Maxcode)
2441 break;
2442 frm_nxt += 4;
2443 }
2444 }
2445 return static_cast<int>(frm_nxt - frm);
2446}
2447
2448static
2449codecvt_base::result
2450ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt,
2451 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2452 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2453{
2454 frm_nxt = frm;
2455 to_nxt = to;
2456 if (mode & generate_header)
2457 {
2458 if (to_end-to_nxt < 2)
2459 return codecvt_base::partial;
2460 *to_nxt++ = static_cast<uint8_t>(0xFF);
2461 *to_nxt++ = static_cast<uint8_t>(0xFE);
2462 }
2463 for (; frm_nxt < frm_end; ++frm_nxt)
2464 {
2465 uint32_t wc = *frm_nxt;
2466 if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode)
2467 return codecvt_base::error;
2468 if (wc < 0x010000)
2469 {
2470 if (to_end-to_nxt < 2)
2471 return codecvt_base::partial;
2472 *to_nxt++ = static_cast<uint8_t>(wc);
2473 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2474 }
2475 else
2476 {
2477 if (to_end-to_nxt < 4)
2478 return codecvt_base::partial;
2479 uint16_t t = static_cast<uint16_t>(
2480 0xD800
2481 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
2482 | ((wc & 0x00FC00) >> 10));
2483 *to_nxt++ = static_cast<uint8_t>(t);
2484 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2485 t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF));
2486 *to_nxt++ = static_cast<uint8_t>(t);
2487 *to_nxt++ = static_cast<uint8_t>(t >> 8);
2488 }
2489 }
2490 return codecvt_base::ok;
2491}
2492
2493static
2494codecvt_base::result
2495utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2496 uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt,
2497 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2498{
2499 frm_nxt = frm;
2500 to_nxt = to;
2501 if (mode & consume_header)
2502 {
2503 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2504 frm_nxt += 2;
2505 }
2506 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2507 {
2508 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2509 if ((c1 & 0xFC00) == 0xDC00)
2510 return codecvt_base::error;
2511 if ((c1 & 0xFC00) != 0xD800)
2512 {
2513 if (c1 > Maxcode)
2514 return codecvt_base::error;
2515 *to_nxt = static_cast<uint32_t>(c1);
2516 frm_nxt += 2;
2517 }
2518 else
2519 {
2520 if (frm_end-frm_nxt < 4)
2521 return codecvt_base::partial;
2522 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2523 if ((c2 & 0xFC00) != 0xDC00)
2524 return codecvt_base::error;
2525 uint32_t t = static_cast<uint32_t>(
2526 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2527 | ((c1 & 0x003F) << 10)
2528 | (c2 & 0x03FF));
2529 if (t > Maxcode)
2530 return codecvt_base::error;
2531 *to_nxt = t;
2532 frm_nxt += 4;
2533 }
2534 }
2535 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2536}
2537
2538static
2539int
2540utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end,
2541 size_t mx, unsigned long Maxcode = 0x10FFFF,
2542 codecvt_mode mode = codecvt_mode(0))
2543{
2544 const uint8_t* frm_nxt = frm;
2545 frm_nxt = frm;
2546 if (mode & consume_header)
2547 {
2548 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2549 frm_nxt += 2;
2550 }
2551 for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t)
2552 {
2553 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2554 if ((c1 & 0xFC00) == 0xDC00)
2555 break;
2556 if ((c1 & 0xFC00) != 0xD800)
2557 {
2558 if (c1 > Maxcode)
2559 break;
2560 frm_nxt += 2;
2561 }
2562 else
2563 {
2564 if (frm_end-frm_nxt < 4)
2565 break;
2566 uint16_t c2 = frm_nxt[3] << 8 | frm_nxt[2];
2567 if ((c2 & 0xFC00) != 0xDC00)
2568 break;
2569 uint32_t t = static_cast<uint32_t>(
2570 ((((c1 & 0x03C0) >> 6) + 1) << 16)
2571 | ((c1 & 0x003F) << 10)
2572 | (c2 & 0x03FF));
2573 if (t > Maxcode)
2574 break;
2575 frm_nxt += 4;
2576 }
2577 }
2578 return static_cast<int>(frm_nxt - frm);
2579}
2580
2581static
2582codecvt_base::result
2583ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2584 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2585 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2586{
2587 frm_nxt = frm;
2588 to_nxt = to;
2589 if (mode & generate_header)
2590 {
2591 if (to_end-to_nxt < 2)
2592 return codecvt_base::partial;
2593 *to_nxt++ = static_cast<uint8_t>(0xFE);
2594 *to_nxt++ = static_cast<uint8_t>(0xFF);
2595 }
2596 for (; frm_nxt < frm_end; ++frm_nxt)
2597 {
2598 uint16_t wc = *frm_nxt;
2599 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2600 return codecvt_base::error;
2601 if (to_end-to_nxt < 2)
2602 return codecvt_base::partial;
2603 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2604 *to_nxt++ = static_cast<uint8_t>(wc);
2605 }
2606 return codecvt_base::ok;
2607}
2608
2609static
2610codecvt_base::result
2611utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2612 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2613 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2614{
2615 frm_nxt = frm;
2616 to_nxt = to;
2617 if (mode & consume_header)
2618 {
2619 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2620 frm_nxt += 2;
2621 }
2622 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2623 {
2624 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2625 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2626 return codecvt_base::error;
2627 *to_nxt = c1;
2628 frm_nxt += 2;
2629 }
2630 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2631}
2632
2633static
2634int
2635utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2636 size_t mx, unsigned long Maxcode = 0x10FFFF,
2637 codecvt_mode mode = codecvt_mode(0))
2638{
2639 const uint8_t* frm_nxt = frm;
2640 frm_nxt = frm;
2641 if (mode & consume_header)
2642 {
2643 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF)
2644 frm_nxt += 2;
2645 }
2646 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2647 {
2648 uint16_t c1 = frm_nxt[0] << 8 | frm_nxt[1];
2649 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2650 break;
2651 frm_nxt += 2;
2652 }
2653 return static_cast<int>(frm_nxt - frm);
2654}
2655
2656static
2657codecvt_base::result
2658ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt,
2659 uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt,
2660 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2661{
2662 frm_nxt = frm;
2663 to_nxt = to;
2664 if (mode & generate_header)
2665 {
2666 if (to_end-to_nxt < 2)
2667 return codecvt_base::partial;
2668 *to_nxt++ = static_cast<uint8_t>(0xFF);
2669 *to_nxt++ = static_cast<uint8_t>(0xFE);
2670 }
2671 for (; frm_nxt < frm_end; ++frm_nxt)
2672 {
2673 uint16_t wc = *frm_nxt;
2674 if ((wc & 0xF800) == 0xD800 || wc > Maxcode)
2675 return codecvt_base::error;
2676 if (to_end-to_nxt < 2)
2677 return codecvt_base::partial;
2678 *to_nxt++ = static_cast<uint8_t>(wc);
2679 *to_nxt++ = static_cast<uint8_t>(wc >> 8);
2680 }
2681 return codecvt_base::ok;
2682}
2683
2684static
2685codecvt_base::result
2686utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt,
2687 uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt,
2688 unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0))
2689{
2690 frm_nxt = frm;
2691 to_nxt = to;
2692 if (mode & consume_header)
2693 {
2694 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2695 frm_nxt += 2;
2696 }
2697 for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt)
2698 {
2699 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2700 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2701 return codecvt_base::error;
2702 *to_nxt = c1;
2703 frm_nxt += 2;
2704 }
2705 return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok;
2706}
2707
2708static
2709int
2710utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end,
2711 size_t mx, unsigned long Maxcode = 0x10FFFF,
2712 codecvt_mode mode = codecvt_mode(0))
2713{
2714 const uint8_t* frm_nxt = frm;
2715 frm_nxt = frm;
2716 if (mode & consume_header)
2717 {
2718 if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE)
2719 frm_nxt += 2;
2720 }
2721 for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t)
2722 {
2723 uint16_t c1 = frm_nxt[1] << 8 | frm_nxt[0];
2724 if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode)
2725 break;
2726 frm_nxt += 2;
2727 }
2728 return static_cast<int>(frm_nxt - frm);
2729}
2730
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002731// template <> class codecvt<char16_t, char, mbstate_t>
2732
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002733locale::id codecvt<char16_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002734
2735codecvt<char16_t, char, mbstate_t>::~codecvt()
2736{
2737}
2738
2739codecvt<char16_t, char, mbstate_t>::result
2740codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002741 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002742 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2743{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002744 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2745 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2746 const uint16_t* _frm_nxt = _frm;
2747 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2748 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2749 uint8_t* _to_nxt = _to;
2750 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2751 frm_nxt = frm + (_frm_nxt - _frm);
2752 to_nxt = to + (_to_nxt - _to);
2753 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002754}
2755
2756codecvt<char16_t, char, mbstate_t>::result
2757codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002758 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002759 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2760{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002761 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2762 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2763 const uint8_t* _frm_nxt = _frm;
2764 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2765 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2766 uint16_t* _to_nxt = _to;
2767 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2768 frm_nxt = frm + (_frm_nxt - _frm);
2769 to_nxt = to + (_to_nxt - _to);
2770 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002771}
2772
2773codecvt<char16_t, char, mbstate_t>::result
2774codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
2775 extern_type* to, extern_type*, extern_type*& to_nxt) const
2776{
2777 to_nxt = to;
2778 return noconv;
2779}
2780
2781int
2782codecvt<char16_t, char, mbstate_t>::do_encoding() const throw()
2783{
2784 return 0;
2785}
2786
2787bool
2788codecvt<char16_t, char, mbstate_t>::do_always_noconv() const throw()
2789{
2790 return false;
2791}
2792
2793int
2794codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
2795 const extern_type* frm, const extern_type* frm_end, size_t mx) const
2796{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002797 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2798 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2799 return utf8_to_utf16_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002800}
2801
2802int
2803codecvt<char16_t, char, mbstate_t>::do_max_length() const throw()
2804{
2805 return 4;
2806}
2807
2808// template <> class codecvt<char32_t, char, mbstate_t>
2809
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002810locale::id codecvt<char32_t, char, mbstate_t>::id;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002811
2812codecvt<char32_t, char, mbstate_t>::~codecvt()
2813{
2814}
2815
2816codecvt<char32_t, char, mbstate_t>::result
2817codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002818 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002819 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2820{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002821 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
2822 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
2823 const uint32_t* _frm_nxt = _frm;
2824 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2825 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2826 uint8_t* _to_nxt = _to;
2827 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2828 frm_nxt = frm + (_frm_nxt - _frm);
2829 to_nxt = to + (_to_nxt - _to);
2830 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002831}
2832
2833codecvt<char32_t, char, mbstate_t>::result
2834codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00002835 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002836 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2837{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002838 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2839 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2840 const uint8_t* _frm_nxt = _frm;
2841 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
2842 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
2843 uint32_t* _to_nxt = _to;
2844 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt);
2845 frm_nxt = frm + (_frm_nxt - _frm);
2846 to_nxt = to + (_to_nxt - _to);
2847 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002848}
2849
2850codecvt<char32_t, char, mbstate_t>::result
2851codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
2852 extern_type* to, extern_type*, extern_type*& to_nxt) const
2853{
2854 to_nxt = to;
2855 return noconv;
2856}
2857
2858int
2859codecvt<char32_t, char, mbstate_t>::do_encoding() const throw()
2860{
2861 return 0;
2862}
2863
2864bool
2865codecvt<char32_t, char, mbstate_t>::do_always_noconv() const throw()
2866{
2867 return false;
2868}
2869
2870int
2871codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
2872 const extern_type* frm, const extern_type* frm_end, size_t mx) const
2873{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002874 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2875 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2876 return utf8_to_ucs4_length(_frm, _frm_end, mx);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002877}
2878
2879int
2880codecvt<char32_t, char, mbstate_t>::do_max_length() const throw()
2881{
2882 return 4;
2883}
2884
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002885// __codecvt_utf8<wchar_t>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002886
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002887__codecvt_utf8<wchar_t>::result
2888__codecvt_utf8<wchar_t>::do_out(state_type&,
2889 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002890 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2891{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002892 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
2893 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
2894 const uint32_t* _frm_nxt = _frm;
2895 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2896 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2897 uint8_t* _to_nxt = _to;
2898 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
2899 _Maxcode_, _Mode_);
2900 frm_nxt = frm + (_frm_nxt - _frm);
2901 to_nxt = to + (_to_nxt - _to);
2902 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002903}
2904
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002905__codecvt_utf8<wchar_t>::result
2906__codecvt_utf8<wchar_t>::do_in(state_type&,
2907 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002908 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2909{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002910 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2911 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2912 const uint8_t* _frm_nxt = _frm;
2913 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
2914 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
2915 uint32_t* _to_nxt = _to;
2916 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
2917 _Maxcode_, _Mode_);
2918 frm_nxt = frm + (_frm_nxt - _frm);
2919 to_nxt = to + (_to_nxt - _to);
2920 return r;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002921}
2922
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002923__codecvt_utf8<wchar_t>::result
2924__codecvt_utf8<wchar_t>::do_unshift(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002925 extern_type* to, extern_type*, extern_type*& to_nxt) const
2926{
2927 to_nxt = to;
2928 return noconv;
2929}
2930
2931int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002932__codecvt_utf8<wchar_t>::do_encoding() const throw()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002933{
2934 return 0;
2935}
2936
2937bool
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002938__codecvt_utf8<wchar_t>::do_always_noconv() const throw()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002939{
2940 return false;
2941}
2942
2943int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002944__codecvt_utf8<wchar_t>::do_length(state_type&,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002945 const extern_type* frm, const extern_type* frm_end, size_t mx) const
2946{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002947 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2948 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2949 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002950}
2951
2952int
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002953__codecvt_utf8<wchar_t>::do_max_length() const throw()
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002954{
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00002955 if (_Mode_ & consume_header)
2956 return 7;
2957 return 4;
2958}
2959
2960// __codecvt_utf8<char16_t>
2961
2962__codecvt_utf8<char16_t>::result
2963__codecvt_utf8<char16_t>::do_out(state_type&,
2964 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
2965 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
2966{
2967 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
2968 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
2969 const uint16_t* _frm_nxt = _frm;
2970 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
2971 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
2972 uint8_t* _to_nxt = _to;
2973 result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
2974 _Maxcode_, _Mode_);
2975 frm_nxt = frm + (_frm_nxt - _frm);
2976 to_nxt = to + (_to_nxt - _to);
2977 return r;
2978}
2979
2980__codecvt_utf8<char16_t>::result
2981__codecvt_utf8<char16_t>::do_in(state_type&,
2982 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
2983 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
2984{
2985 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
2986 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
2987 const uint8_t* _frm_nxt = _frm;
2988 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
2989 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
2990 uint16_t* _to_nxt = _to;
2991 result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
2992 _Maxcode_, _Mode_);
2993 frm_nxt = frm + (_frm_nxt - _frm);
2994 to_nxt = to + (_to_nxt - _to);
2995 return r;
2996}
2997
2998__codecvt_utf8<char16_t>::result
2999__codecvt_utf8<char16_t>::do_unshift(state_type&,
3000 extern_type* to, extern_type*, extern_type*& to_nxt) const
3001{
3002 to_nxt = to;
3003 return noconv;
3004}
3005
3006int
3007__codecvt_utf8<char16_t>::do_encoding() const throw()
3008{
3009 return 0;
3010}
3011
3012bool
3013__codecvt_utf8<char16_t>::do_always_noconv() const throw()
3014{
3015 return false;
3016}
3017
3018int
3019__codecvt_utf8<char16_t>::do_length(state_type&,
3020 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3021{
3022 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3023 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3024 return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3025}
3026
3027int
3028__codecvt_utf8<char16_t>::do_max_length() const throw()
3029{
3030 if (_Mode_ & consume_header)
3031 return 6;
3032 return 3;
3033}
3034
3035// __codecvt_utf8<char32_t>
3036
3037__codecvt_utf8<char32_t>::result
3038__codecvt_utf8<char32_t>::do_out(state_type&,
3039 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3040 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3041{
3042 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3043 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3044 const uint32_t* _frm_nxt = _frm;
3045 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3046 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3047 uint8_t* _to_nxt = _to;
3048 result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3049 _Maxcode_, _Mode_);
3050 frm_nxt = frm + (_frm_nxt - _frm);
3051 to_nxt = to + (_to_nxt - _to);
3052 return r;
3053}
3054
3055__codecvt_utf8<char32_t>::result
3056__codecvt_utf8<char32_t>::do_in(state_type&,
3057 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3058 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3059{
3060 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3061 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3062 const uint8_t* _frm_nxt = _frm;
3063 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3064 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3065 uint32_t* _to_nxt = _to;
3066 result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3067 _Maxcode_, _Mode_);
3068 frm_nxt = frm + (_frm_nxt - _frm);
3069 to_nxt = to + (_to_nxt - _to);
3070 return r;
3071}
3072
3073__codecvt_utf8<char32_t>::result
3074__codecvt_utf8<char32_t>::do_unshift(state_type&,
3075 extern_type* to, extern_type*, extern_type*& to_nxt) const
3076{
3077 to_nxt = to;
3078 return noconv;
3079}
3080
3081int
3082__codecvt_utf8<char32_t>::do_encoding() const throw()
3083{
3084 return 0;
3085}
3086
3087bool
3088__codecvt_utf8<char32_t>::do_always_noconv() const throw()
3089{
3090 return false;
3091}
3092
3093int
3094__codecvt_utf8<char32_t>::do_length(state_type&,
3095 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3096{
3097 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3098 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3099 return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3100}
3101
3102int
3103__codecvt_utf8<char32_t>::do_max_length() const throw()
3104{
3105 if (_Mode_ & consume_header)
3106 return 7;
3107 return 4;
3108}
3109
3110// __codecvt_utf16<wchar_t, false>
3111
3112__codecvt_utf16<wchar_t, false>::result
3113__codecvt_utf16<wchar_t, false>::do_out(state_type&,
3114 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3115 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3116{
3117 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3118 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3119 const uint32_t* _frm_nxt = _frm;
3120 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3121 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3122 uint8_t* _to_nxt = _to;
3123 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3124 _Maxcode_, _Mode_);
3125 frm_nxt = frm + (_frm_nxt - _frm);
3126 to_nxt = to + (_to_nxt - _to);
3127 return r;
3128}
3129
3130__codecvt_utf16<wchar_t, false>::result
3131__codecvt_utf16<wchar_t, false>::do_in(state_type&,
3132 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3133 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3134{
3135 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3136 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3137 const uint8_t* _frm_nxt = _frm;
3138 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3139 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3140 uint32_t* _to_nxt = _to;
3141 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3142 _Maxcode_, _Mode_);
3143 frm_nxt = frm + (_frm_nxt - _frm);
3144 to_nxt = to + (_to_nxt - _to);
3145 return r;
3146}
3147
3148__codecvt_utf16<wchar_t, false>::result
3149__codecvt_utf16<wchar_t, false>::do_unshift(state_type&,
3150 extern_type* to, extern_type*, extern_type*& to_nxt) const
3151{
3152 to_nxt = to;
3153 return noconv;
3154}
3155
3156int
3157__codecvt_utf16<wchar_t, false>::do_encoding() const throw()
3158{
3159 return 0;
3160}
3161
3162bool
3163__codecvt_utf16<wchar_t, false>::do_always_noconv() const throw()
3164{
3165 return false;
3166}
3167
3168int
3169__codecvt_utf16<wchar_t, false>::do_length(state_type&,
3170 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3171{
3172 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3173 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3174 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3175}
3176
3177int
3178__codecvt_utf16<wchar_t, false>::do_max_length() const throw()
3179{
3180 if (_Mode_ & consume_header)
3181 return 6;
3182 return 4;
3183}
3184
3185// __codecvt_utf16<wchar_t, true>
3186
3187__codecvt_utf16<wchar_t, true>::result
3188__codecvt_utf16<wchar_t, true>::do_out(state_type&,
3189 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3190 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3191{
3192 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3193 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3194 const uint32_t* _frm_nxt = _frm;
3195 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3196 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3197 uint8_t* _to_nxt = _to;
3198 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3199 _Maxcode_, _Mode_);
3200 frm_nxt = frm + (_frm_nxt - _frm);
3201 to_nxt = to + (_to_nxt - _to);
3202 return r;
3203}
3204
3205__codecvt_utf16<wchar_t, true>::result
3206__codecvt_utf16<wchar_t, true>::do_in(state_type&,
3207 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3208 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3209{
3210 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3211 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3212 const uint8_t* _frm_nxt = _frm;
3213 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3214 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3215 uint32_t* _to_nxt = _to;
3216 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3217 _Maxcode_, _Mode_);
3218 frm_nxt = frm + (_frm_nxt - _frm);
3219 to_nxt = to + (_to_nxt - _to);
3220 return r;
3221}
3222
3223__codecvt_utf16<wchar_t, true>::result
3224__codecvt_utf16<wchar_t, true>::do_unshift(state_type&,
3225 extern_type* to, extern_type*, extern_type*& to_nxt) const
3226{
3227 to_nxt = to;
3228 return noconv;
3229}
3230
3231int
3232__codecvt_utf16<wchar_t, true>::do_encoding() const throw()
3233{
3234 return 0;
3235}
3236
3237bool
3238__codecvt_utf16<wchar_t, true>::do_always_noconv() const throw()
3239{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003240 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003241}
3242
3243int
3244__codecvt_utf16<wchar_t, true>::do_length(state_type&,
3245 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3246{
3247 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3248 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3249 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3250}
3251
3252int
3253__codecvt_utf16<wchar_t, true>::do_max_length() const throw()
3254{
3255 if (_Mode_ & consume_header)
3256 return 6;
3257 return 4;
3258}
3259
3260// __codecvt_utf16<char16_t, false>
3261
3262__codecvt_utf16<char16_t, false>::result
3263__codecvt_utf16<char16_t, false>::do_out(state_type&,
3264 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3265 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3266{
3267 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3268 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3269 const uint16_t* _frm_nxt = _frm;
3270 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3271 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3272 uint8_t* _to_nxt = _to;
3273 result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3274 _Maxcode_, _Mode_);
3275 frm_nxt = frm + (_frm_nxt - _frm);
3276 to_nxt = to + (_to_nxt - _to);
3277 return r;
3278}
3279
3280__codecvt_utf16<char16_t, false>::result
3281__codecvt_utf16<char16_t, false>::do_in(state_type&,
3282 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3283 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3284{
3285 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3286 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3287 const uint8_t* _frm_nxt = _frm;
3288 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3289 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3290 uint16_t* _to_nxt = _to;
3291 result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3292 _Maxcode_, _Mode_);
3293 frm_nxt = frm + (_frm_nxt - _frm);
3294 to_nxt = to + (_to_nxt - _to);
3295 return r;
3296}
3297
3298__codecvt_utf16<char16_t, false>::result
3299__codecvt_utf16<char16_t, false>::do_unshift(state_type&,
3300 extern_type* to, extern_type*, extern_type*& to_nxt) const
3301{
3302 to_nxt = to;
3303 return noconv;
3304}
3305
3306int
3307__codecvt_utf16<char16_t, false>::do_encoding() const throw()
3308{
3309 return 0;
3310}
3311
3312bool
3313__codecvt_utf16<char16_t, false>::do_always_noconv() const throw()
3314{
3315 return false;
3316}
3317
3318int
3319__codecvt_utf16<char16_t, false>::do_length(state_type&,
3320 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3321{
3322 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3323 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3324 return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3325}
3326
3327int
3328__codecvt_utf16<char16_t, false>::do_max_length() const throw()
3329{
3330 if (_Mode_ & consume_header)
3331 return 4;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003332 return 2;
3333}
3334
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003335// __codecvt_utf16<char16_t, true>
3336
3337__codecvt_utf16<char16_t, true>::result
3338__codecvt_utf16<char16_t, true>::do_out(state_type&,
3339 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3340 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3341{
3342 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3343 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3344 const uint16_t* _frm_nxt = _frm;
3345 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3346 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3347 uint8_t* _to_nxt = _to;
3348 result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3349 _Maxcode_, _Mode_);
3350 frm_nxt = frm + (_frm_nxt - _frm);
3351 to_nxt = to + (_to_nxt - _to);
3352 return r;
3353}
3354
3355__codecvt_utf16<char16_t, true>::result
3356__codecvt_utf16<char16_t, true>::do_in(state_type&,
3357 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3358 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3359{
3360 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3361 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3362 const uint8_t* _frm_nxt = _frm;
3363 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3364 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3365 uint16_t* _to_nxt = _to;
3366 result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3367 _Maxcode_, _Mode_);
3368 frm_nxt = frm + (_frm_nxt - _frm);
3369 to_nxt = to + (_to_nxt - _to);
3370 return r;
3371}
3372
3373__codecvt_utf16<char16_t, true>::result
3374__codecvt_utf16<char16_t, true>::do_unshift(state_type&,
3375 extern_type* to, extern_type*, extern_type*& to_nxt) const
3376{
3377 to_nxt = to;
3378 return noconv;
3379}
3380
3381int
3382__codecvt_utf16<char16_t, true>::do_encoding() const throw()
3383{
3384 return 0;
3385}
3386
3387bool
3388__codecvt_utf16<char16_t, true>::do_always_noconv() const throw()
3389{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003390 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003391}
3392
3393int
3394__codecvt_utf16<char16_t, true>::do_length(state_type&,
3395 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3396{
3397 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3398 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3399 return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3400}
3401
3402int
3403__codecvt_utf16<char16_t, true>::do_max_length() const throw()
3404{
3405 if (_Mode_ & consume_header)
3406 return 4;
3407 return 2;
3408}
3409
3410// __codecvt_utf16<char32_t, false>
3411
3412__codecvt_utf16<char32_t, false>::result
3413__codecvt_utf16<char32_t, false>::do_out(state_type&,
3414 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3415 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3416{
3417 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3418 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3419 const uint32_t* _frm_nxt = _frm;
3420 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3421 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3422 uint8_t* _to_nxt = _to;
3423 result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3424 _Maxcode_, _Mode_);
3425 frm_nxt = frm + (_frm_nxt - _frm);
3426 to_nxt = to + (_to_nxt - _to);
3427 return r;
3428}
3429
3430__codecvt_utf16<char32_t, false>::result
3431__codecvt_utf16<char32_t, false>::do_in(state_type&,
3432 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3433 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3434{
3435 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3436 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3437 const uint8_t* _frm_nxt = _frm;
3438 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3439 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3440 uint32_t* _to_nxt = _to;
3441 result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3442 _Maxcode_, _Mode_);
3443 frm_nxt = frm + (_frm_nxt - _frm);
3444 to_nxt = to + (_to_nxt - _to);
3445 return r;
3446}
3447
3448__codecvt_utf16<char32_t, false>::result
3449__codecvt_utf16<char32_t, false>::do_unshift(state_type&,
3450 extern_type* to, extern_type*, extern_type*& to_nxt) const
3451{
3452 to_nxt = to;
3453 return noconv;
3454}
3455
3456int
3457__codecvt_utf16<char32_t, false>::do_encoding() const throw()
3458{
3459 return 0;
3460}
3461
3462bool
3463__codecvt_utf16<char32_t, false>::do_always_noconv() const throw()
3464{
3465 return false;
3466}
3467
3468int
3469__codecvt_utf16<char32_t, false>::do_length(state_type&,
3470 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3471{
3472 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3473 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3474 return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3475}
3476
3477int
3478__codecvt_utf16<char32_t, false>::do_max_length() const throw()
3479{
3480 if (_Mode_ & consume_header)
3481 return 6;
3482 return 4;
3483}
3484
3485// __codecvt_utf16<char32_t, true>
3486
3487__codecvt_utf16<char32_t, true>::result
3488__codecvt_utf16<char32_t, true>::do_out(state_type&,
3489 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3490 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3491{
3492 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3493 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3494 const uint32_t* _frm_nxt = _frm;
3495 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3496 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3497 uint8_t* _to_nxt = _to;
3498 result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3499 _Maxcode_, _Mode_);
3500 frm_nxt = frm + (_frm_nxt - _frm);
3501 to_nxt = to + (_to_nxt - _to);
3502 return r;
3503}
3504
3505__codecvt_utf16<char32_t, true>::result
3506__codecvt_utf16<char32_t, true>::do_in(state_type&,
3507 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3508 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3509{
3510 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3511 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3512 const uint8_t* _frm_nxt = _frm;
3513 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3514 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3515 uint32_t* _to_nxt = _to;
3516 result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3517 _Maxcode_, _Mode_);
3518 frm_nxt = frm + (_frm_nxt - _frm);
3519 to_nxt = to + (_to_nxt - _to);
3520 return r;
3521}
3522
3523__codecvt_utf16<char32_t, true>::result
3524__codecvt_utf16<char32_t, true>::do_unshift(state_type&,
3525 extern_type* to, extern_type*, extern_type*& to_nxt) const
3526{
3527 to_nxt = to;
3528 return noconv;
3529}
3530
3531int
3532__codecvt_utf16<char32_t, true>::do_encoding() const throw()
3533{
3534 return 0;
3535}
3536
3537bool
3538__codecvt_utf16<char32_t, true>::do_always_noconv() const throw()
3539{
Howard Hinnantd23b4642010-05-31 20:58:54 +00003540 return false;
Howard Hinnant87d1a8a2010-05-30 21:39:41 +00003541}
3542
3543int
3544__codecvt_utf16<char32_t, true>::do_length(state_type&,
3545 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3546{
3547 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3548 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3549 return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3550}
3551
3552int
3553__codecvt_utf16<char32_t, true>::do_max_length() const throw()
3554{
3555 if (_Mode_ & consume_header)
3556 return 6;
3557 return 4;
3558}
3559
3560// __codecvt_utf8_utf16<wchar_t>
3561
3562__codecvt_utf8_utf16<wchar_t>::result
3563__codecvt_utf8_utf16<wchar_t>::do_out(state_type&,
3564 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3565 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3566{
3567 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3568 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3569 const uint32_t* _frm_nxt = _frm;
3570 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3571 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3572 uint8_t* _to_nxt = _to;
3573 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3574 _Maxcode_, _Mode_);
3575 frm_nxt = frm + (_frm_nxt - _frm);
3576 to_nxt = to + (_to_nxt - _to);
3577 return r;
3578}
3579
3580__codecvt_utf8_utf16<wchar_t>::result
3581__codecvt_utf8_utf16<wchar_t>::do_in(state_type&,
3582 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3583 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3584{
3585 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3586 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3587 const uint8_t* _frm_nxt = _frm;
3588 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3589 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3590 uint32_t* _to_nxt = _to;
3591 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3592 _Maxcode_, _Mode_);
3593 frm_nxt = frm + (_frm_nxt - _frm);
3594 to_nxt = to + (_to_nxt - _to);
3595 return r;
3596}
3597
3598__codecvt_utf8_utf16<wchar_t>::result
3599__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&,
3600 extern_type* to, extern_type*, extern_type*& to_nxt) const
3601{
3602 to_nxt = to;
3603 return noconv;
3604}
3605
3606int
3607__codecvt_utf8_utf16<wchar_t>::do_encoding() const throw()
3608{
3609 return 0;
3610}
3611
3612bool
3613__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const throw()
3614{
3615 return false;
3616}
3617
3618int
3619__codecvt_utf8_utf16<wchar_t>::do_length(state_type&,
3620 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3621{
3622 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3623 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3624 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3625}
3626
3627int
3628__codecvt_utf8_utf16<wchar_t>::do_max_length() const throw()
3629{
3630 if (_Mode_ & consume_header)
3631 return 7;
3632 return 4;
3633}
3634
3635// __codecvt_utf8_utf16<char16_t>
3636
3637__codecvt_utf8_utf16<char16_t>::result
3638__codecvt_utf8_utf16<char16_t>::do_out(state_type&,
3639 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3640 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3641{
3642 const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm);
3643 const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end);
3644 const uint16_t* _frm_nxt = _frm;
3645 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3646 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3647 uint8_t* _to_nxt = _to;
3648 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3649 _Maxcode_, _Mode_);
3650 frm_nxt = frm + (_frm_nxt - _frm);
3651 to_nxt = to + (_to_nxt - _to);
3652 return r;
3653}
3654
3655__codecvt_utf8_utf16<char16_t>::result
3656__codecvt_utf8_utf16<char16_t>::do_in(state_type&,
3657 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3658 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3659{
3660 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3661 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3662 const uint8_t* _frm_nxt = _frm;
3663 uint16_t* _to = reinterpret_cast<uint16_t*>(to);
3664 uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end);
3665 uint16_t* _to_nxt = _to;
3666 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3667 _Maxcode_, _Mode_);
3668 frm_nxt = frm + (_frm_nxt - _frm);
3669 to_nxt = to + (_to_nxt - _to);
3670 return r;
3671}
3672
3673__codecvt_utf8_utf16<char16_t>::result
3674__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&,
3675 extern_type* to, extern_type*, extern_type*& to_nxt) const
3676{
3677 to_nxt = to;
3678 return noconv;
3679}
3680
3681int
3682__codecvt_utf8_utf16<char16_t>::do_encoding() const throw()
3683{
3684 return 0;
3685}
3686
3687bool
3688__codecvt_utf8_utf16<char16_t>::do_always_noconv() const throw()
3689{
3690 return false;
3691}
3692
3693int
3694__codecvt_utf8_utf16<char16_t>::do_length(state_type&,
3695 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3696{
3697 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3698 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3699 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3700}
3701
3702int
3703__codecvt_utf8_utf16<char16_t>::do_max_length() const throw()
3704{
3705 if (_Mode_ & consume_header)
3706 return 7;
3707 return 4;
3708}
3709
3710// __codecvt_utf8_utf16<char32_t>
3711
3712__codecvt_utf8_utf16<char32_t>::result
3713__codecvt_utf8_utf16<char32_t>::do_out(state_type&,
3714 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
3715 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
3716{
3717 const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm);
3718 const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end);
3719 const uint32_t* _frm_nxt = _frm;
3720 uint8_t* _to = reinterpret_cast<uint8_t*>(to);
3721 uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end);
3722 uint8_t* _to_nxt = _to;
3723 result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3724 _Maxcode_, _Mode_);
3725 frm_nxt = frm + (_frm_nxt - _frm);
3726 to_nxt = to + (_to_nxt - _to);
3727 return r;
3728}
3729
3730__codecvt_utf8_utf16<char32_t>::result
3731__codecvt_utf8_utf16<char32_t>::do_in(state_type&,
3732 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
3733 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
3734{
3735 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3736 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3737 const uint8_t* _frm_nxt = _frm;
3738 uint32_t* _to = reinterpret_cast<uint32_t*>(to);
3739 uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end);
3740 uint32_t* _to_nxt = _to;
3741 result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt,
3742 _Maxcode_, _Mode_);
3743 frm_nxt = frm + (_frm_nxt - _frm);
3744 to_nxt = to + (_to_nxt - _to);
3745 return r;
3746}
3747
3748__codecvt_utf8_utf16<char32_t>::result
3749__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&,
3750 extern_type* to, extern_type*, extern_type*& to_nxt) const
3751{
3752 to_nxt = to;
3753 return noconv;
3754}
3755
3756int
3757__codecvt_utf8_utf16<char32_t>::do_encoding() const throw()
3758{
3759 return 0;
3760}
3761
3762bool
3763__codecvt_utf8_utf16<char32_t>::do_always_noconv() const throw()
3764{
3765 return false;
3766}
3767
3768int
3769__codecvt_utf8_utf16<char32_t>::do_length(state_type&,
3770 const extern_type* frm, const extern_type* frm_end, size_t mx) const
3771{
3772 const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm);
3773 const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end);
3774 return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_);
3775}
3776
3777int
3778__codecvt_utf8_utf16<char32_t>::do_max_length() const throw()
3779{
3780 if (_Mode_ & consume_header)
3781 return 7;
3782 return 4;
3783}
3784
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003785// __narrow_to_utf8<16>
3786
3787__narrow_to_utf8<16>::~__narrow_to_utf8()
3788{
3789}
3790
3791// __narrow_to_utf8<32>
3792
3793__narrow_to_utf8<32>::~__narrow_to_utf8()
3794{
3795}
3796
3797// __widen_from_utf8<16>
3798
3799__widen_from_utf8<16>::~__widen_from_utf8()
3800{
3801}
3802
3803// __widen_from_utf8<32>
3804
3805__widen_from_utf8<32>::~__widen_from_utf8()
3806{
3807}
3808
3809// numpunct<char> && numpunct<wchar_t>
3810
3811locale::id numpunct< char >::id;
3812locale::id numpunct<wchar_t>::id;
3813
3814numpunct<char>::numpunct(size_t refs)
3815 : locale::facet(refs),
3816 __decimal_point_('.'),
3817 __thousands_sep_(',')
3818{
3819}
3820
3821numpunct<wchar_t>::numpunct(size_t refs)
3822 : locale::facet(refs),
3823 __decimal_point_(L'.'),
3824 __thousands_sep_(L',')
3825{
3826}
3827
3828numpunct<char>::~numpunct()
3829{
3830}
3831
3832numpunct<wchar_t>::~numpunct()
3833{
3834}
3835
3836 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
3837wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
3838
3839 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
3840wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
3841
3842string numpunct< char >::do_grouping() const {return __grouping_;}
3843string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
3844
3845 string numpunct< char >::do_truename() const {return "true";}
3846wstring numpunct<wchar_t>::do_truename() const {return L"true";}
3847
3848 string numpunct< char >::do_falsename() const {return "false";}
3849wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
3850
3851// numpunct_byname<char>
3852
3853numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
3854 : numpunct<char>(refs)
3855{
3856 __init(nm);
3857}
3858
3859numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
3860 : numpunct<char>(refs)
3861{
3862 __init(nm.c_str());
3863}
3864
3865numpunct_byname<char>::~numpunct_byname()
3866{
3867}
3868
3869void
3870numpunct_byname<char>::__init(const char* nm)
3871{
3872 if (strcmp(nm, "C") != 0)
3873 {
3874 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00003875#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003876 if (loc == 0)
3877 throw runtime_error("numpunct_byname<char>::numpunct_byname"
3878 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003879#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003880 lconv* lc = localeconv_l(loc.get());
3881 if (*lc->decimal_point)
3882 __decimal_point_ = *lc->decimal_point;
3883 if (*lc->thousands_sep)
3884 __thousands_sep_ = *lc->thousands_sep;
3885 __grouping_ = lc->grouping;
3886 // locallization for truename and falsename is not available
3887 }
3888}
3889
3890// numpunct_byname<wchar_t>
3891
3892numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
3893 : numpunct<wchar_t>(refs)
3894{
3895 __init(nm);
3896}
3897
3898numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
3899 : numpunct<wchar_t>(refs)
3900{
3901 __init(nm.c_str());
3902}
3903
3904numpunct_byname<wchar_t>::~numpunct_byname()
3905{
3906}
3907
3908void
3909numpunct_byname<wchar_t>::__init(const char* nm)
3910{
3911 if (strcmp(nm, "C") != 0)
3912 {
3913 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00003914#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003915 if (loc == 0)
3916 throw runtime_error("numpunct_byname<char>::numpunct_byname"
3917 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00003918#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00003919 lconv* lc = localeconv_l(loc.get());
3920 if (*lc->decimal_point)
3921 __decimal_point_ = *lc->decimal_point;
3922 if (*lc->thousands_sep)
3923 __thousands_sep_ = *lc->thousands_sep;
3924 __grouping_ = lc->grouping;
3925 // locallization for truename and falsename is not available
3926 }
3927}
3928
3929// num_get helpers
3930
3931int
3932__num_get_base::__get_base(ios_base& iob)
3933{
3934 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
3935 if (__basefield == ios_base::oct)
3936 return 8;
3937 else if (__basefield == ios_base::hex)
3938 return 16;
3939 else if (__basefield == 0)
3940 return 0;
3941 return 10;
3942}
3943
3944const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
3945
3946void
3947__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
3948 ios_base::iostate& __err)
3949{
3950 if (__grouping.size() != 0)
3951 {
3952 reverse(__g, __g_end);
3953 const char* __ig = __grouping.data();
3954 const char* __eg = __ig + __grouping.size();
3955 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
3956 {
3957 if (0 < *__ig && *__ig < numeric_limits<char>::max())
3958 {
3959 if (*__ig != *__r)
3960 {
3961 __err = ios_base::failbit;
3962 return;
3963 }
3964 }
3965 if (__eg - __ig > 1)
3966 ++__ig;
3967 }
3968 if (0 < *__ig && *__ig < numeric_limits<char>::max())
3969 {
3970 if (*__ig < __g_end[-1] || __g_end[-1] == 0)
3971 __err = ios_base::failbit;
3972 }
3973 }
3974}
3975
3976void
3977__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
3978 ios_base::fmtflags __flags)
3979{
3980 if (__flags & ios_base::showpos)
3981 *__fmtp++ = '+';
3982 if (__flags & ios_base::showbase)
3983 *__fmtp++ = '#';
3984 while(*__len)
3985 *__fmtp++ = *__len++;
3986 if ((__flags & ios_base::basefield) == ios_base::oct)
3987 *__fmtp = 'o';
3988 else if ((__flags & ios_base::basefield) == ios_base::hex)
3989 {
3990 if (__flags & ios_base::uppercase)
3991 *__fmtp = 'X';
3992 else
3993 *__fmtp = 'x';
3994 }
3995 else if (__signd)
3996 *__fmtp = 'd';
3997 else
3998 *__fmtp = 'u';
3999}
4000
4001bool
4002__num_put_base::__format_float(char* __fmtp, const char* __len,
4003 ios_base::fmtflags __flags)
4004{
4005 bool specify_precision = true;
4006 if (__flags & ios_base::showpos)
4007 *__fmtp++ = '+';
4008 if (__flags & ios_base::showpoint)
4009 *__fmtp++ = '#';
4010 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
4011 bool uppercase = __flags & ios_base::uppercase;
4012 if (floatfield == (ios_base::fixed | ios_base::scientific))
4013 specify_precision = false;
4014 else
4015 {
4016 *__fmtp++ = '.';
4017 *__fmtp++ = '*';
4018 }
4019 while(*__len)
4020 *__fmtp++ = *__len++;
4021 if (floatfield == ios_base::fixed)
4022 {
4023 if (uppercase)
4024 *__fmtp = 'F';
4025 else
4026 *__fmtp = 'f';
4027 }
4028 else if (floatfield == ios_base::scientific)
4029 {
4030 if (uppercase)
4031 *__fmtp = 'E';
4032 else
4033 *__fmtp = 'e';
4034 }
4035 else if (floatfield == (ios_base::fixed | ios_base::scientific))
4036 {
4037 if (uppercase)
4038 *__fmtp = 'A';
4039 else
4040 *__fmtp = 'a';
4041 }
4042 else
4043 {
4044 if (uppercase)
4045 *__fmtp = 'G';
4046 else
4047 *__fmtp = 'g';
4048 }
4049 return specify_precision;
4050}
4051
4052char*
4053__num_put_base::__identify_padding(char* __nb, char* __ne,
4054 const ios_base& __iob)
4055{
4056 switch (__iob.flags() & ios_base::adjustfield)
4057 {
4058 case ios_base::internal:
4059 if (__nb[0] == '-' || __nb[0] == '+')
4060 return __nb+1;
4061 if (__ne - __nb >= 2 && __nb[0] == '0'
4062 && (__nb[1] == 'x' || __nb[1] == 'X'))
4063 return __nb+2;
4064 break;
4065 case ios_base::left:
4066 return __ne;
4067 case ios_base::right:
4068 default:
4069 break;
4070 }
4071 return __nb;
4072}
4073
4074// time_get
4075
4076static
4077string*
4078init_weeks()
4079{
4080 static string weeks[14];
4081 weeks[0] = "Sunday";
4082 weeks[1] = "Monday";
4083 weeks[2] = "Tuesday";
4084 weeks[3] = "Wednesday";
4085 weeks[4] = "Thursday";
4086 weeks[5] = "Friday";
4087 weeks[6] = "Saturday";
4088 weeks[7] = "Sun";
4089 weeks[8] = "Mon";
4090 weeks[9] = "Tue";
4091 weeks[10] = "Wed";
4092 weeks[11] = "Thu";
4093 weeks[12] = "Fri";
4094 weeks[13] = "Sat";
4095 return weeks;
4096}
4097
4098static
4099wstring*
4100init_wweeks()
4101{
4102 static wstring weeks[14];
4103 weeks[0] = L"Sunday";
4104 weeks[1] = L"Monday";
4105 weeks[2] = L"Tuesday";
4106 weeks[3] = L"Wednesday";
4107 weeks[4] = L"Thursday";
4108 weeks[5] = L"Friday";
4109 weeks[6] = L"Saturday";
4110 weeks[7] = L"Sun";
4111 weeks[8] = L"Mon";
4112 weeks[9] = L"Tue";
4113 weeks[10] = L"Wed";
4114 weeks[11] = L"Thu";
4115 weeks[12] = L"Fri";
4116 weeks[13] = L"Sat";
4117 return weeks;
4118}
4119
4120template <>
4121const string*
4122__time_get_c_storage<char>::__weeks() const
4123{
4124 static const string* weeks = init_weeks();
4125 return weeks;
4126}
4127
4128template <>
4129const wstring*
4130__time_get_c_storage<wchar_t>::__weeks() const
4131{
4132 static const wstring* weeks = init_wweeks();
4133 return weeks;
4134}
4135
4136static
4137string*
4138init_months()
4139{
4140 static string months[24];
4141 months[0] = "January";
4142 months[1] = "February";
4143 months[2] = "March";
4144 months[3] = "April";
4145 months[4] = "May";
4146 months[5] = "June";
4147 months[6] = "July";
4148 months[7] = "August";
4149 months[8] = "September";
4150 months[9] = "October";
4151 months[10] = "November";
4152 months[11] = "December";
4153 months[12] = "Jan";
4154 months[13] = "Feb";
4155 months[14] = "Mar";
4156 months[15] = "Apr";
4157 months[16] = "May";
4158 months[17] = "Jun";
4159 months[18] = "Jul";
4160 months[19] = "Aug";
4161 months[20] = "Sep";
4162 months[21] = "Oct";
4163 months[22] = "Nov";
4164 months[23] = "Dec";
4165 return months;
4166}
4167
4168static
4169wstring*
4170init_wmonths()
4171{
4172 static wstring months[24];
4173 months[0] = L"January";
4174 months[1] = L"February";
4175 months[2] = L"March";
4176 months[3] = L"April";
4177 months[4] = L"May";
4178 months[5] = L"June";
4179 months[6] = L"July";
4180 months[7] = L"August";
4181 months[8] = L"September";
4182 months[9] = L"October";
4183 months[10] = L"November";
4184 months[11] = L"December";
4185 months[12] = L"Jan";
4186 months[13] = L"Feb";
4187 months[14] = L"Mar";
4188 months[15] = L"Apr";
4189 months[16] = L"May";
4190 months[17] = L"Jun";
4191 months[18] = L"Jul";
4192 months[19] = L"Aug";
4193 months[20] = L"Sep";
4194 months[21] = L"Oct";
4195 months[22] = L"Nov";
4196 months[23] = L"Dec";
4197 return months;
4198}
4199
4200template <>
4201const string*
4202__time_get_c_storage<char>::__months() const
4203{
4204 static const string* months = init_months();
4205 return months;
4206}
4207
4208template <>
4209const wstring*
4210__time_get_c_storage<wchar_t>::__months() const
4211{
4212 static const wstring* months = init_wmonths();
4213 return months;
4214}
4215
4216static
4217string*
4218init_am_pm()
4219{
4220 static string am_pm[24];
4221 am_pm[0] = "AM";
4222 am_pm[1] = "PM";
4223 return am_pm;
4224}
4225
4226static
4227wstring*
4228init_wam_pm()
4229{
4230 static wstring am_pm[24];
4231 am_pm[0] = L"AM";
4232 am_pm[1] = L"PM";
4233 return am_pm;
4234}
4235
4236template <>
4237const string*
4238__time_get_c_storage<char>::__am_pm() const
4239{
4240 static const string* am_pm = init_am_pm();
4241 return am_pm;
4242}
4243
4244template <>
4245const wstring*
4246__time_get_c_storage<wchar_t>::__am_pm() const
4247{
4248 static const wstring* am_pm = init_wam_pm();
4249 return am_pm;
4250}
4251
4252template <>
4253const string&
4254__time_get_c_storage<char>::__x() const
4255{
4256 static string s("%m/%d/%y");
4257 return s;
4258}
4259
4260template <>
4261const wstring&
4262__time_get_c_storage<wchar_t>::__x() const
4263{
4264 static wstring s(L"%m/%d/%y");
4265 return s;
4266}
4267
4268template <>
4269const string&
4270__time_get_c_storage<char>::__X() const
4271{
4272 static string s("%H:%M:%S");
4273 return s;
4274}
4275
4276template <>
4277const wstring&
4278__time_get_c_storage<wchar_t>::__X() const
4279{
4280 static wstring s(L"%H:%M:%S");
4281 return s;
4282}
4283
4284template <>
4285const string&
4286__time_get_c_storage<char>::__c() const
4287{
4288 static string s("%a %b %d %H:%M:%S %Y");
4289 return s;
4290}
4291
4292template <>
4293const wstring&
4294__time_get_c_storage<wchar_t>::__c() const
4295{
4296 static wstring s(L"%a %b %d %H:%M:%S %Y");
4297 return s;
4298}
4299
4300template <>
4301const string&
4302__time_get_c_storage<char>::__r() const
4303{
4304 static string s("%I:%M:%S %p");
4305 return s;
4306}
4307
4308template <>
4309const wstring&
4310__time_get_c_storage<wchar_t>::__r() const
4311{
4312 static wstring s(L"%I:%M:%S %p");
4313 return s;
4314}
4315
4316// time_get_byname
4317
4318__time_get::__time_get(const char* nm)
4319 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4320{
Howard Hinnantd4444702010-08-11 17:04:31 +00004321#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004322 if (__loc_ == 0)
4323 throw runtime_error("time_get_byname"
4324 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004325#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004326}
4327
4328__time_get::__time_get(const string& nm)
4329 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4330{
Howard Hinnantd4444702010-08-11 17:04:31 +00004331#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004332 if (__loc_ == 0)
4333 throw runtime_error("time_get_byname"
4334 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004335#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004336}
4337
4338__time_get::~__time_get()
4339{
4340 freelocale(__loc_);
4341}
4342
4343template <>
4344string
4345__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
4346{
4347 tm t;
4348 t.tm_sec = 59;
4349 t.tm_min = 55;
4350 t.tm_hour = 23;
4351 t.tm_mday = 31;
4352 t.tm_mon = 11;
4353 t.tm_year = 161;
4354 t.tm_wday = 6;
4355 t.tm_yday = 364;
4356 t.tm_isdst = -1;
4357 char buf[100];
4358 char f[3] = {0};
4359 f[0] = '%';
4360 f[1] = fmt;
4361 size_t n = strftime_l(buf, 100, f, &t, __loc_);
4362 char* bb = buf;
4363 char* be = buf + n;
4364 string result;
4365 while (bb != be)
4366 {
4367 if (ct.is(ctype_base::space, *bb))
4368 {
4369 result.push_back(' ');
4370 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
4371 ;
4372 continue;
4373 }
4374 char* w = bb;
4375 ios_base::iostate err = ios_base::goodbit;
4376 int i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
4377 ct, err, false)
4378 - this->__weeks_;
4379 if (i < 14)
4380 {
4381 result.push_back('%');
4382 if (i < 7)
4383 result.push_back('A');
4384 else
4385 result.push_back('a');
4386 bb = w;
4387 continue;
4388 }
4389 w = bb;
4390 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
4391 ct, err, false)
4392 - this->__months_;
4393 if (i < 24)
4394 {
4395 result.push_back('%');
4396 if (i < 12)
4397 result.push_back('B');
4398 else
4399 result.push_back('b');
4400 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4401 result.back() = 'm';
4402 bb = w;
4403 continue;
4404 }
4405 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4406 {
4407 w = bb;
4408 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
4409 ct, err, false) - this->__am_pm_;
4410 if (i < 2)
4411 {
4412 result.push_back('%');
4413 result.push_back('p');
4414 bb = w;
4415 continue;
4416 }
4417 }
4418 w = bb;
4419 if (ct.is(ctype_base::digit, *bb))
4420 {
4421 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
4422 {
4423 case 6:
4424 result.push_back('%');
4425 result.push_back('w');
4426 break;
4427 case 7:
4428 result.push_back('%');
4429 result.push_back('u');
4430 break;
4431 case 11:
4432 result.push_back('%');
4433 result.push_back('I');
4434 break;
4435 case 12:
4436 result.push_back('%');
4437 result.push_back('m');
4438 break;
4439 case 23:
4440 result.push_back('%');
4441 result.push_back('H');
4442 break;
4443 case 31:
4444 result.push_back('%');
4445 result.push_back('d');
4446 break;
4447 case 55:
4448 result.push_back('%');
4449 result.push_back('M');
4450 break;
4451 case 59:
4452 result.push_back('%');
4453 result.push_back('S');
4454 break;
4455 case 61:
4456 result.push_back('%');
4457 result.push_back('y');
4458 break;
4459 case 364:
4460 result.push_back('%');
4461 result.push_back('j');
4462 break;
4463 case 2061:
4464 result.push_back('%');
4465 result.push_back('Y');
4466 break;
4467 default:
4468 for (; w != bb; ++w)
4469 result.push_back(*w);
4470 break;
4471 }
4472 continue;
4473 }
4474 if (*bb == '%')
4475 {
4476 result.push_back('%');
4477 result.push_back('%');
4478 ++bb;
4479 continue;
4480 }
4481 result.push_back(*bb);
4482 ++bb;
4483 }
4484 return result;
4485}
4486
4487template <>
4488wstring
4489__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
4490{
4491 tm t;
4492 t.tm_sec = 59;
4493 t.tm_min = 55;
4494 t.tm_hour = 23;
4495 t.tm_mday = 31;
4496 t.tm_mon = 11;
4497 t.tm_year = 161;
4498 t.tm_wday = 6;
4499 t.tm_yday = 364;
4500 t.tm_isdst = -1;
4501 char buf[100];
4502 char f[3] = {0};
4503 f[0] = '%';
4504 f[1] = fmt;
4505 size_t be = strftime_l(buf, 100, f, &t, __loc_);
4506 wchar_t wbuf[100];
4507 wchar_t* wbb = wbuf;
4508 mbstate_t mb = {0};
4509 const char* bb = buf;
4510 size_t i = mbsrtowcs_l(wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4511 if (i == -1)
4512 __throw_runtime_error("locale not supported");
4513 wchar_t* wbe = wbb + i;
4514 wstring result;
4515 while (wbb != wbe)
4516 {
4517 if (ct.is(ctype_base::space, *wbb))
4518 {
4519 result.push_back(L' ');
4520 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
4521 ;
4522 continue;
4523 }
4524 wchar_t* w = wbb;
4525 ios_base::iostate err = ios_base::goodbit;
4526 int i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
4527 ct, err, false)
4528 - this->__weeks_;
4529 if (i < 14)
4530 {
4531 result.push_back(L'%');
4532 if (i < 7)
4533 result.push_back(L'A');
4534 else
4535 result.push_back(L'a');
4536 wbb = w;
4537 continue;
4538 }
4539 w = wbb;
4540 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
4541 ct, err, false)
4542 - this->__months_;
4543 if (i < 24)
4544 {
4545 result.push_back(L'%');
4546 if (i < 12)
4547 result.push_back(L'B');
4548 else
4549 result.push_back(L'b');
4550 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
4551 result.back() = L'm';
4552 wbb = w;
4553 continue;
4554 }
4555 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
4556 {
4557 w = wbb;
4558 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
4559 ct, err, false) - this->__am_pm_;
4560 if (i < 2)
4561 {
4562 result.push_back(L'%');
4563 result.push_back(L'p');
4564 wbb = w;
4565 continue;
4566 }
4567 }
4568 w = wbb;
4569 if (ct.is(ctype_base::digit, *wbb))
4570 {
4571 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
4572 {
4573 case 6:
4574 result.push_back(L'%');
4575 result.push_back(L'w');
4576 break;
4577 case 7:
4578 result.push_back(L'%');
4579 result.push_back(L'u');
4580 break;
4581 case 11:
4582 result.push_back(L'%');
4583 result.push_back(L'I');
4584 break;
4585 case 12:
4586 result.push_back(L'%');
4587 result.push_back(L'm');
4588 break;
4589 case 23:
4590 result.push_back(L'%');
4591 result.push_back(L'H');
4592 break;
4593 case 31:
4594 result.push_back(L'%');
4595 result.push_back(L'd');
4596 break;
4597 case 55:
4598 result.push_back(L'%');
4599 result.push_back(L'M');
4600 break;
4601 case 59:
4602 result.push_back(L'%');
4603 result.push_back(L'S');
4604 break;
4605 case 61:
4606 result.push_back(L'%');
4607 result.push_back(L'y');
4608 break;
4609 case 364:
4610 result.push_back(L'%');
4611 result.push_back(L'j');
4612 break;
4613 case 2061:
4614 result.push_back(L'%');
4615 result.push_back(L'Y');
4616 break;
4617 default:
4618 for (; w != wbb; ++w)
4619 result.push_back(*w);
4620 break;
4621 }
4622 continue;
4623 }
4624 if (ct.narrow(*wbb, 0) == '%')
4625 {
4626 result.push_back(L'%');
4627 result.push_back(L'%');
4628 ++wbb;
4629 continue;
4630 }
4631 result.push_back(*wbb);
4632 ++wbb;
4633 }
4634 return result;
4635}
4636
4637template <>
4638void
4639__time_get_storage<char>::init(const ctype<char>& ct)
4640{
4641 tm t;
4642 char buf[100];
4643 // __weeks_
4644 for (int i = 0; i < 7; ++i)
4645 {
4646 t.tm_wday = i;
4647 strftime_l(buf, 100, "%A", &t, __loc_);
4648 __weeks_[i] = buf;
4649 strftime_l(buf, 100, "%a", &t, __loc_);
4650 __weeks_[i+7] = buf;
4651 }
4652 // __months_
4653 for (int i = 0; i < 12; ++i)
4654 {
4655 t.tm_mon = i;
4656 strftime_l(buf, 100, "%B", &t, __loc_);
4657 __months_[i] = buf;
4658 strftime_l(buf, 100, "%b", &t, __loc_);
4659 __months_[i+12] = buf;
4660 }
4661 // __am_pm_
4662 t.tm_hour = 1;
4663 strftime_l(buf, 100, "%p", &t, __loc_);
4664 __am_pm_[0] = buf;
4665 t.tm_hour = 13;
4666 strftime_l(buf, 100, "%p", &t, __loc_);
4667 __am_pm_[1] = buf;
4668 __c_ = __analyze('c', ct);
4669 __r_ = __analyze('r', ct);
4670 __x_ = __analyze('x', ct);
4671 __X_ = __analyze('X', ct);
4672}
4673
4674template <>
4675void
4676__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
4677{
4678 tm t = {0};
4679 char buf[100];
4680 size_t be;
4681 wchar_t wbuf[100];
4682 wchar_t* wbe;
4683 mbstate_t mb = {0};
4684 // __weeks_
4685 for (int i = 0; i < 7; ++i)
4686 {
4687 t.tm_wday = i;
4688 be = strftime_l(buf, 100, "%A", &t, __loc_);
4689 mb = mbstate_t();
4690 const char* bb = buf;
4691 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4692 if (j == -1)
4693 __throw_runtime_error("locale not supported");
4694 wbe = wbuf + j;
4695 __weeks_[i].assign(wbuf, wbe);
4696 be = strftime_l(buf, 100, "%a", &t, __loc_);
4697 mb = mbstate_t();
4698 bb = buf;
4699 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4700 if (j == -1)
4701 __throw_runtime_error("locale not supported");
4702 wbe = wbuf + j;
4703 __weeks_[i+7].assign(wbuf, wbe);
4704 }
4705 // __months_
4706 for (int i = 0; i < 12; ++i)
4707 {
4708 t.tm_mon = i;
4709 be = strftime_l(buf, 100, "%B", &t, __loc_);
4710 mb = mbstate_t();
4711 const char* bb = buf;
4712 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4713 if (j == -1)
4714 __throw_runtime_error("locale not supported");
4715 wbe = wbuf + j;
4716 __months_[i].assign(wbuf, wbe);
4717 be = strftime_l(buf, 100, "%b", &t, __loc_);
4718 mb = mbstate_t();
4719 bb = buf;
4720 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4721 if (j == -1)
4722 __throw_runtime_error("locale not supported");
4723 wbe = wbuf + j;
4724 __months_[i+12].assign(wbuf, wbe);
4725 }
4726 // __am_pm_
4727 t.tm_hour = 1;
4728 be = strftime_l(buf, 100, "%p", &t, __loc_);
4729 mb = mbstate_t();
4730 const char* bb = buf;
4731 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4732 if (j == -1)
4733 __throw_runtime_error("locale not supported");
4734 wbe = wbuf + j;
4735 __am_pm_[0].assign(wbuf, wbe);
4736 t.tm_hour = 13;
4737 be = strftime_l(buf, 100, "%p", &t, __loc_);
4738 mb = mbstate_t();
4739 bb = buf;
4740 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
4741 if (j == -1)
4742 __throw_runtime_error("locale not supported");
4743 wbe = wbuf + j;
4744 __am_pm_[1].assign(wbuf, wbe);
4745 __c_ = __analyze('c', ct);
4746 __r_ = __analyze('r', ct);
4747 __x_ = __analyze('x', ct);
4748 __X_ = __analyze('X', ct);
4749}
4750
4751template <class CharT>
4752struct _LIBCPP_HIDDEN __time_get_temp
4753 : public ctype_byname<CharT>
4754{
4755 explicit __time_get_temp(const char* nm)
4756 : ctype_byname<CharT>(nm, 1) {}
4757 explicit __time_get_temp(const string& nm)
4758 : ctype_byname<CharT>(nm, 1) {}
4759};
4760
4761template <>
4762__time_get_storage<char>::__time_get_storage(const char* __nm)
4763 : __time_get(__nm)
4764{
4765 const __time_get_temp<char> ct(__nm);
4766 init(ct);
4767}
4768
4769template <>
4770__time_get_storage<char>::__time_get_storage(const string& __nm)
4771 : __time_get(__nm)
4772{
4773 const __time_get_temp<char> ct(__nm);
4774 init(ct);
4775}
4776
4777template <>
4778__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
4779 : __time_get(__nm)
4780{
4781 const __time_get_temp<wchar_t> ct(__nm);
4782 init(ct);
4783}
4784
4785template <>
4786__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
4787 : __time_get(__nm)
4788{
4789 const __time_get_temp<wchar_t> ct(__nm);
4790 init(ct);
4791}
4792
4793template <>
4794time_base::dateorder
4795__time_get_storage<char>::__do_date_order() const
4796{
4797 unsigned i;
4798 for (i = 0; i < __x_.size(); ++i)
4799 if (__x_[i] == '%')
4800 break;
4801 ++i;
4802 switch (__x_[i])
4803 {
4804 case 'y':
4805 case 'Y':
4806 for (++i; i < __x_.size(); ++i)
4807 if (__x_[i] == '%')
4808 break;
4809 if (i == __x_.size())
4810 break;
4811 ++i;
4812 switch (__x_[i])
4813 {
4814 case 'm':
4815 for (++i; i < __x_.size(); ++i)
4816 if (__x_[i] == '%')
4817 break;
4818 if (i == __x_.size())
4819 break;
4820 ++i;
4821 if (__x_[i] == 'd')
4822 return time_base::ymd;
4823 break;
4824 case 'd':
4825 for (++i; i < __x_.size(); ++i)
4826 if (__x_[i] == '%')
4827 break;
4828 if (i == __x_.size())
4829 break;
4830 ++i;
4831 if (__x_[i] == 'm')
4832 return time_base::ydm;
4833 break;
4834 }
4835 break;
4836 case 'm':
4837 for (++i; i < __x_.size(); ++i)
4838 if (__x_[i] == '%')
4839 break;
4840 if (i == __x_.size())
4841 break;
4842 ++i;
4843 if (__x_[i] == 'd')
4844 {
4845 for (++i; i < __x_.size(); ++i)
4846 if (__x_[i] == '%')
4847 break;
4848 if (i == __x_.size())
4849 break;
4850 ++i;
4851 if (__x_[i] == 'y' || __x_[i] == 'Y')
4852 return time_base::mdy;
4853 break;
4854 }
4855 break;
4856 case 'd':
4857 for (++i; i < __x_.size(); ++i)
4858 if (__x_[i] == '%')
4859 break;
4860 if (i == __x_.size())
4861 break;
4862 ++i;
4863 if (__x_[i] == 'm')
4864 {
4865 for (++i; i < __x_.size(); ++i)
4866 if (__x_[i] == '%')
4867 break;
4868 if (i == __x_.size())
4869 break;
4870 ++i;
4871 if (__x_[i] == 'y' || __x_[i] == 'Y')
4872 return time_base::dmy;
4873 break;
4874 }
4875 break;
4876 }
4877 return time_base::no_order;
4878}
4879
4880template <>
4881time_base::dateorder
4882__time_get_storage<wchar_t>::__do_date_order() const
4883{
4884 unsigned i;
4885 for (i = 0; i < __x_.size(); ++i)
4886 if (__x_[i] == L'%')
4887 break;
4888 ++i;
4889 switch (__x_[i])
4890 {
4891 case L'y':
4892 case L'Y':
4893 for (++i; i < __x_.size(); ++i)
4894 if (__x_[i] == L'%')
4895 break;
4896 if (i == __x_.size())
4897 break;
4898 ++i;
4899 switch (__x_[i])
4900 {
4901 case L'm':
4902 for (++i; i < __x_.size(); ++i)
4903 if (__x_[i] == L'%')
4904 break;
4905 if (i == __x_.size())
4906 break;
4907 ++i;
4908 if (__x_[i] == L'd')
4909 return time_base::ymd;
4910 break;
4911 case L'd':
4912 for (++i; i < __x_.size(); ++i)
4913 if (__x_[i] == L'%')
4914 break;
4915 if (i == __x_.size())
4916 break;
4917 ++i;
4918 if (__x_[i] == L'm')
4919 return time_base::ydm;
4920 break;
4921 }
4922 break;
4923 case L'm':
4924 for (++i; i < __x_.size(); ++i)
4925 if (__x_[i] == L'%')
4926 break;
4927 if (i == __x_.size())
4928 break;
4929 ++i;
4930 if (__x_[i] == L'd')
4931 {
4932 for (++i; i < __x_.size(); ++i)
4933 if (__x_[i] == L'%')
4934 break;
4935 if (i == __x_.size())
4936 break;
4937 ++i;
4938 if (__x_[i] == L'y' || __x_[i] == L'Y')
4939 return time_base::mdy;
4940 break;
4941 }
4942 break;
4943 case L'd':
4944 for (++i; i < __x_.size(); ++i)
4945 if (__x_[i] == L'%')
4946 break;
4947 if (i == __x_.size())
4948 break;
4949 ++i;
4950 if (__x_[i] == L'm')
4951 {
4952 for (++i; i < __x_.size(); ++i)
4953 if (__x_[i] == L'%')
4954 break;
4955 if (i == __x_.size())
4956 break;
4957 ++i;
4958 if (__x_[i] == L'y' || __x_[i] == L'Y')
4959 return time_base::dmy;
4960 break;
4961 }
4962 break;
4963 }
4964 return time_base::no_order;
4965}
4966
4967// time_put
4968
4969__time_put::__time_put(const char* nm)
4970 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
4971{
Howard Hinnantd4444702010-08-11 17:04:31 +00004972#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004973 if (__loc_ == 0)
4974 throw runtime_error("time_put_byname"
4975 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004976#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004977}
4978
4979__time_put::__time_put(const string& nm)
4980 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
4981{
Howard Hinnantd4444702010-08-11 17:04:31 +00004982#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004983 if (__loc_ == 0)
4984 throw runtime_error("time_put_byname"
4985 " failed to construct for " + nm);
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00004986#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004987}
4988
4989__time_put::~__time_put()
4990{
4991 if (__loc_)
4992 freelocale(__loc_);
4993}
4994
4995void
4996__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
4997 char __fmt, char __mod) const
4998{
4999 char fmt[] = {'%', __fmt, __mod, 0};
5000 if (__mod != 0)
5001 swap(fmt[1], fmt[2]);
5002 size_t n = strftime_l(__nb, __ne-__nb, fmt, __tm, __loc_);
5003 __ne = __nb + n;
5004}
5005
5006void
5007__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
5008 char __fmt, char __mod) const
5009{
5010 char __nar[100];
5011 char* __ne = __nar + 100;
5012 __do_put(__nar, __ne, __tm, __fmt, __mod);
5013 mbstate_t mb = {0};
5014 const char* __nb = __nar;
5015 size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
5016 if (j == -1)
5017 __throw_runtime_error("locale not supported");
5018 __we = __wb + j;
5019}
5020
5021// moneypunct_byname
5022
5023static
5024void
5025__init_pat(money_base::pattern& pat, char cs_precedes, char sep_by_space, char sign_posn)
5026{
5027 const char sign = static_cast<char>(money_base::sign);
5028 const char space = static_cast<char>(money_base::space);
5029 const char none = static_cast<char>(money_base::none);
5030 const char symbol = static_cast<char>(money_base::symbol);
5031 const char value = static_cast<char>(money_base::value);
5032 switch (cs_precedes)
5033 {
5034 case 0:
5035 switch (sign_posn)
5036 {
5037 case 0:
5038 pat.field[0] = sign;
5039 pat.field[1] = value;
5040 pat.field[3] = symbol;
5041 switch (sep_by_space)
5042 {
5043 case 0:
5044 pat.field[2] = none;
5045 return;
5046 case 1:
5047 case 2:
5048 pat.field[2] = space;
5049 return;
5050 default:
5051 break;
5052 }
5053 break;
5054 case 1:
5055 pat.field[0] = sign;
5056 pat.field[3] = symbol;
5057 switch (sep_by_space)
5058 {
5059 case 0:
5060 pat.field[1] = value;
5061 pat.field[2] = none;
5062 return;
5063 case 1:
5064 pat.field[1] = value;
5065 pat.field[2] = space;
5066 return;
5067 case 2:
5068 pat.field[1] = space;
5069 pat.field[2] = value;
5070 return;
5071 default:
5072 break;
5073 }
5074 break;
5075 case 2:
5076 pat.field[0] = value;
5077 pat.field[3] = sign;
5078 switch (sep_by_space)
5079 {
5080 case 0:
5081 pat.field[1] = none;
5082 pat.field[2] = symbol;
5083 return;
5084 case 1:
5085 pat.field[1] = space;
5086 pat.field[2] = symbol;
5087 return;
5088 case 2:
5089 pat.field[1] = symbol;
5090 pat.field[2] = space;
5091 return;
5092 default:
5093 break;
5094 }
5095 break;
5096 case 3:
5097 pat.field[0] = value;
5098 pat.field[3] = symbol;
5099 switch (sep_by_space)
5100 {
5101 case 0:
5102 pat.field[1] = none;
5103 pat.field[2] = sign;
5104 return;
5105 case 1:
5106 pat.field[1] = space;
5107 pat.field[2] = sign;
5108 return;
5109 case 2:
5110 pat.field[1] = sign;
5111 pat.field[2] = space;
5112 return;
5113 default:
5114 break;
5115 }
5116 break;
5117 case 4:
5118 pat.field[0] = value;
5119 pat.field[3] = sign;
5120 switch (sep_by_space)
5121 {
5122 case 0:
5123 pat.field[1] = none;
5124 pat.field[2] = symbol;
5125 return;
5126 case 1:
5127 pat.field[1] = space;
5128 pat.field[2] = symbol;
5129 return;
5130 case 2:
5131 pat.field[1] = symbol;
5132 pat.field[2] = space;
5133 return;
5134 default:
5135 break;
5136 }
5137 break;
5138 default:
5139 break;
5140 }
5141 break;
5142 case 1:
5143 switch (sign_posn)
5144 {
5145 case 0:
5146 pat.field[0] = sign;
5147 pat.field[1] = symbol;
5148 pat.field[3] = value;
5149 switch (sep_by_space)
5150 {
5151 case 0:
5152 pat.field[2] = none;
5153 return;
5154 case 1:
5155 case 2:
5156 pat.field[2] = space;
5157 return;
5158 default:
5159 break;
5160 }
5161 break;
5162 case 1:
5163 pat.field[0] = sign;
5164 pat.field[3] = value;
5165 switch (sep_by_space)
5166 {
5167 case 0:
5168 pat.field[1] = symbol;
5169 pat.field[2] = none;
5170 return;
5171 case 1:
5172 pat.field[1] = symbol;
5173 pat.field[2] = space;
5174 return;
5175 case 2:
5176 pat.field[1] = space;
5177 pat.field[2] = symbol;
5178 return;
5179 default:
5180 break;
5181 }
5182 break;
5183 case 2:
5184 pat.field[0] = symbol;
5185 pat.field[3] = sign;
5186 switch (sep_by_space)
5187 {
5188 case 0:
5189 pat.field[1] = none;
5190 pat.field[2] = value;
5191 return;
5192 case 1:
5193 pat.field[1] = space;
5194 pat.field[2] = value;
5195 return;
5196 case 2:
5197 pat.field[1] = value;
5198 pat.field[2] = space;
5199 return;
5200 default:
5201 break;
5202 }
5203 break;
5204 case 3:
5205 pat.field[0] = sign;
5206 pat.field[3] = value;
5207 switch (sep_by_space)
5208 {
5209 case 0:
5210 pat.field[1] = symbol;
5211 pat.field[2] = none;
5212 return;
5213 case 1:
5214 pat.field[1] = symbol;
5215 pat.field[2] = space;
5216 return;
5217 case 2:
5218 pat.field[1] = space;
5219 pat.field[2] = symbol;
5220 return;
5221 default:
5222 break;
5223 }
5224 break;
5225 case 4:
5226 pat.field[0] = symbol;
5227 pat.field[3] = value;
5228 switch (sep_by_space)
5229 {
5230 case 0:
5231 pat.field[1] = sign;
5232 pat.field[2] = none;
5233 return;
5234 case 1:
5235 pat.field[1] = sign;
5236 pat.field[2] = space;
5237 return;
5238 case 2:
5239 pat.field[1] = space;
5240 pat.field[2] = sign;
5241 return;
5242 default:
5243 break;
5244 }
5245 break;
5246 default:
5247 break;
5248 }
5249 break;
5250 default:
5251 break;
5252 }
5253 pat.field[0] = symbol;
5254 pat.field[1] = sign;
5255 pat.field[2] = none;
5256 pat.field[3] = value;
5257}
5258
5259template<>
5260void
5261moneypunct_byname<char, false>::init(const char* nm)
5262{
5263 typedef moneypunct<char, false> base;
5264 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005265#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005266 if (loc == 0)
5267 throw runtime_error("moneypunct_byname"
5268 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005269#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005270 lconv* lc = localeconv_l(loc.get());
5271 if (*lc->mon_decimal_point)
5272 __decimal_point_ = *lc->mon_decimal_point;
5273 else
5274 __decimal_point_ = base::do_decimal_point();
5275 if (*lc->mon_thousands_sep)
5276 __thousands_sep_ = *lc->mon_thousands_sep;
5277 else
5278 __thousands_sep_ = base::do_thousands_sep();
5279 __grouping_ = lc->mon_grouping;
5280 __curr_symbol_ = lc->currency_symbol;
5281 if (lc->frac_digits != CHAR_MAX)
5282 __frac_digits_ = lc->frac_digits;
5283 else
5284 __frac_digits_ = base::do_frac_digits();
5285 if (lc->p_sign_posn == 0)
5286 __positive_sign_ = "()";
5287 else
5288 __positive_sign_ = lc->positive_sign;
5289 if (lc->n_sign_posn == 0)
5290 __negative_sign_ = "()";
5291 else
5292 __negative_sign_ = lc->negative_sign;
5293 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5294 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5295}
5296
5297template<>
5298void
5299moneypunct_byname<char, true>::init(const char* nm)
5300{
5301 typedef moneypunct<char, true> base;
5302 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005303#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005304 if (loc == 0)
5305 throw runtime_error("moneypunct_byname"
5306 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005307#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005308 lconv* lc = localeconv_l(loc.get());
5309 if (*lc->mon_decimal_point)
5310 __decimal_point_ = *lc->mon_decimal_point;
5311 else
5312 __decimal_point_ = base::do_decimal_point();
5313 if (*lc->mon_thousands_sep)
5314 __thousands_sep_ = *lc->mon_thousands_sep;
5315 else
5316 __thousands_sep_ = base::do_thousands_sep();
5317 __grouping_ = lc->mon_grouping;
5318 __curr_symbol_ = lc->int_curr_symbol;
5319 if (lc->int_frac_digits != CHAR_MAX)
5320 __frac_digits_ = lc->int_frac_digits;
5321 else
5322 __frac_digits_ = base::do_frac_digits();
5323 if (lc->int_p_sign_posn == 0)
5324 __positive_sign_ = "()";
5325 else
5326 __positive_sign_ = lc->positive_sign;
5327 if (lc->int_n_sign_posn == 0)
5328 __negative_sign_ = "()";
5329 else
5330 __negative_sign_ = lc->negative_sign;
5331 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5332 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
5333}
5334
5335template<>
5336void
5337moneypunct_byname<wchar_t, false>::init(const char* nm)
5338{
5339 typedef moneypunct<wchar_t, false> base;
5340 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005341#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005342 if (loc == 0)
5343 throw runtime_error("moneypunct_byname"
5344 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005345#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005346 lconv* lc = localeconv_l(loc.get());
5347 if (*lc->mon_decimal_point)
5348 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5349 else
5350 __decimal_point_ = base::do_decimal_point();
5351 if (*lc->mon_thousands_sep)
5352 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5353 else
5354 __thousands_sep_ = base::do_thousands_sep();
5355 __grouping_ = lc->mon_grouping;
5356 wchar_t wbuf[100];
5357 mbstate_t mb = {0};
5358 const char* bb = lc->currency_symbol;
5359 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5360 if (j == -1)
5361 __throw_runtime_error("locale not supported");
5362 wchar_t* wbe = wbuf + j;
5363 __curr_symbol_.assign(wbuf, wbe);
5364 if (lc->frac_digits != CHAR_MAX)
5365 __frac_digits_ = lc->frac_digits;
5366 else
5367 __frac_digits_ = base::do_frac_digits();
5368 if (lc->p_sign_posn == 0)
5369 __positive_sign_ = L"()";
5370 else
5371 {
5372 mb = mbstate_t();
5373 bb = lc->positive_sign;
5374 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5375 if (j == -1)
5376 __throw_runtime_error("locale not supported");
5377 wbe = wbuf + j;
5378 __positive_sign_.assign(wbuf, wbe);
5379 }
5380 if (lc->n_sign_posn == 0)
5381 __negative_sign_ = L"()";
5382 else
5383 {
5384 mb = mbstate_t();
5385 bb = lc->negative_sign;
5386 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5387 if (j == -1)
5388 __throw_runtime_error("locale not supported");
5389 wbe = wbuf + j;
5390 __negative_sign_.assign(wbuf, wbe);
5391 }
5392 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
5393 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
5394}
5395
5396template<>
5397void
5398moneypunct_byname<wchar_t, true>::init(const char* nm)
5399{
5400 typedef moneypunct<wchar_t, true> base;
5401 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
Howard Hinnantd4444702010-08-11 17:04:31 +00005402#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005403 if (loc == 0)
5404 throw runtime_error("moneypunct_byname"
5405 " failed to construct for " + string(nm));
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005406#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005407 lconv* lc = localeconv_l(loc.get());
5408 if (*lc->mon_decimal_point)
5409 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
5410 else
5411 __decimal_point_ = base::do_decimal_point();
5412 if (*lc->mon_thousands_sep)
5413 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
5414 else
5415 __thousands_sep_ = base::do_thousands_sep();
5416 __grouping_ = lc->mon_grouping;
5417 wchar_t wbuf[100];
5418 mbstate_t mb = {0};
5419 const char* bb = lc->int_curr_symbol;
5420 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5421 if (j == -1)
5422 __throw_runtime_error("locale not supported");
5423 wchar_t* wbe = wbuf + j;
5424 __curr_symbol_.assign(wbuf, wbe);
5425 if (lc->int_frac_digits != CHAR_MAX)
5426 __frac_digits_ = lc->int_frac_digits;
5427 else
5428 __frac_digits_ = base::do_frac_digits();
5429 if (lc->int_p_sign_posn == 0)
5430 __positive_sign_ = L"()";
5431 else
5432 {
5433 mb = mbstate_t();
5434 bb = lc->positive_sign;
5435 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5436 if (j == -1)
5437 __throw_runtime_error("locale not supported");
5438 wbe = wbuf + j;
5439 __positive_sign_.assign(wbuf, wbe);
5440 }
5441 if (lc->int_n_sign_posn == 0)
5442 __negative_sign_ = L"()";
5443 else
5444 {
5445 mb = mbstate_t();
5446 bb = lc->negative_sign;
5447 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
5448 if (j == -1)
5449 __throw_runtime_error("locale not supported");
5450 wbe = wbuf + j;
5451 __negative_sign_.assign(wbuf, wbe);
5452 }
5453 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
5454 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
5455}
5456
5457void __do_nothing(void*) {}
5458
5459void __throw_runtime_error(const char* msg)
5460{
Howard Hinnantd4444702010-08-11 17:04:31 +00005461#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005462 throw runtime_error(msg);
Howard Hinnantd4444702010-08-11 17:04:31 +00005463#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005464}
5465
5466template class collate<char>;
5467template class collate<wchar_t>;
5468
5469template class num_get<char>;
5470template class num_get<wchar_t>;
5471
5472template class __num_get<char>;
5473template class __num_get<wchar_t>;
5474
5475template class num_put<char>;
5476template class num_put<wchar_t>;
5477
5478template class __num_put<char>;
5479template class __num_put<wchar_t>;
5480
5481template class time_get<char>;
5482template class time_get<wchar_t>;
5483
5484template class time_get_byname<char>;
5485template class time_get_byname<wchar_t>;
5486
5487template class time_put<char>;
5488template class time_put<wchar_t>;
5489
5490template class time_put_byname<char>;
5491template class time_put_byname<wchar_t>;
5492
5493template class moneypunct<char, false>;
5494template class moneypunct<char, true>;
5495template class moneypunct<wchar_t, false>;
5496template class moneypunct<wchar_t, true>;
5497
5498template class moneypunct_byname<char, false>;
5499template class moneypunct_byname<char, true>;
5500template class moneypunct_byname<wchar_t, false>;
5501template class moneypunct_byname<wchar_t, true>;
5502
5503template class money_get<char>;
5504template class money_get<wchar_t>;
5505
5506template class __money_get<char>;
5507template class __money_get<wchar_t>;
5508
5509template class money_put<char>;
5510template class money_put<wchar_t>;
5511
5512template class __money_put<char>;
5513template class __money_put<wchar_t>;
5514
5515template class messages<char>;
5516template class messages<wchar_t>;
5517
5518template class messages_byname<char>;
5519template class messages_byname<wchar_t>;
5520
5521template class codecvt_byname<char, char, mbstate_t>;
5522template class codecvt_byname<wchar_t, char, mbstate_t>;
5523template class codecvt_byname<char16_t, char, mbstate_t>;
5524template class codecvt_byname<char32_t, char, mbstate_t>;
5525
5526template class __vector_base_common<true>;
5527
5528_LIBCPP_END_NAMESPACE_STD
Howard Hinnant16e6e1d2010-08-22 00:03:27 +00005529#endif // __APPLE__