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