blob: e219d982a20275b051208ffdb90af933d5d80bdb [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------- locale.cpp ---------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
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"
12#include "vector"
13#include "algorithm"
14#include "algorithm"
15#include "typeinfo"
16#include "clocale"
17#include "cstring"
18#include "cwctype"
19#include "__sso_allocator"
20#include <libkern/OSAtomic.h>
21#include <langinfo.h>
22#include <stdlib.h>
23
24_LIBCPP_BEGIN_NAMESPACE_STD
25
26namespace {
27
28struct release
29{
30 void operator()(locale::facet* p) {p->__release_shared();}
31};
32
33template <class T, class A0>
34inline
35T&
36make(A0 a0)
37{
38 static typename aligned_storage<sizeof(T)>::type buf;
39 ::new (&buf) T(a0);
40 return *(T*)&buf;
41}
42
43template <class T, class A0, class A1>
44inline
45T&
46make(A0 a0, A1 a1)
47{
48 static typename aligned_storage<sizeof(T)>::type buf;
49 ::new (&buf) T(a0, a1);
50 return *(T*)&buf;
51}
52
53template <class T, class A0, class A1, class A2>
54inline
55T&
56make(A0 a0, A1 a1, A2 a2)
57{
58 static typename aligned_storage<sizeof(T)>::type buf;
59 ::new (&buf) T(a0, a1, a2);
60 return *(T*)&buf;
61}
62
63}
64
65class _LIBCPP_HIDDEN locale::__imp
66 : public facet
67{
68 enum {N = 28};
69 string name_;
70 vector<facet*, __sso_allocator<facet*, N> > facets_;
71public:
72 explicit __imp(size_t refs = 0);
73 explicit __imp(const string& name, size_t refs = 0);
74 __imp(const __imp&);
75 __imp(const __imp&, const string&, locale::category c);
76 __imp(const __imp& other, const __imp& one, locale::category c);
77 __imp(const __imp&, facet* f, long id);
78 ~__imp();
79
80 const string& name() const {return name_;}
81 bool has_facet(long id) const {return id < facets_.size() && facets_[id];}
82 const locale::facet* use_facet(long id) const;
83
84 static const locale& make_classic();
85 static locale& make_global();
86private:
87 void install(facet* f, long id);
88 template <class F> void install(F* f) {install(f, f->id.__get());}
89 template <class F> void install_from(const __imp& other);
90};
91
92locale::__imp::__imp(size_t refs)
93 : facet(refs),
94 name_("C"),
95 facets_(N)
96{
97 facets_.clear();
98 install(&make<_STD::collate<char> >(1));
99 install(&make<_STD::collate<wchar_t> >(1));
100 install(&make<_STD::ctype<char> >((ctype_base::mask*)0, false, 1));
101 install(&make<_STD::ctype<wchar_t> >(1));
102 install(&make<codecvt<char, char, mbstate_t> >(1));
103 install(&make<codecvt<wchar_t, char, mbstate_t> >(1));
104 install(&make<codecvt<char16_t, char, mbstate_t> >(1));
105 install(&make<codecvt<char32_t, char, mbstate_t> >(1));
106 install(&make<numpunct<char> >(1));
107 install(&make<numpunct<wchar_t> >(1));
108 install(&make<num_get<char> >(1));
109 install(&make<num_get<wchar_t> >(1));
110 install(&make<num_put<char> >(1));
111 install(&make<num_put<wchar_t> >(1));
112 install(&make<moneypunct<char, false> >(1));
113 install(&make<moneypunct<char, true> >(1));
114 install(&make<moneypunct<wchar_t, false> >(1));
115 install(&make<moneypunct<wchar_t, true> >(1));
116 install(&make<money_get<char> >(1));
117 install(&make<money_get<wchar_t> >(1));
118 install(&make<money_put<char> >(1));
119 install(&make<money_put<wchar_t> >(1));
120 install(&make<time_get<char> >(1));
121 install(&make<time_get<wchar_t> >(1));
122 install(&make<time_put<char> >(1));
123 install(&make<time_put<wchar_t> >(1));
124 install(&make<_STD::messages<char> >(1));
125 install(&make<_STD::messages<wchar_t> >(1));
126}
127
128locale::__imp::__imp(const string& name, size_t refs)
129 : facet(refs),
130 name_(name),
131 facets_(N)
132{
133 try
134 {
135 facets_ = locale::classic().__locale_->facets_;
136 for (unsigned i = 0; i < facets_.size(); ++i)
137 if (facets_[i])
138 facets_[i]->__add_shared();
139 install(new collate_byname<char>(name_));
140 install(new collate_byname<wchar_t>(name_));
141 install(new ctype_byname<char>(name_));
142 install(new ctype_byname<wchar_t>(name_));
143 install(new codecvt_byname<char, char, mbstate_t>(name_));
144 install(new codecvt_byname<wchar_t, char, mbstate_t>(name_));
145 install(new codecvt_byname<char16_t, char, mbstate_t>(name_));
146 install(new codecvt_byname<char32_t, char, mbstate_t>(name_));
147 install(new numpunct_byname<char>(name_));
148 install(new numpunct_byname<wchar_t>(name_));
149 install(new moneypunct_byname<char, false>(name_));
150 install(new moneypunct_byname<char, true>(name_));
151 install(new moneypunct_byname<wchar_t, false>(name_));
152 install(new moneypunct_byname<wchar_t, true>(name_));
153 install(new time_get_byname<char>(name_));
154 install(new time_get_byname<wchar_t>(name_));
155 install(new time_put_byname<char>(name_));
156 install(new time_put_byname<wchar_t>(name_));
157 install(new messages_byname<char>(name_));
158 install(new messages_byname<wchar_t>(name_));
159 }
160 catch (...)
161 {
162 for (unsigned i = 0; i < facets_.size(); ++i)
163 if (facets_[i])
164 facets_[i]->__release_shared();
165 throw;
166 }
167}
168
169locale::__imp::__imp(const __imp& other)
170 : name_(other.name_),
171 facets_(max<size_t>(N, other.facets_.size()))
172{
173 facets_ = other.facets_;
174 for (unsigned i = 0; i < facets_.size(); ++i)
175 if (facets_[i])
176 facets_[i]->__add_shared();
177}
178
179locale::__imp::__imp(const __imp& other, const string& name, locale::category c)
180 : name_("*"),
181 facets_(N)
182{
183 facets_ = other.facets_;
184 for (unsigned i = 0; i < facets_.size(); ++i)
185 if (facets_[i])
186 facets_[i]->__add_shared();
187 try
188 {
189 if (c & locale::collate)
190 {
191 install(new collate_byname<char>(name));
192 install(new collate_byname<wchar_t>(name));
193 }
194 if (c & locale::ctype)
195 {
196 install(new ctype_byname<char>(name));
197 install(new ctype_byname<wchar_t>(name));
198 install(new codecvt_byname<char, char, mbstate_t>(name));
199 install(new codecvt_byname<wchar_t, char, mbstate_t>(name));
200 install(new codecvt_byname<char16_t, char, mbstate_t>(name));
201 install(new codecvt_byname<char32_t, char, mbstate_t>(name));
202 }
203 if (c & locale::monetary)
204 {
205 install(new moneypunct_byname<char, false>(name));
206 install(new moneypunct_byname<char, true>(name));
207 install(new moneypunct_byname<wchar_t, false>(name));
208 install(new moneypunct_byname<wchar_t, true>(name));
209 }
210 if (c & locale::numeric)
211 {
212 install(new numpunct_byname<char>(name));
213 install(new numpunct_byname<wchar_t>(name));
214 }
215 if (c & locale::time)
216 {
217 install(new time_get_byname<char>(name));
218 install(new time_get_byname<wchar_t>(name));
219 install(new time_put_byname<char>(name));
220 install(new time_put_byname<wchar_t>(name));
221 }
222 if (c & locale::messages)
223 {
224 install(new messages_byname<char>(name));
225 install(new messages_byname<wchar_t>(name));
226 }
227 }
228 catch (...)
229 {
230 for (unsigned i = 0; i < facets_.size(); ++i)
231 if (facets_[i])
232 facets_[i]->__release_shared();
233 throw;
234 }
235}
236
237template<class F>
238inline
239void
240locale::__imp::install_from(const locale::__imp& one)
241{
242 long id = F::id.__get();
243 install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id);
244}
245
246locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c)
247 : name_("*"),
248 facets_(N)
249{
250 facets_ = other.facets_;
251 for (unsigned i = 0; i < facets_.size(); ++i)
252 if (facets_[i])
253 facets_[i]->__add_shared();
254 try
255 {
256 if (c & locale::collate)
257 {
258 install_from<_STD::collate<char> >(one);
259 install_from<_STD::collate<wchar_t> >(one);
260 }
261 if (c & locale::ctype)
262 {
263 install_from<_STD::ctype<char> >(one);
264 install_from<_STD::ctype<wchar_t> >(one);
265 install_from<_STD::codecvt<char, char, mbstate_t> >(one);
266 install_from<_STD::codecvt<char16_t, char, mbstate_t> >(one);
267 install_from<_STD::codecvt<char32_t, char, mbstate_t> >(one);
268 install_from<_STD::codecvt<wchar_t, char, mbstate_t> >(one);
269 }
270 if (c & locale::monetary)
271 {
272 install_from<moneypunct<char, false> >(one);
273 install_from<moneypunct<char, true> >(one);
274 install_from<moneypunct<wchar_t, false> >(one);
275 install_from<moneypunct<wchar_t, true> >(one);
276 install_from<money_get<char> >(one);
277 install_from<money_get<wchar_t> >(one);
278 install_from<money_put<char> >(one);
279 install_from<money_put<wchar_t> >(one);
280 }
281 if (c & locale::numeric)
282 {
283 install_from<numpunct<char> >(one);
284 install_from<numpunct<wchar_t> >(one);
285 install_from<num_get<char> >(one);
286 install_from<num_get<wchar_t> >(one);
287 install_from<num_put<char> >(one);
288 install_from<num_put<wchar_t> >(one);
289 }
290 if (c & locale::time)
291 {
292 install_from<time_get<char> >(one);
293 install_from<time_get<wchar_t> >(one);
294 install_from<time_put<char> >(one);
295 install_from<time_put<wchar_t> >(one);
296 }
297 if (c & locale::messages)
298 {
299 install_from<_STD::messages<char> >(one);
300 install_from<_STD::messages<wchar_t> >(one);
301 }
302 }
303 catch (...)
304 {
305 for (unsigned i = 0; i < facets_.size(); ++i)
306 if (facets_[i])
307 facets_[i]->__release_shared();
308 throw;
309 }
310}
311
312locale::__imp::__imp(const __imp& other, facet* f, long id)
313 : name_("*"),
314 facets_(max<size_t>(N, other.facets_.size()+1))
315{
316 f->__add_shared();
317 unique_ptr<facet, release> hold(f);
318 facets_ = other.facets_;
319 for (unsigned i = 0; i < other.facets_.size(); ++i)
320 if (facets_[i])
321 facets_[i]->__add_shared();
322 install(hold.get(), id);
323}
324
325locale::__imp::~__imp()
326{
327 for (unsigned i = 0; i < facets_.size(); ++i)
328 if (facets_[i])
329 facets_[i]->__release_shared();
330}
331
332void
333locale::__imp::install(facet* f, long id)
334{
335 f->__add_shared();
336 unique_ptr<facet, release> hold(f);
337 if (id >= facets_.size())
338 facets_.resize(id+1);
339 if (facets_[id])
340 facets_[id]->__release_shared();
341 facets_[id] = hold.release();
342}
343
344const locale::facet*
345locale::__imp::use_facet(long id) const
346{
347 if (!has_facet(id))
348 throw bad_cast();
349 return facets_[id];
350}
351
352// locale
353
354const locale&
355locale::__imp::make_classic()
356{
357 // only one thread can get in here and it only gets in once
358 static aligned_storage<sizeof(locale)>::type buf;
359 locale* c = (locale*)&buf;
360 c->__locale_ = &make<__imp>(1);
361 return *c;
362}
363
364const locale&
365locale::classic()
366{
367 static const locale& c = __imp::make_classic();
368 return c;
369}
370
371locale&
372locale::__imp::make_global()
373{
374 // only one thread can get in here and it only gets in once
375 static aligned_storage<sizeof(locale)>::type buf;
376 locale* g = (locale*)&buf;
377 ::new (&buf) locale(locale::classic());
378 return *(locale*)&buf;
379}
380
381locale&
382locale::__global()
383{
384 static locale& g = __imp::make_global();
385 return g;
386}
387
388locale::locale() throw()
389 : __locale_(__global().__locale_)
390{
391 __locale_->__add_shared();
392}
393
394locale::locale(const locale& l) throw()
395 : __locale_(l.__locale_)
396{
397 __locale_->__add_shared();
398}
399
400locale::~locale() throw()
401{
402 __locale_->__release_shared();
403}
404
405const locale&
406locale::operator=(const locale& other) throw()
407{
408 other.__locale_->__add_shared();
409 __locale_->__release_shared();
410 __locale_ = other.__locale_;
411 return *this;
412}
413
414locale::locale(const char* name)
415 : __locale_(name ? new __imp(name)
416 : throw runtime_error("locale constructed with null"))
417{
418 __locale_->__add_shared();
419}
420
421locale::locale(const string& name)
422 : __locale_(new __imp(name))
423{
424 __locale_->__add_shared();
425}
426
427locale::locale(const locale& other, const char* name, category c)
428 : __locale_(name ? new __imp(*other.__locale_, name, c)
429 : throw runtime_error("locale constructed with null"))
430{
431 __locale_->__add_shared();
432}
433
434locale::locale(const locale& other, const string& name, category c)
435 : __locale_(new __imp(*other.__locale_, name, c))
436{
437 __locale_->__add_shared();
438}
439
440locale::locale(const locale& other, const locale& one, category c)
441 : __locale_(new __imp(*other.__locale_, *one.__locale_, c))
442{
443 __locale_->__add_shared();
444}
445
446string
447locale::name() const
448{
449 return __locale_->name();
450}
451
452void
453locale::__install_ctor(const locale& other, facet* f, long id)
454{
455 if (f)
456 __locale_ = new __imp(*other.__locale_, f, id);
457 else
458 __locale_ = other.__locale_;
459 __locale_->__add_shared();
460}
461
462locale
463locale::global(const locale& loc)
464{
465 locale& g = __global();
466 locale r = g;
467 g = loc;
468 if (g.name() != "*")
469 setlocale(LC_ALL, g.name().c_str());
470 return r;
471}
472
473bool
474locale::has_facet(id& x) const
475{
476 return __locale_->has_facet(x.__get());
477}
478
479const locale::facet*
480locale::use_facet(id& x) const
481{
482 return __locale_->use_facet(x.__get());
483}
484
485bool
486locale::operator==(const locale& y) const
487{
488 return (__locale_ == y.__locale_)
489 || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name());
490}
491
492// locale::facet
493
494locale::facet::~facet()
495{
496}
497
498void
499locale::facet::__on_zero_shared()
500{
501 delete this;
502}
503
504// locale::id
505
506int32_t locale::id::__next_id = 0;
507
508namespace
509{
510
511class __fake_bind
512{
513 locale::id* id_;
514 void (locale::id::* pmf_)();
515public:
516 __fake_bind(void (locale::id::* pmf)(), locale::id* id)
517 : id_(id), pmf_(pmf) {}
518
519 void operator()() const
520 {
521 (id_->*pmf_)();
522 }
523};
524
525}
526
527long
528locale::id::__get()
529{
530 call_once(__flag_, __fake_bind(&locale::id::__init, this));
531 return __id_ - 1;
532}
533
534void
535locale::id::__init()
536{
537 __id_ = OSAtomicIncrement32Barrier(&__next_id);
538}
539
540// template <> class collate_byname<char>
541
542collate_byname<char>::collate_byname(const char* n, size_t refs)
543 : collate<char>(refs),
544 __l(newlocale(LC_ALL_MASK, n, 0))
545{
546 if (__l == 0)
547 throw runtime_error("collate_byname<char>::collate_byname"
548 " failed to construct for " + string(n));
549}
550
551collate_byname<char>::collate_byname(const string& name, size_t refs)
552 : collate<char>(refs),
553 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
554{
555 if (__l == 0)
556 throw runtime_error("collate_byname<char>::collate_byname"
557 " failed to construct for " + name);
558}
559
560collate_byname<char>::~collate_byname()
561{
562 freelocale(__l);
563}
564
565int
566collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1,
567 const char_type* __lo2, const char_type* __hi2) const
568{
569 string_type lhs(__lo1, __hi1);
570 string_type rhs(__lo2, __hi2);
571 int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l);
572 if (r < 0)
573 return -1;
574 if (r > 0)
575 return 1;
576 return r;
577}
578
579collate_byname<char>::string_type
580collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const
581{
582 const string_type in(lo, hi);
583 string_type out(strxfrm_l(0, in.c_str(), 0, __l), char());
584 strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l);
585 return out;
586}
587
588// template <> class collate_byname<wchar_t>
589
590collate_byname<wchar_t>::collate_byname(const char* n, size_t refs)
591 : collate<wchar_t>(refs),
592 __l(newlocale(LC_ALL_MASK, n, 0))
593{
594 if (__l == 0)
595 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
596 " failed to construct for " + string(n));
597}
598
599collate_byname<wchar_t>::collate_byname(const string& name, size_t refs)
600 : collate<wchar_t>(refs),
601 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
602{
603 if (__l == 0)
604 throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)"
605 " failed to construct for " + name);
606}
607
608collate_byname<wchar_t>::~collate_byname()
609{
610 freelocale(__l);
611}
612
613int
614collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1,
615 const char_type* __lo2, const char_type* __hi2) const
616{
617 string_type lhs(__lo1, __hi1);
618 string_type rhs(__lo2, __hi2);
619 int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l);
620 if (r < 0)
621 return -1;
622 if (r > 0)
623 return 1;
624 return r;
625}
626
627collate_byname<wchar_t>::string_type
628collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const
629{
630 const string_type in(lo, hi);
631 string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t());
632 wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l);
633 return out;
634}
635
636// template <> class ctype<wchar_t>;
637
638locale::id ctype<wchar_t>::id;
639
640ctype<wchar_t>::~ctype()
641{
642}
643
644bool
645ctype<wchar_t>::do_is(mask m, char_type c) const
646{
647 return isascii(c) ? _DefaultRuneLocale.__runetype[c] & m : false;
648}
649
650const wchar_t*
651ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
652{
653 for (; low != high; ++low, ++vec)
654 *vec = static_cast<mask>(isascii(*low) ? _DefaultRuneLocale.__runetype[*low] : 0);
655 return low;
656}
657
658const wchar_t*
659ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
660{
661 for (; low != high; ++low)
662 if (isascii(*low) && (_DefaultRuneLocale.__runetype[*low] & m))
663 break;
664 return low;
665}
666
667const wchar_t*
668ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
669{
670 for (; low != high; ++low)
671 if (!(isascii(*low) && (_DefaultRuneLocale.__runetype[*low] & m)))
672 break;
673 return low;
674}
675
676wchar_t
677ctype<wchar_t>::do_toupper(char_type c) const
678{
679 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
680}
681
682const wchar_t*
683ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const
684{
685 for (; low != high; ++low)
686 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
687 return low;
688}
689
690wchar_t
691ctype<wchar_t>::do_tolower(char_type c) const
692{
693 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
694}
695
696const wchar_t*
697ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const
698{
699 for (; low != high; ++low)
700 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
701 return low;
702}
703
704wchar_t
705ctype<wchar_t>::do_widen(char c) const
706{
707 return c;
708}
709
710const char*
711ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
712{
713 for (; low != high; ++low, ++dest)
714 *dest = *low;
715 return low;
716}
717
718char
719ctype<wchar_t>::do_narrow(char_type c, char dfault) const
720{
721 if (isascii(c))
722 return static_cast<char>(c);
723 return dfault;
724}
725
726const wchar_t*
727ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
728{
729 for (; low != high; ++low, ++dest)
730 if (isascii(*low))
731 *dest = *low;
732 else
733 *dest = dfault;
734 return low;
735}
736
737// template <> class ctype<char>;
738
739locale::id ctype<char>::id;
740
741ctype<char>::ctype(const mask* tab, bool del, size_t refs)
742 : locale::facet(refs),
743 __tab_(tab),
744 __del_(del)
745{
746 if (__tab_ == 0)
747 __tab_ = _DefaultRuneLocale.__runetype;
748}
749
750ctype<char>::~ctype()
751{
752 if (__tab_ && __del_)
753 delete [] __tab_;
754}
755
756char
757ctype<char>::do_toupper(char_type c) const
758{
759 return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c;
760}
761
762const char*
763ctype<char>::do_toupper(char_type* low, const char_type* high) const
764{
765 for (; low != high; ++low)
766 *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low;
767 return low;
768}
769
770char
771ctype<char>::do_tolower(char_type c) const
772{
773 return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c;
774}
775
776const char*
777ctype<char>::do_tolower(char_type* low, const char_type* high) const
778{
779 for (; low != high; ++low)
780 *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low;
781 return low;
782}
783
784char
785ctype<char>::do_widen(char c) const
786{
787 return c;
788}
789
790const char*
791ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const
792{
793 for (; low != high; ++low, ++dest)
794 *dest = *low;
795 return low;
796}
797
798char
799ctype<char>::do_narrow(char_type c, char dfault) const
800{
801 if (isascii(c))
802 return static_cast<char>(c);
803 return dfault;
804}
805
806const char*
807ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
808{
809 for (; low != high; ++low, ++dest)
810 if (isascii(*low))
811 *dest = *low;
812 else
813 *dest = dfault;
814 return low;
815}
816
817const ctype<char>::mask*
818ctype<char>::classic_table() throw()
819{
820 return _DefaultRuneLocale.__runetype;
821}
822
823// template <> class ctype_byname<char>
824
825ctype_byname<char>::ctype_byname(const char* name, size_t refs)
826 : ctype<char>(0, false, refs),
827 __l(newlocale(LC_ALL_MASK, name, 0))
828{
829 if (__l == 0)
830 throw runtime_error("ctype_byname<char>::ctype_byname"
831 " failed to construct for " + string(name));
832}
833
834ctype_byname<char>::ctype_byname(const string& name, size_t refs)
835 : ctype<char>(0, false, refs),
836 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
837{
838 if (__l == 0)
839 throw runtime_error("ctype_byname<char>::ctype_byname"
840 " failed to construct for " + name);
841}
842
843ctype_byname<char>::~ctype_byname()
844{
845 freelocale(__l);
846}
847
848char
849ctype_byname<char>::do_toupper(char_type c) const
850{
851 return toupper_l(c, __l);
852}
853
854const char*
855ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const
856{
857 for (; low != high; ++low)
858 *low = toupper_l(*low, __l);
859 return low;
860}
861
862char
863ctype_byname<char>::do_tolower(char_type c) const
864{
865 return tolower_l(c, __l);
866}
867
868const char*
869ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const
870{
871 for (; low != high; ++low)
872 *low = tolower_l(*low, __l);
873 return low;
874}
875
876// template <> class ctype_byname<wchar_t>
877
878ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
879 : ctype<wchar_t>(refs),
880 __l(newlocale(LC_ALL_MASK, name, 0))
881{
882 if (__l == 0)
883 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
884 " failed to construct for " + string(name));
885}
886
887ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs)
888 : ctype<wchar_t>(refs),
889 __l(newlocale(LC_ALL_MASK, name.c_str(), 0))
890{
891 if (__l == 0)
892 throw runtime_error("ctype_byname<wchar_t>::ctype_byname"
893 " failed to construct for " + name);
894}
895
896ctype_byname<wchar_t>::~ctype_byname()
897{
898 freelocale(__l);
899}
900
901bool
902ctype_byname<wchar_t>::do_is(mask m, char_type c) const
903{
904 return static_cast<bool>(iswctype_l(c, m, __l));
905}
906
907const wchar_t*
908ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const
909{
910 for (; low != high; ++low, ++vec)
911 {
912 if (isascii(*low))
913 *vec = static_cast<mask>(_DefaultRuneLocale.__runetype[*low]);
914 else
915 {
916 *vec = 0;
917 if (iswspace_l(*low, __l))
918 *vec |= space;
919 if (iswprint_l(*low, __l))
920 *vec |= print;
921 if (iswcntrl_l(*low, __l))
922 *vec |= cntrl;
923 if (iswupper_l(*low, __l))
924 *vec |= upper;
925 if (iswlower_l(*low, __l))
926 *vec |= lower;
927 if (iswalpha_l(*low, __l))
928 *vec |= alpha;
929 if (iswdigit_l(*low, __l))
930 *vec |= digit;
931 if (iswpunct_l(*low, __l))
932 *vec |= punct;
933 if (iswxdigit_l(*low, __l))
934 *vec |= xdigit;
935 }
936 }
937 return low;
938}
939
940const wchar_t*
941ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const
942{
943 for (; low != high; ++low)
944 if (iswctype_l(*low, m, __l))
945 break;
946 return low;
947}
948
949const wchar_t*
950ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const
951{
952 for (; low != high; ++low)
953 if (!iswctype_l(*low, m, __l))
954 break;
955 return low;
956}
957
958wchar_t
959ctype_byname<wchar_t>::do_toupper(char_type c) const
960{
961 return towupper_l(c, __l);
962}
963
964const wchar_t*
965ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const
966{
967 for (; low != high; ++low)
968 *low = towupper_l(*low, __l);
969 return low;
970}
971
972wchar_t
973ctype_byname<wchar_t>::do_tolower(char_type c) const
974{
975 return towlower_l(c, __l);
976}
977
978const wchar_t*
979ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const
980{
981 for (; low != high; ++low)
982 *low = towlower_l(*low, __l);
983 return low;
984}
985
986wchar_t
987ctype_byname<wchar_t>::do_widen(char c) const
988{
989 return btowc_l(c, __l);
990}
991
992const char*
993ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const
994{
995 for (; low != high; ++low, ++dest)
996 *dest = btowc_l(*low, __l);
997 return low;
998}
999
1000char
1001ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const
1002{
1003 int r = wctob_l(c, __l);
1004 return r != WEOF ? static_cast<char>(r) : dfault;
1005}
1006
1007const wchar_t*
1008ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const
1009{
1010 for (; low != high; ++low, ++dest)
1011 {
1012 int r = wctob_l(*low, __l);
1013 *dest = r != WEOF ? static_cast<char>(r) : dfault;
1014 }
1015 return low;
1016}
1017
1018// template <> class codecvt<char, char, mbstate_t>
1019
1020locale::id codecvt<char, char, mbstate_t>::id;
1021
1022codecvt<char, char, mbstate_t>::~codecvt()
1023{
1024}
1025
1026codecvt<char, char, mbstate_t>::result
1027codecvt<char, char, mbstate_t>::do_out(state_type&,
1028 const intern_type* frm, const intern_type*, const intern_type*& frm_nxt,
1029 extern_type* to, extern_type*, extern_type*& to_nxt) const
1030{
1031 frm_nxt = frm;
1032 to_nxt = to;
1033 return noconv;
1034}
1035
1036codecvt<char, char, mbstate_t>::result
1037codecvt<char, char, mbstate_t>::do_in(state_type&,
1038 const extern_type* frm, const extern_type*, const extern_type*& frm_nxt,
1039 intern_type* to, intern_type*, intern_type*& to_nxt) const
1040{
1041 frm_nxt = frm;
1042 to_nxt = to;
1043 return noconv;
1044}
1045
1046codecvt<char, char, mbstate_t>::result
1047codecvt<char, char, mbstate_t>::do_unshift(state_type&,
1048 extern_type* to, extern_type*, extern_type*& to_nxt) const
1049{
1050 to_nxt = to;
1051 return noconv;
1052}
1053
1054int
1055codecvt<char, char, mbstate_t>::do_encoding() const throw()
1056{
1057 return 1;
1058}
1059
1060bool
1061codecvt<char, char, mbstate_t>::do_always_noconv() const throw()
1062{
1063 return true;
1064}
1065
1066int
1067codecvt<char, char, mbstate_t>::do_length(state_type&,
1068 const extern_type* frm, const extern_type* end, size_t mx) const
1069{
1070 return static_cast<int>(min<size_t>(mx, end-frm));
1071}
1072
1073int
1074codecvt<char, char, mbstate_t>::do_max_length() const throw()
1075{
1076 return 1;
1077}
1078
1079// template <> class codecvt<wchar_t, char, mbstate_t>
1080
1081locale::id codecvt<wchar_t, char, mbstate_t>::id;
1082
1083codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs)
1084 : locale::facet(refs),
1085 __l(0)
1086{
1087}
1088
1089codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs)
1090 : locale::facet(refs),
1091 __l(newlocale(LC_ALL_MASK, nm, 0))
1092{
1093 if (__l == 0)
1094 throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname"
1095 " failed to construct for " + string(nm));
1096}
1097
1098codecvt<wchar_t, char, mbstate_t>::~codecvt()
1099{
1100 if (__l != 0)
1101 freelocale(__l);
1102}
1103
1104codecvt<wchar_t, char, mbstate_t>::result
1105codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st,
1106 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
1107 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1108{
1109 // look for first internal null in frm
1110 const intern_type* fend = frm;
1111 for (; fend != frm_end; ++fend)
1112 if (*fend == 0)
1113 break;
1114 // loop over all null-terminated sequences in frm
1115 to_nxt = to;
1116 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1117 {
1118 // save state in case needed to reover to_nxt on error
1119 mbstate_t save_state = st;
1120 size_t n = wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1121 if (n == size_t(-1))
1122 {
1123 // need to recover to_nxt
1124 for (to_nxt = to; frm != frm_nxt; ++frm)
1125 {
1126 n = wcrtomb_l(to_nxt, *frm, &save_state, __l);
1127 if (n == size_t(-1))
1128 break;
1129 to_nxt += n;
1130 }
1131 frm_nxt = frm;
1132 return error;
1133 }
1134 if (n == 0)
1135 return partial;
1136 to_nxt += n;
1137 if (to_nxt == to_end)
1138 break;
1139 if (fend != frm_end) // set up next null terminated sequence
1140 {
1141 // Try to write the terminating null
1142 extern_type tmp[MB_LEN_MAX];
1143 n = wcrtomb_l(tmp, intern_type(), &st, __l);
1144 if (n == size_t(-1)) // on error
1145 return error;
1146 if (n > to_end-to_nxt) // is there room?
1147 return partial;
1148 for (extern_type* p = tmp; n; --n) // write it
1149 *to_nxt++ = *p++;
1150 ++frm_nxt;
1151 // look for next null in frm
1152 for (fend = frm_nxt; fend != frm_end; ++fend)
1153 if (*fend == 0)
1154 break;
1155 }
1156 }
1157 return frm_nxt == frm_end ? ok : partial;
1158}
1159
1160codecvt<wchar_t, char, mbstate_t>::result
1161codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st,
1162 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
1163 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1164{
1165 // look for first internal null in frm
1166 const extern_type* fend = frm;
1167 for (; fend != frm_end; ++fend)
1168 if (*fend == 0)
1169 break;
1170 // loop over all null-terminated sequences in frm
1171 to_nxt = to;
1172 for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt)
1173 {
1174 // save state in case needed to reover to_nxt on error
1175 mbstate_t save_state = st;
1176 size_t n = mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l);
1177 if (n == size_t(-1))
1178 {
1179 // need to recover to_nxt
1180 for (to_nxt = to; frm != frm_nxt; ++to_nxt)
1181 {
1182 n = mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l);
1183 switch (n)
1184 {
1185 case 0:
1186 ++frm;
1187 break;
1188 case -1:
1189 frm_nxt = frm;
1190 return error;
1191 case -2:
1192 frm_nxt = frm;
1193 return partial;
1194 default:
1195 frm += n;
1196 break;
1197 }
1198 }
1199 frm_nxt = frm;
1200 return frm_nxt == frm_end ? ok : partial;
1201 }
1202 if (n == 0)
1203 return error;
1204 to_nxt += n;
1205 if (to_nxt == to_end)
1206 break;
1207 if (fend != frm_end) // set up next null terminated sequence
1208 {
1209 // Try to write the terminating null
1210 n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l);
1211 if (n != 0) // on error
1212 return error;
1213 ++to_nxt;
1214 ++frm_nxt;
1215 // look for next null in frm
1216 for (fend = frm_nxt; fend != frm_end; ++fend)
1217 if (*fend == 0)
1218 break;
1219 }
1220 }
1221 return frm_nxt == frm_end ? ok : partial;
1222}
1223
1224codecvt<wchar_t, char, mbstate_t>::result
1225codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st,
1226 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1227{
1228 to_nxt = to;
1229 extern_type tmp[MB_LEN_MAX];
1230 size_t n = wcrtomb_l(tmp, intern_type(), &st, __l);
1231 if (n == size_t(-1) || n == 0) // on error
1232 return error;
1233 --n;
1234 if (n > to_end-to_nxt) // is there room?
1235 return partial;
1236 for (extern_type* p = tmp; n; --n) // write it
1237 *to_nxt++ = *p++;
1238 return ok;
1239}
1240
1241int
1242codecvt<wchar_t, char, mbstate_t>::do_encoding() const throw()
1243{
1244 if (mbtowc_l(0, 0, MB_LEN_MAX, __l) == 0)
1245 {
1246 // stateless encoding
1247 if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings
1248 return 1; // which take more than 1 char to form a wchar_t
1249 return 0;
1250 }
1251 return -1;
1252}
1253
1254bool
1255codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const throw()
1256{
1257 return false;
1258}
1259
1260int
1261codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st,
1262 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1263{
1264 int nbytes = 0;
1265 for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t)
1266 {
1267 size_t n = mbrlen_l(frm, frm_end-frm, &st, __l);
1268 switch (n)
1269 {
1270 case 0:
1271 ++nbytes;
1272 ++frm;
1273 break;
1274 case -1:
1275 case -2:
1276 return nbytes;
1277 default:
1278 nbytes += n;
1279 frm += n;
1280 break;
1281 }
1282 }
1283 return nbytes;
1284}
1285
1286int
1287codecvt<wchar_t, char, mbstate_t>::do_max_length() const throw()
1288{
1289 return __l == 0 ? 1 : MB_CUR_MAX_L(__l);
1290}
1291
1292// Valid UTF ranges
1293// UTF-32 UTF-16 UTF-8 # of code points
1294// first second first second third fourth
1295// 000000 - 00007F 0000 - 007F 00 - 7F 127
1296// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920
1297// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048
1298// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152
1299// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048
1300// 00D800 - 00DFFF invalid
1301// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192
1302// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608
1303// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432
1304// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536
1305
1306// template <> class codecvt<char16_t, char, mbstate_t>
1307
1308locale::id codecvt<char16_t, char, mbstate_t>::id;
1309
1310codecvt<char16_t, char, mbstate_t>::~codecvt()
1311{
1312}
1313
1314codecvt<char16_t, char, mbstate_t>::result
1315codecvt<char16_t, char, mbstate_t>::do_out(state_type&,
1316 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
1317 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1318{
1319 for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end; ++frm_nxt)
1320 {
1321 intern_type wc1 = *frm_nxt;
1322 if (wc1 < 0x0080)
1323 {
1324 if (to_end-to_nxt < 1)
1325 return partial;
1326 *to_nxt++ = static_cast<extern_type>(wc1);
1327 }
1328 else if (wc1 < 0x0800)
1329 {
1330 if (to_end-to_nxt < 2)
1331 return partial;
1332 *to_nxt++ = static_cast<extern_type>(0xC0 | (wc1 >> 6));
1333 *to_nxt++ = static_cast<extern_type>(0x80 | (wc1 & 0x03F));
1334 }
1335 else if (wc1 < 0xD800)
1336 {
1337 if (to_end-to_nxt < 3)
1338 return partial;
1339 *to_nxt++ = static_cast<extern_type>(0xE0 | (wc1 >> 12));
1340 *to_nxt++ = static_cast<extern_type>(0x80 | ((wc1 & 0x0FC0) >> 6));
1341 *to_nxt++ = static_cast<extern_type>(0x80 | (wc1 & 0x003F));
1342 }
1343 else if (wc1 < 0xDC00)
1344 {
1345 if (frm_end-frm_nxt < 2)
1346 return partial;
1347 intern_type wc2 = frm_nxt[1];
1348 if ((wc2 & 0xFC00) != 0xDC00)
1349 return error;
1350 if (to_end-to_nxt < 4)
1351 return partial;
1352 ++frm_nxt;
1353 unsigned char z = ((wc1 & 0x03C0) >> 6) + 1;
1354 *to_nxt++ = static_cast<extern_type>(0xF0 | (z >> 2));
1355 *to_nxt++ = static_cast<extern_type>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2));
1356 *to_nxt++ = static_cast<extern_type>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6));
1357 *to_nxt++ = static_cast<extern_type>(0x80 | (wc2 & 0x003F));
1358 }
1359 else if (wc1 < 0xE000)
1360 {
1361 return error;
1362 }
1363 else
1364 {
1365 if (to_end-to_nxt < 3)
1366 return partial;
1367 *to_nxt++ = static_cast<extern_type>(0xE0 | (wc1 >> 12));
1368 *to_nxt++ = static_cast<extern_type>(0x80 | ((wc1 & 0x0FC0) >> 6));
1369 *to_nxt++ = static_cast<extern_type>(0x80 | (wc1 & 0x003F));
1370 }
1371 }
1372 return ok;
1373}
1374
1375codecvt<char16_t, char, mbstate_t>::result
1376codecvt<char16_t, char, mbstate_t>::do_in(state_type&,
1377 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
1378 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1379{
1380 for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1381 {
1382 unsigned char c1 = static_cast<unsigned char>(*frm_nxt);
1383 if (c1 < 0x80)
1384 {
1385 *to_nxt = static_cast<intern_type>(c1);
1386 ++frm_nxt;
1387 }
1388 else if (c1 < 0xC2)
1389 {
1390 return error;
1391 }
1392 else if (c1 < 0xE0)
1393 {
1394 if (frm_end-frm_nxt < 2)
1395 return partial;
1396 unsigned char c2 = frm_nxt[1];
1397 if ((c2 & 0xC0) != 0x80)
1398 return error;
1399 *to_nxt = static_cast<intern_type>(((c1 & 0x1F) << 6)
1400 | (c2 & 0x3F));
1401 frm_nxt += 2;
1402 }
1403 else if (c1 < 0xF0)
1404 {
1405 if (frm_end-frm_nxt < 3)
1406 return partial;
1407 unsigned char c2 = frm_nxt[1];
1408 unsigned char c3 = frm_nxt[2];
1409 switch (c1)
1410 {
1411 case 0xE0:
1412 if ((c2 & 0xE0) != 0xA0)
1413 return error;
1414 break;
1415 case 0xED:
1416 if ((c2 & 0xE0) != 0x80)
1417 return error;
1418 break;
1419 default:
1420 if ((c2 & 0xC0) != 0x80)
1421 return error;
1422 break;
1423 }
1424 if ((c3 & 0xC0) != 0x80)
1425 return error;
1426 *to_nxt = static_cast<intern_type>(((c1 & 0x0F) << 12)
1427 | ((c2 & 0x3F) << 6)
1428 | (c3 & 0x3F));
1429 frm_nxt += 3;
1430 }
1431 else if (c1 < 0xF5)
1432 {
1433 if (frm_end-frm_nxt < 4)
1434 return partial;
1435 unsigned char c2 = frm_nxt[1];
1436 unsigned char c3 = frm_nxt[2];
1437 unsigned char c4 = frm_nxt[3];
1438 switch (c1)
1439 {
1440 case 0xF0:
1441 if (!(0x90 <= c2 && c2 <= 0xBF))
1442 return error;
1443 break;
1444 case 0xF4:
1445 if ((c2 & 0xF0) != 0x80)
1446 return error;
1447 break;
1448 default:
1449 if ((c2 & 0xC0) != 0x80)
1450 return error;
1451 break;
1452 }
1453 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1454 return error;
1455 if (to_end-to_nxt < 2)
1456 return partial;
1457 *to_nxt = static_cast<intern_type>(
1458 0xD800
1459 | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6)
1460 | ((c2 & 0x0F) << 2)
1461 | ((c3 & 0x30) >> 4));
1462 *++to_nxt = static_cast<intern_type>(
1463 0xDC00
1464 | ((c3 & 0x0F) << 6)
1465 | (c4 & 0x3F));
1466 frm_nxt += 4;
1467 }
1468 else
1469 {
1470 return error;
1471 }
1472 }
1473 return frm_nxt < frm_end ? partial : ok;
1474}
1475
1476codecvt<char16_t, char, mbstate_t>::result
1477codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&,
1478 extern_type* to, extern_type*, extern_type*& to_nxt) const
1479{
1480 to_nxt = to;
1481 return noconv;
1482}
1483
1484int
1485codecvt<char16_t, char, mbstate_t>::do_encoding() const throw()
1486{
1487 return 0;
1488}
1489
1490bool
1491codecvt<char16_t, char, mbstate_t>::do_always_noconv() const throw()
1492{
1493 return false;
1494}
1495
1496int
1497codecvt<char16_t, char, mbstate_t>::do_length(state_type&,
1498 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1499{
1500 const extern_type* frm_nxt = frm;
1501 for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t)
1502 {
1503 unsigned char c1 = static_cast<unsigned char>(*frm_nxt);
1504 if (c1 < 0x80)
1505 {
1506 ++frm_nxt;
1507 }
1508 else if (c1 < 0xC2)
1509 {
1510 break;
1511 }
1512 else if (c1 < 0xE0)
1513 {
1514 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80)
1515 break;
1516 frm_nxt += 2;
1517 }
1518 else if (c1 < 0xF0)
1519 {
1520 if (frm_end-frm_nxt < 3)
1521 break;
1522 unsigned char c2 = frm_nxt[1];
1523 unsigned char c3 = frm_nxt[2];
1524 switch (c1)
1525 {
1526 case 0xE0:
1527 if ((c2 & 0xE0) != 0xA0)
1528 return static_cast<int>(frm_nxt - frm);
1529 break;
1530 case 0xED:
1531 if ((c2 & 0xE0) != 0x80)
1532 return static_cast<int>(frm_nxt - frm);
1533 break;
1534 default:
1535 if ((c2 & 0xC0) != 0x80)
1536 return static_cast<int>(frm_nxt - frm);
1537 break;
1538 }
1539 if ((c3 & 0xC0) != 0x80)
1540 break;
1541 frm_nxt += 3;
1542 }
1543 else if (c1 < 0xF5)
1544 {
1545 if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2)
1546 break;
1547 unsigned char c2 = frm_nxt[1];
1548 unsigned char c3 = frm_nxt[2];
1549 unsigned char c4 = frm_nxt[3];
1550 switch (c1)
1551 {
1552 case 0xF0:
1553 if (!(0x90 <= c2 && c2 <= 0xBF))
1554 return static_cast<int>(frm_nxt - frm);
1555 break;
1556 case 0xF4:
1557 if ((c2 & 0xF0) != 0x80)
1558 return static_cast<int>(frm_nxt - frm);
1559 break;
1560 default:
1561 if ((c2 & 0xC0) != 0x80)
1562 return static_cast<int>(frm_nxt - frm);
1563 break;
1564 }
1565 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1566 break;
1567 ++nchar16_t;
1568 frm_nxt += 4;
1569 }
1570 else
1571 {
1572 break;
1573 }
1574 }
1575 return static_cast<int>(frm_nxt - frm);
1576}
1577
1578int
1579codecvt<char16_t, char, mbstate_t>::do_max_length() const throw()
1580{
1581 return 4;
1582}
1583
1584// template <> class codecvt<char32_t, char, mbstate_t>
1585
1586locale::id codecvt<char32_t, char, mbstate_t>::id;
1587
1588codecvt<char32_t, char, mbstate_t>::~codecvt()
1589{
1590}
1591
1592codecvt<char32_t, char, mbstate_t>::result
1593codecvt<char32_t, char, mbstate_t>::do_out(state_type&,
1594 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
1595 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1596{
1597 for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end; ++frm_nxt)
1598 {
1599 intern_type wc = *frm_nxt;
1600 if ((wc & 0xFFFFF800) == 0x00D800 || wc >= 0x110000)
1601 return error;
1602 if (wc < 0x000080)
1603 {
1604 if (to_end-to_nxt < 1)
1605 return partial;
1606 *to_nxt++ = static_cast<extern_type>(wc);
1607 }
1608 else if (wc < 0x000800)
1609 {
1610 if (to_end-to_nxt < 2)
1611 return partial;
1612 *to_nxt++ = static_cast<extern_type>(0xC0 | (wc >> 6));
1613 *to_nxt++ = static_cast<extern_type>(0x80 | (wc & 0x03F));
1614 }
1615 else if (wc < 0x010000)
1616 {
1617 if (to_end-to_nxt < 3)
1618 return partial;
1619 *to_nxt++ = static_cast<extern_type>(0xE0 | (wc >> 12));
1620 *to_nxt++ = static_cast<extern_type>(0x80 | ((wc & 0x0FC0) >> 6));
1621 *to_nxt++ = static_cast<extern_type>(0x80 | (wc & 0x003F));
1622 }
1623 else // if (wc < 0x110000)
1624 {
1625 if (to_end-to_nxt < 4)
1626 return partial;
1627 *to_nxt++ = static_cast<extern_type>(0xF0 | (wc >> 18));
1628 *to_nxt++ = static_cast<extern_type>(0x80 | ((wc & 0x03F000) >> 12));
1629 *to_nxt++ = static_cast<extern_type>(0x80 | ((wc & 0x000FC0) >> 6));
1630 *to_nxt++ = static_cast<extern_type>(0x80 | (wc & 0x00003F));
1631 }
1632 }
1633 return ok;
1634}
1635
1636codecvt<char32_t, char, mbstate_t>::result
1637codecvt<char32_t, char, mbstate_t>::do_in(state_type&,
1638 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
1639 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1640{
1641 for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1642 {
1643 unsigned char c1 = static_cast<unsigned char>(*frm_nxt);
1644 if (c1 < 0x80)
1645 {
1646 *to_nxt = static_cast<intern_type>(c1);
1647 ++frm_nxt;
1648 }
1649 else if (c1 < 0xC2)
1650 {
1651 return error;
1652 }
1653 else if (c1 < 0xE0)
1654 {
1655 if (frm_end-frm_nxt < 2)
1656 return partial;
1657 unsigned char c2 = frm_nxt[1];
1658 if ((c2 & 0xC0) != 0x80)
1659 return error;
1660 *to_nxt = static_cast<intern_type>(((c1 & 0x1F) << 6)
1661 | (c2 & 0x3F));
1662 frm_nxt += 2;
1663 }
1664 else if (c1 < 0xF0)
1665 {
1666 if (frm_end-frm_nxt < 3)
1667 return partial;
1668 unsigned char c2 = frm_nxt[1];
1669 unsigned char c3 = frm_nxt[2];
1670 switch (c1)
1671 {
1672 case 0xE0:
1673 if ((c2 & 0xE0) != 0xA0)
1674 return error;
1675 break;
1676 case 0xED:
1677 if ((c2 & 0xE0) != 0x80)
1678 return error;
1679 break;
1680 default:
1681 if ((c2 & 0xC0) != 0x80)
1682 return error;
1683 break;
1684 }
1685 if ((c3 & 0xC0) != 0x80)
1686 return error;
1687 *to_nxt = static_cast<intern_type>(((c1 & 0x0F) << 12)
1688 | ((c2 & 0x3F) << 6)
1689 | (c3 & 0x3F));
1690 frm_nxt += 3;
1691 }
1692 else if (c1 < 0xF5)
1693 {
1694 if (frm_end-frm_nxt < 4)
1695 return partial;
1696 unsigned char c2 = frm_nxt[1];
1697 unsigned char c3 = frm_nxt[2];
1698 unsigned char c4 = frm_nxt[3];
1699 switch (c1)
1700 {
1701 case 0xF0:
1702 if (!(0x90 <= c2 && c2 <= 0xBF))
1703 return error;
1704 break;
1705 case 0xF4:
1706 if ((c2 & 0xF0) != 0x80)
1707 return error;
1708 break;
1709 default:
1710 if ((c2 & 0xC0) != 0x80)
1711 return error;
1712 break;
1713 }
1714 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1715 return error;
1716 *to_nxt = static_cast<intern_type>(((c1 & 0x07) << 18)
1717 | ((c2 & 0x3F) << 12)
1718 | ((c3 & 0x3F) << 6)
1719 | (c4 & 0x3F));
1720 frm_nxt += 4;
1721 }
1722 else
1723 {
1724 return error;
1725 }
1726 }
1727 return frm_nxt < frm_end ? partial : ok;
1728}
1729
1730codecvt<char32_t, char, mbstate_t>::result
1731codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&,
1732 extern_type* to, extern_type*, extern_type*& to_nxt) const
1733{
1734 to_nxt = to;
1735 return noconv;
1736}
1737
1738int
1739codecvt<char32_t, char, mbstate_t>::do_encoding() const throw()
1740{
1741 return 0;
1742}
1743
1744bool
1745codecvt<char32_t, char, mbstate_t>::do_always_noconv() const throw()
1746{
1747 return false;
1748}
1749
1750int
1751codecvt<char32_t, char, mbstate_t>::do_length(state_type&,
1752 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1753{
1754 const extern_type* frm_nxt = frm;
1755 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
1756 {
1757 unsigned char c1 = static_cast<unsigned char>(*frm_nxt);
1758 if (c1 < 0x80)
1759 {
1760 ++frm_nxt;
1761 }
1762 else if (c1 < 0xC2)
1763 {
1764 break;
1765 }
1766 else if (c1 < 0xE0)
1767 {
1768 if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80))
1769 break;
1770 frm_nxt += 2;
1771 }
1772 else if (c1 < 0xF0)
1773 {
1774 if (frm_end-frm_nxt < 3)
1775 break;
1776 unsigned char c2 = frm_nxt[1];
1777 unsigned char c3 = frm_nxt[2];
1778 switch (c1)
1779 {
1780 case 0xE0:
1781 if ((c2 & 0xE0) != 0xA0)
1782 return static_cast<int>(frm_nxt - frm);
1783 break;
1784 case 0xED:
1785 if ((c2 & 0xE0) != 0x80)
1786 return static_cast<int>(frm_nxt - frm);
1787 break;
1788 default:
1789 if ((c2 & 0xC0) != 0x80)
1790 return static_cast<int>(frm_nxt - frm);
1791 break;
1792 }
1793 if ((c3 & 0xC0) != 0x80)
1794 break;
1795 frm_nxt += 3;
1796 }
1797 else if (c1 < 0xF5)
1798 {
1799 if (frm_end-frm_nxt < 4)
1800 break;
1801 unsigned char c2 = frm_nxt[1];
1802 unsigned char c3 = frm_nxt[2];
1803 unsigned char c4 = frm_nxt[3];
1804 switch (c1)
1805 {
1806 case 0xF0:
1807 if (!(0x90 <= c2 && c2 <= 0xBF))
1808 return static_cast<int>(frm_nxt - frm);
1809 break;
1810 case 0xF4:
1811 if ((c2 & 0xF0) != 0x80)
1812 return static_cast<int>(frm_nxt - frm);
1813 break;
1814 default:
1815 if ((c2 & 0xC0) != 0x80)
1816 return static_cast<int>(frm_nxt - frm);
1817 break;
1818 }
1819 if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80)
1820 break;
1821 frm_nxt += 4;
1822 }
1823 else
1824 {
1825 break;
1826 }
1827 }
1828 return static_cast<int>(frm_nxt - frm);
1829}
1830
1831int
1832codecvt<char32_t, char, mbstate_t>::do_max_length() const throw()
1833{
1834 return 4;
1835}
1836
1837// template <> class codecvt<char32_t, char16_t, mbstate_t>
1838
1839locale::id codecvt<char32_t, char16_t, mbstate_t>::id;
1840
1841codecvt<char32_t, char16_t, mbstate_t>::~codecvt()
1842{
1843}
1844
1845codecvt<char32_t, char16_t, mbstate_t>::result
1846codecvt<char32_t, char16_t, mbstate_t>::do_out(state_type&,
1847 const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt,
1848 extern_type* to, extern_type* to_end, extern_type*& to_nxt) const
1849{
1850 for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end; ++frm_nxt)
1851 {
1852 intern_type wc = *frm_nxt;
1853 if ((wc & 0xFFFFF800) == 0x00D800 || wc >= 0x110000)
1854 return error;
1855 if (wc < 0x010000)
1856 {
1857 if (to_end-to_nxt < 1)
1858 return partial;
1859 *to_nxt++ = static_cast<extern_type>(wc);
1860 }
1861 else
1862 {
1863 if (to_end-to_nxt < 2)
1864 return partial;
1865 *to_nxt++ = static_cast<extern_type>(
1866 0xD800
1867 | ((((wc & 0x1F0000) >> 16) - 1) << 6)
1868 | ((wc & 0x00FC00) >> 10));
1869 *to_nxt++ = static_cast<extern_type>(
1870 0xDC00
1871 | (wc & 0x03FF));
1872 }
1873 }
1874 return ok;
1875}
1876
1877codecvt<char32_t, char16_t, mbstate_t>::result
1878codecvt<char32_t, char16_t, mbstate_t>::do_in(state_type&,
1879 const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt,
1880 intern_type* to, intern_type* to_end, intern_type*& to_nxt) const
1881{
1882 for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt)
1883 {
1884 extern_type c1 = *frm_nxt;
1885 if ((c1 & 0xFC00) == 0xDC00)
1886 return error;
1887 if ((c1 & 0xFC00) != 0xD800)
1888 {
1889 *to_nxt = static_cast<intern_type>(c1);
1890 ++frm_nxt;
1891 }
1892 else
1893 {
1894 if (frm_end-frm_nxt < 2)
1895 return partial;
1896 extern_type c2 = frm_nxt[1];
1897 if ((c2 & 0xFC00) != 0xDC00)
1898 return error;
1899 *to_nxt = static_cast<intern_type>(
1900 ((((c1 & 0x03C0) >> 6) + 1) << 16)
1901 | ((c1 & 0x003F) << 10)
1902 | (c2 & 0x03FF));
1903 frm_nxt += 2;
1904 }
1905 }
1906 return frm_nxt < frm_end ? partial : ok;
1907}
1908
1909codecvt<char32_t, char16_t, mbstate_t>::result
1910codecvt<char32_t, char16_t, mbstate_t>::do_unshift(state_type&,
1911 extern_type* to, extern_type*, extern_type*& to_nxt) const
1912{
1913 to_nxt = to;
1914 return noconv;
1915}
1916
1917int
1918codecvt<char32_t, char16_t, mbstate_t>::do_encoding() const throw()
1919{
1920 return 0;
1921}
1922
1923bool
1924codecvt<char32_t, char16_t, mbstate_t>::do_always_noconv() const throw()
1925{
1926 return false;
1927}
1928
1929int
1930codecvt<char32_t, char16_t, mbstate_t>::do_length(state_type&,
1931 const extern_type* frm, const extern_type* frm_end, size_t mx) const
1932{
1933 const extern_type* frm_nxt = frm;
1934 for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t)
1935 {
1936 extern_type c1 = *frm_nxt;
1937 if ((c1 & 0xFC00) == 0xDC00)
1938 break;
1939 if ((c1 & 0xFC00) != 0xD800)
1940 {
1941 ++frm_nxt;
1942 }
1943 else
1944 {
1945 if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xFC00) != 0xDC00)
1946 break;
1947 frm_nxt += 2;
1948 }
1949 }
1950 return static_cast<int>(frm_nxt - frm);
1951}
1952
1953int
1954codecvt<char32_t, char16_t, mbstate_t>::do_max_length() const throw()
1955{
1956 return 2;
1957}
1958
1959// __narrow_to_utf8<16>
1960
1961__narrow_to_utf8<16>::~__narrow_to_utf8()
1962{
1963}
1964
1965// __narrow_to_utf8<32>
1966
1967__narrow_to_utf8<32>::~__narrow_to_utf8()
1968{
1969}
1970
1971// __widen_from_utf8<16>
1972
1973__widen_from_utf8<16>::~__widen_from_utf8()
1974{
1975}
1976
1977// __widen_from_utf8<32>
1978
1979__widen_from_utf8<32>::~__widen_from_utf8()
1980{
1981}
1982
1983// numpunct<char> && numpunct<wchar_t>
1984
1985locale::id numpunct< char >::id;
1986locale::id numpunct<wchar_t>::id;
1987
1988numpunct<char>::numpunct(size_t refs)
1989 : locale::facet(refs),
1990 __decimal_point_('.'),
1991 __thousands_sep_(',')
1992{
1993}
1994
1995numpunct<wchar_t>::numpunct(size_t refs)
1996 : locale::facet(refs),
1997 __decimal_point_(L'.'),
1998 __thousands_sep_(L',')
1999{
2000}
2001
2002numpunct<char>::~numpunct()
2003{
2004}
2005
2006numpunct<wchar_t>::~numpunct()
2007{
2008}
2009
2010 char numpunct< char >::do_decimal_point() const {return __decimal_point_;}
2011wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;}
2012
2013 char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;}
2014wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;}
2015
2016string numpunct< char >::do_grouping() const {return __grouping_;}
2017string numpunct<wchar_t>::do_grouping() const {return __grouping_;}
2018
2019 string numpunct< char >::do_truename() const {return "true";}
2020wstring numpunct<wchar_t>::do_truename() const {return L"true";}
2021
2022 string numpunct< char >::do_falsename() const {return "false";}
2023wstring numpunct<wchar_t>::do_falsename() const {return L"false";}
2024
2025// numpunct_byname<char>
2026
2027numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs)
2028 : numpunct<char>(refs)
2029{
2030 __init(nm);
2031}
2032
2033numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs)
2034 : numpunct<char>(refs)
2035{
2036 __init(nm.c_str());
2037}
2038
2039numpunct_byname<char>::~numpunct_byname()
2040{
2041}
2042
2043void
2044numpunct_byname<char>::__init(const char* nm)
2045{
2046 if (strcmp(nm, "C") != 0)
2047 {
2048 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
2049 if (loc == 0)
2050 throw runtime_error("numpunct_byname<char>::numpunct_byname"
2051 " failed to construct for " + string(nm));
2052 lconv* lc = localeconv_l(loc.get());
2053 if (*lc->decimal_point)
2054 __decimal_point_ = *lc->decimal_point;
2055 if (*lc->thousands_sep)
2056 __thousands_sep_ = *lc->thousands_sep;
2057 __grouping_ = lc->grouping;
2058 // locallization for truename and falsename is not available
2059 }
2060}
2061
2062// numpunct_byname<wchar_t>
2063
2064numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs)
2065 : numpunct<wchar_t>(refs)
2066{
2067 __init(nm);
2068}
2069
2070numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs)
2071 : numpunct<wchar_t>(refs)
2072{
2073 __init(nm.c_str());
2074}
2075
2076numpunct_byname<wchar_t>::~numpunct_byname()
2077{
2078}
2079
2080void
2081numpunct_byname<wchar_t>::__init(const char* nm)
2082{
2083 if (strcmp(nm, "C") != 0)
2084 {
2085 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
2086 if (loc == 0)
2087 throw runtime_error("numpunct_byname<char>::numpunct_byname"
2088 " failed to construct for " + string(nm));
2089 lconv* lc = localeconv_l(loc.get());
2090 if (*lc->decimal_point)
2091 __decimal_point_ = *lc->decimal_point;
2092 if (*lc->thousands_sep)
2093 __thousands_sep_ = *lc->thousands_sep;
2094 __grouping_ = lc->grouping;
2095 // locallization for truename and falsename is not available
2096 }
2097}
2098
2099// num_get helpers
2100
2101int
2102__num_get_base::__get_base(ios_base& iob)
2103{
2104 ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield;
2105 if (__basefield == ios_base::oct)
2106 return 8;
2107 else if (__basefield == ios_base::hex)
2108 return 16;
2109 else if (__basefield == 0)
2110 return 0;
2111 return 10;
2112}
2113
2114const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN";
2115
2116void
2117__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end,
2118 ios_base::iostate& __err)
2119{
2120 if (__grouping.size() != 0)
2121 {
2122 reverse(__g, __g_end);
2123 const char* __ig = __grouping.data();
2124 const char* __eg = __ig + __grouping.size();
2125 for (unsigned* __r = __g; __r < __g_end-1; ++__r)
2126 {
2127 if (0 < *__ig && *__ig < numeric_limits<char>::max())
2128 {
2129 if (*__ig != *__r)
2130 {
2131 __err = ios_base::failbit;
2132 return;
2133 }
2134 }
2135 if (__eg - __ig > 1)
2136 ++__ig;
2137 }
2138 if (0 < *__ig && *__ig < numeric_limits<char>::max())
2139 {
2140 if (*__ig < __g_end[-1] || __g_end[-1] == 0)
2141 __err = ios_base::failbit;
2142 }
2143 }
2144}
2145
2146void
2147__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd,
2148 ios_base::fmtflags __flags)
2149{
2150 if (__flags & ios_base::showpos)
2151 *__fmtp++ = '+';
2152 if (__flags & ios_base::showbase)
2153 *__fmtp++ = '#';
2154 while(*__len)
2155 *__fmtp++ = *__len++;
2156 if ((__flags & ios_base::basefield) == ios_base::oct)
2157 *__fmtp = 'o';
2158 else if ((__flags & ios_base::basefield) == ios_base::hex)
2159 {
2160 if (__flags & ios_base::uppercase)
2161 *__fmtp = 'X';
2162 else
2163 *__fmtp = 'x';
2164 }
2165 else if (__signd)
2166 *__fmtp = 'd';
2167 else
2168 *__fmtp = 'u';
2169}
2170
2171bool
2172__num_put_base::__format_float(char* __fmtp, const char* __len,
2173 ios_base::fmtflags __flags)
2174{
2175 bool specify_precision = true;
2176 if (__flags & ios_base::showpos)
2177 *__fmtp++ = '+';
2178 if (__flags & ios_base::showpoint)
2179 *__fmtp++ = '#';
2180 ios_base::fmtflags floatfield = __flags & ios_base::floatfield;
2181 bool uppercase = __flags & ios_base::uppercase;
2182 if (floatfield == (ios_base::fixed | ios_base::scientific))
2183 specify_precision = false;
2184 else
2185 {
2186 *__fmtp++ = '.';
2187 *__fmtp++ = '*';
2188 }
2189 while(*__len)
2190 *__fmtp++ = *__len++;
2191 if (floatfield == ios_base::fixed)
2192 {
2193 if (uppercase)
2194 *__fmtp = 'F';
2195 else
2196 *__fmtp = 'f';
2197 }
2198 else if (floatfield == ios_base::scientific)
2199 {
2200 if (uppercase)
2201 *__fmtp = 'E';
2202 else
2203 *__fmtp = 'e';
2204 }
2205 else if (floatfield == (ios_base::fixed | ios_base::scientific))
2206 {
2207 if (uppercase)
2208 *__fmtp = 'A';
2209 else
2210 *__fmtp = 'a';
2211 }
2212 else
2213 {
2214 if (uppercase)
2215 *__fmtp = 'G';
2216 else
2217 *__fmtp = 'g';
2218 }
2219 return specify_precision;
2220}
2221
2222char*
2223__num_put_base::__identify_padding(char* __nb, char* __ne,
2224 const ios_base& __iob)
2225{
2226 switch (__iob.flags() & ios_base::adjustfield)
2227 {
2228 case ios_base::internal:
2229 if (__nb[0] == '-' || __nb[0] == '+')
2230 return __nb+1;
2231 if (__ne - __nb >= 2 && __nb[0] == '0'
2232 && (__nb[1] == 'x' || __nb[1] == 'X'))
2233 return __nb+2;
2234 break;
2235 case ios_base::left:
2236 return __ne;
2237 case ios_base::right:
2238 default:
2239 break;
2240 }
2241 return __nb;
2242}
2243
2244// time_get
2245
2246static
2247string*
2248init_weeks()
2249{
2250 static string weeks[14];
2251 weeks[0] = "Sunday";
2252 weeks[1] = "Monday";
2253 weeks[2] = "Tuesday";
2254 weeks[3] = "Wednesday";
2255 weeks[4] = "Thursday";
2256 weeks[5] = "Friday";
2257 weeks[6] = "Saturday";
2258 weeks[7] = "Sun";
2259 weeks[8] = "Mon";
2260 weeks[9] = "Tue";
2261 weeks[10] = "Wed";
2262 weeks[11] = "Thu";
2263 weeks[12] = "Fri";
2264 weeks[13] = "Sat";
2265 return weeks;
2266}
2267
2268static
2269wstring*
2270init_wweeks()
2271{
2272 static wstring weeks[14];
2273 weeks[0] = L"Sunday";
2274 weeks[1] = L"Monday";
2275 weeks[2] = L"Tuesday";
2276 weeks[3] = L"Wednesday";
2277 weeks[4] = L"Thursday";
2278 weeks[5] = L"Friday";
2279 weeks[6] = L"Saturday";
2280 weeks[7] = L"Sun";
2281 weeks[8] = L"Mon";
2282 weeks[9] = L"Tue";
2283 weeks[10] = L"Wed";
2284 weeks[11] = L"Thu";
2285 weeks[12] = L"Fri";
2286 weeks[13] = L"Sat";
2287 return weeks;
2288}
2289
2290template <>
2291const string*
2292__time_get_c_storage<char>::__weeks() const
2293{
2294 static const string* weeks = init_weeks();
2295 return weeks;
2296}
2297
2298template <>
2299const wstring*
2300__time_get_c_storage<wchar_t>::__weeks() const
2301{
2302 static const wstring* weeks = init_wweeks();
2303 return weeks;
2304}
2305
2306static
2307string*
2308init_months()
2309{
2310 static string months[24];
2311 months[0] = "January";
2312 months[1] = "February";
2313 months[2] = "March";
2314 months[3] = "April";
2315 months[4] = "May";
2316 months[5] = "June";
2317 months[6] = "July";
2318 months[7] = "August";
2319 months[8] = "September";
2320 months[9] = "October";
2321 months[10] = "November";
2322 months[11] = "December";
2323 months[12] = "Jan";
2324 months[13] = "Feb";
2325 months[14] = "Mar";
2326 months[15] = "Apr";
2327 months[16] = "May";
2328 months[17] = "Jun";
2329 months[18] = "Jul";
2330 months[19] = "Aug";
2331 months[20] = "Sep";
2332 months[21] = "Oct";
2333 months[22] = "Nov";
2334 months[23] = "Dec";
2335 return months;
2336}
2337
2338static
2339wstring*
2340init_wmonths()
2341{
2342 static wstring months[24];
2343 months[0] = L"January";
2344 months[1] = L"February";
2345 months[2] = L"March";
2346 months[3] = L"April";
2347 months[4] = L"May";
2348 months[5] = L"June";
2349 months[6] = L"July";
2350 months[7] = L"August";
2351 months[8] = L"September";
2352 months[9] = L"October";
2353 months[10] = L"November";
2354 months[11] = L"December";
2355 months[12] = L"Jan";
2356 months[13] = L"Feb";
2357 months[14] = L"Mar";
2358 months[15] = L"Apr";
2359 months[16] = L"May";
2360 months[17] = L"Jun";
2361 months[18] = L"Jul";
2362 months[19] = L"Aug";
2363 months[20] = L"Sep";
2364 months[21] = L"Oct";
2365 months[22] = L"Nov";
2366 months[23] = L"Dec";
2367 return months;
2368}
2369
2370template <>
2371const string*
2372__time_get_c_storage<char>::__months() const
2373{
2374 static const string* months = init_months();
2375 return months;
2376}
2377
2378template <>
2379const wstring*
2380__time_get_c_storage<wchar_t>::__months() const
2381{
2382 static const wstring* months = init_wmonths();
2383 return months;
2384}
2385
2386static
2387string*
2388init_am_pm()
2389{
2390 static string am_pm[24];
2391 am_pm[0] = "AM";
2392 am_pm[1] = "PM";
2393 return am_pm;
2394}
2395
2396static
2397wstring*
2398init_wam_pm()
2399{
2400 static wstring am_pm[24];
2401 am_pm[0] = L"AM";
2402 am_pm[1] = L"PM";
2403 return am_pm;
2404}
2405
2406template <>
2407const string*
2408__time_get_c_storage<char>::__am_pm() const
2409{
2410 static const string* am_pm = init_am_pm();
2411 return am_pm;
2412}
2413
2414template <>
2415const wstring*
2416__time_get_c_storage<wchar_t>::__am_pm() const
2417{
2418 static const wstring* am_pm = init_wam_pm();
2419 return am_pm;
2420}
2421
2422template <>
2423const string&
2424__time_get_c_storage<char>::__x() const
2425{
2426 static string s("%m/%d/%y");
2427 return s;
2428}
2429
2430template <>
2431const wstring&
2432__time_get_c_storage<wchar_t>::__x() const
2433{
2434 static wstring s(L"%m/%d/%y");
2435 return s;
2436}
2437
2438template <>
2439const string&
2440__time_get_c_storage<char>::__X() const
2441{
2442 static string s("%H:%M:%S");
2443 return s;
2444}
2445
2446template <>
2447const wstring&
2448__time_get_c_storage<wchar_t>::__X() const
2449{
2450 static wstring s(L"%H:%M:%S");
2451 return s;
2452}
2453
2454template <>
2455const string&
2456__time_get_c_storage<char>::__c() const
2457{
2458 static string s("%a %b %d %H:%M:%S %Y");
2459 return s;
2460}
2461
2462template <>
2463const wstring&
2464__time_get_c_storage<wchar_t>::__c() const
2465{
2466 static wstring s(L"%a %b %d %H:%M:%S %Y");
2467 return s;
2468}
2469
2470template <>
2471const string&
2472__time_get_c_storage<char>::__r() const
2473{
2474 static string s("%I:%M:%S %p");
2475 return s;
2476}
2477
2478template <>
2479const wstring&
2480__time_get_c_storage<wchar_t>::__r() const
2481{
2482 static wstring s(L"%I:%M:%S %p");
2483 return s;
2484}
2485
2486// time_get_byname
2487
2488__time_get::__time_get(const char* nm)
2489 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
2490{
2491 if (__loc_ == 0)
2492 throw runtime_error("time_get_byname"
2493 " failed to construct for " + string(nm));
2494}
2495
2496__time_get::__time_get(const string& nm)
2497 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
2498{
2499 if (__loc_ == 0)
2500 throw runtime_error("time_get_byname"
2501 " failed to construct for " + nm);
2502}
2503
2504__time_get::~__time_get()
2505{
2506 freelocale(__loc_);
2507}
2508
2509template <>
2510string
2511__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct)
2512{
2513 tm t;
2514 t.tm_sec = 59;
2515 t.tm_min = 55;
2516 t.tm_hour = 23;
2517 t.tm_mday = 31;
2518 t.tm_mon = 11;
2519 t.tm_year = 161;
2520 t.tm_wday = 6;
2521 t.tm_yday = 364;
2522 t.tm_isdst = -1;
2523 char buf[100];
2524 char f[3] = {0};
2525 f[0] = '%';
2526 f[1] = fmt;
2527 size_t n = strftime_l(buf, 100, f, &t, __loc_);
2528 char* bb = buf;
2529 char* be = buf + n;
2530 string result;
2531 while (bb != be)
2532 {
2533 if (ct.is(ctype_base::space, *bb))
2534 {
2535 result.push_back(' ');
2536 for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb)
2537 ;
2538 continue;
2539 }
2540 char* w = bb;
2541 ios_base::iostate err = ios_base::goodbit;
2542 int i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14,
2543 ct, err, false)
2544 - this->__weeks_;
2545 if (i < 14)
2546 {
2547 result.push_back('%');
2548 if (i < 7)
2549 result.push_back('A');
2550 else
2551 result.push_back('a');
2552 bb = w;
2553 continue;
2554 }
2555 w = bb;
2556 i = __scan_keyword(w, be, this->__months_, this->__months_+24,
2557 ct, err, false)
2558 - this->__months_;
2559 if (i < 24)
2560 {
2561 result.push_back('%');
2562 if (i < 12)
2563 result.push_back('B');
2564 else
2565 result.push_back('b');
2566 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
2567 result.back() = 'm';
2568 bb = w;
2569 continue;
2570 }
2571 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
2572 {
2573 w = bb;
2574 i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2,
2575 ct, err, false) - this->__am_pm_;
2576 if (i < 2)
2577 {
2578 result.push_back('%');
2579 result.push_back('p');
2580 bb = w;
2581 continue;
2582 }
2583 }
2584 w = bb;
2585 if (ct.is(ctype_base::digit, *bb))
2586 {
2587 switch(__get_up_to_n_digits(bb, be, err, ct, 4))
2588 {
2589 case 6:
2590 result.push_back('%');
2591 result.push_back('w');
2592 break;
2593 case 7:
2594 result.push_back('%');
2595 result.push_back('u');
2596 break;
2597 case 11:
2598 result.push_back('%');
2599 result.push_back('I');
2600 break;
2601 case 12:
2602 result.push_back('%');
2603 result.push_back('m');
2604 break;
2605 case 23:
2606 result.push_back('%');
2607 result.push_back('H');
2608 break;
2609 case 31:
2610 result.push_back('%');
2611 result.push_back('d');
2612 break;
2613 case 55:
2614 result.push_back('%');
2615 result.push_back('M');
2616 break;
2617 case 59:
2618 result.push_back('%');
2619 result.push_back('S');
2620 break;
2621 case 61:
2622 result.push_back('%');
2623 result.push_back('y');
2624 break;
2625 case 364:
2626 result.push_back('%');
2627 result.push_back('j');
2628 break;
2629 case 2061:
2630 result.push_back('%');
2631 result.push_back('Y');
2632 break;
2633 default:
2634 for (; w != bb; ++w)
2635 result.push_back(*w);
2636 break;
2637 }
2638 continue;
2639 }
2640 if (*bb == '%')
2641 {
2642 result.push_back('%');
2643 result.push_back('%');
2644 ++bb;
2645 continue;
2646 }
2647 result.push_back(*bb);
2648 ++bb;
2649 }
2650 return result;
2651}
2652
2653template <>
2654wstring
2655__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct)
2656{
2657 tm t;
2658 t.tm_sec = 59;
2659 t.tm_min = 55;
2660 t.tm_hour = 23;
2661 t.tm_mday = 31;
2662 t.tm_mon = 11;
2663 t.tm_year = 161;
2664 t.tm_wday = 6;
2665 t.tm_yday = 364;
2666 t.tm_isdst = -1;
2667 char buf[100];
2668 char f[3] = {0};
2669 f[0] = '%';
2670 f[1] = fmt;
2671 size_t be = strftime_l(buf, 100, f, &t, __loc_);
2672 wchar_t wbuf[100];
2673 wchar_t* wbb = wbuf;
2674 mbstate_t mb = {0};
2675 const char* bb = buf;
2676 size_t i = mbsrtowcs_l(wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
2677 if (i == -1)
2678 __throw_runtime_error("locale not supported");
2679 wchar_t* wbe = wbb + i;
2680 wstring result;
2681 while (wbb != wbe)
2682 {
2683 if (ct.is(ctype_base::space, *wbb))
2684 {
2685 result.push_back(L' ');
2686 for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb)
2687 ;
2688 continue;
2689 }
2690 wchar_t* w = wbb;
2691 ios_base::iostate err = ios_base::goodbit;
2692 int i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14,
2693 ct, err, false)
2694 - this->__weeks_;
2695 if (i < 14)
2696 {
2697 result.push_back(L'%');
2698 if (i < 7)
2699 result.push_back(L'A');
2700 else
2701 result.push_back(L'a');
2702 wbb = w;
2703 continue;
2704 }
2705 w = wbb;
2706 i = __scan_keyword(w, wbe, this->__months_, this->__months_+24,
2707 ct, err, false)
2708 - this->__months_;
2709 if (i < 24)
2710 {
2711 result.push_back(L'%');
2712 if (i < 12)
2713 result.push_back(L'B');
2714 else
2715 result.push_back(L'b');
2716 if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0]))
2717 result.back() = L'm';
2718 wbb = w;
2719 continue;
2720 }
2721 if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0)
2722 {
2723 w = wbb;
2724 i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2,
2725 ct, err, false) - this->__am_pm_;
2726 if (i < 2)
2727 {
2728 result.push_back(L'%');
2729 result.push_back(L'p');
2730 wbb = w;
2731 continue;
2732 }
2733 }
2734 w = wbb;
2735 if (ct.is(ctype_base::digit, *wbb))
2736 {
2737 switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4))
2738 {
2739 case 6:
2740 result.push_back(L'%');
2741 result.push_back(L'w');
2742 break;
2743 case 7:
2744 result.push_back(L'%');
2745 result.push_back(L'u');
2746 break;
2747 case 11:
2748 result.push_back(L'%');
2749 result.push_back(L'I');
2750 break;
2751 case 12:
2752 result.push_back(L'%');
2753 result.push_back(L'm');
2754 break;
2755 case 23:
2756 result.push_back(L'%');
2757 result.push_back(L'H');
2758 break;
2759 case 31:
2760 result.push_back(L'%');
2761 result.push_back(L'd');
2762 break;
2763 case 55:
2764 result.push_back(L'%');
2765 result.push_back(L'M');
2766 break;
2767 case 59:
2768 result.push_back(L'%');
2769 result.push_back(L'S');
2770 break;
2771 case 61:
2772 result.push_back(L'%');
2773 result.push_back(L'y');
2774 break;
2775 case 364:
2776 result.push_back(L'%');
2777 result.push_back(L'j');
2778 break;
2779 case 2061:
2780 result.push_back(L'%');
2781 result.push_back(L'Y');
2782 break;
2783 default:
2784 for (; w != wbb; ++w)
2785 result.push_back(*w);
2786 break;
2787 }
2788 continue;
2789 }
2790 if (ct.narrow(*wbb, 0) == '%')
2791 {
2792 result.push_back(L'%');
2793 result.push_back(L'%');
2794 ++wbb;
2795 continue;
2796 }
2797 result.push_back(*wbb);
2798 ++wbb;
2799 }
2800 return result;
2801}
2802
2803template <>
2804void
2805__time_get_storage<char>::init(const ctype<char>& ct)
2806{
2807 tm t;
2808 char buf[100];
2809 // __weeks_
2810 for (int i = 0; i < 7; ++i)
2811 {
2812 t.tm_wday = i;
2813 strftime_l(buf, 100, "%A", &t, __loc_);
2814 __weeks_[i] = buf;
2815 strftime_l(buf, 100, "%a", &t, __loc_);
2816 __weeks_[i+7] = buf;
2817 }
2818 // __months_
2819 for (int i = 0; i < 12; ++i)
2820 {
2821 t.tm_mon = i;
2822 strftime_l(buf, 100, "%B", &t, __loc_);
2823 __months_[i] = buf;
2824 strftime_l(buf, 100, "%b", &t, __loc_);
2825 __months_[i+12] = buf;
2826 }
2827 // __am_pm_
2828 t.tm_hour = 1;
2829 strftime_l(buf, 100, "%p", &t, __loc_);
2830 __am_pm_[0] = buf;
2831 t.tm_hour = 13;
2832 strftime_l(buf, 100, "%p", &t, __loc_);
2833 __am_pm_[1] = buf;
2834 __c_ = __analyze('c', ct);
2835 __r_ = __analyze('r', ct);
2836 __x_ = __analyze('x', ct);
2837 __X_ = __analyze('X', ct);
2838}
2839
2840template <>
2841void
2842__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct)
2843{
2844 tm t = {0};
2845 char buf[100];
2846 size_t be;
2847 wchar_t wbuf[100];
2848 wchar_t* wbe;
2849 mbstate_t mb = {0};
2850 // __weeks_
2851 for (int i = 0; i < 7; ++i)
2852 {
2853 t.tm_wday = i;
2854 be = strftime_l(buf, 100, "%A", &t, __loc_);
2855 mb = mbstate_t();
2856 const char* bb = buf;
2857 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
2858 if (j == -1)
2859 __throw_runtime_error("locale not supported");
2860 wbe = wbuf + j;
2861 __weeks_[i].assign(wbuf, wbe);
2862 be = strftime_l(buf, 100, "%a", &t, __loc_);
2863 mb = mbstate_t();
2864 bb = buf;
2865 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
2866 if (j == -1)
2867 __throw_runtime_error("locale not supported");
2868 wbe = wbuf + j;
2869 __weeks_[i+7].assign(wbuf, wbe);
2870 }
2871 // __months_
2872 for (int i = 0; i < 12; ++i)
2873 {
2874 t.tm_mon = i;
2875 be = strftime_l(buf, 100, "%B", &t, __loc_);
2876 mb = mbstate_t();
2877 const char* bb = buf;
2878 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
2879 if (j == -1)
2880 __throw_runtime_error("locale not supported");
2881 wbe = wbuf + j;
2882 __months_[i].assign(wbuf, wbe);
2883 be = strftime_l(buf, 100, "%b", &t, __loc_);
2884 mb = mbstate_t();
2885 bb = buf;
2886 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
2887 if (j == -1)
2888 __throw_runtime_error("locale not supported");
2889 wbe = wbuf + j;
2890 __months_[i+12].assign(wbuf, wbe);
2891 }
2892 // __am_pm_
2893 t.tm_hour = 1;
2894 be = strftime_l(buf, 100, "%p", &t, __loc_);
2895 mb = mbstate_t();
2896 const char* bb = buf;
2897 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
2898 if (j == -1)
2899 __throw_runtime_error("locale not supported");
2900 wbe = wbuf + j;
2901 __am_pm_[0].assign(wbuf, wbe);
2902 t.tm_hour = 13;
2903 be = strftime_l(buf, 100, "%p", &t, __loc_);
2904 mb = mbstate_t();
2905 bb = buf;
2906 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_);
2907 if (j == -1)
2908 __throw_runtime_error("locale not supported");
2909 wbe = wbuf + j;
2910 __am_pm_[1].assign(wbuf, wbe);
2911 __c_ = __analyze('c', ct);
2912 __r_ = __analyze('r', ct);
2913 __x_ = __analyze('x', ct);
2914 __X_ = __analyze('X', ct);
2915}
2916
2917template <class CharT>
2918struct _LIBCPP_HIDDEN __time_get_temp
2919 : public ctype_byname<CharT>
2920{
2921 explicit __time_get_temp(const char* nm)
2922 : ctype_byname<CharT>(nm, 1) {}
2923 explicit __time_get_temp(const string& nm)
2924 : ctype_byname<CharT>(nm, 1) {}
2925};
2926
2927template <>
2928__time_get_storage<char>::__time_get_storage(const char* __nm)
2929 : __time_get(__nm)
2930{
2931 const __time_get_temp<char> ct(__nm);
2932 init(ct);
2933}
2934
2935template <>
2936__time_get_storage<char>::__time_get_storage(const string& __nm)
2937 : __time_get(__nm)
2938{
2939 const __time_get_temp<char> ct(__nm);
2940 init(ct);
2941}
2942
2943template <>
2944__time_get_storage<wchar_t>::__time_get_storage(const char* __nm)
2945 : __time_get(__nm)
2946{
2947 const __time_get_temp<wchar_t> ct(__nm);
2948 init(ct);
2949}
2950
2951template <>
2952__time_get_storage<wchar_t>::__time_get_storage(const string& __nm)
2953 : __time_get(__nm)
2954{
2955 const __time_get_temp<wchar_t> ct(__nm);
2956 init(ct);
2957}
2958
2959template <>
2960time_base::dateorder
2961__time_get_storage<char>::__do_date_order() const
2962{
2963 unsigned i;
2964 for (i = 0; i < __x_.size(); ++i)
2965 if (__x_[i] == '%')
2966 break;
2967 ++i;
2968 switch (__x_[i])
2969 {
2970 case 'y':
2971 case 'Y':
2972 for (++i; i < __x_.size(); ++i)
2973 if (__x_[i] == '%')
2974 break;
2975 if (i == __x_.size())
2976 break;
2977 ++i;
2978 switch (__x_[i])
2979 {
2980 case 'm':
2981 for (++i; i < __x_.size(); ++i)
2982 if (__x_[i] == '%')
2983 break;
2984 if (i == __x_.size())
2985 break;
2986 ++i;
2987 if (__x_[i] == 'd')
2988 return time_base::ymd;
2989 break;
2990 case 'd':
2991 for (++i; i < __x_.size(); ++i)
2992 if (__x_[i] == '%')
2993 break;
2994 if (i == __x_.size())
2995 break;
2996 ++i;
2997 if (__x_[i] == 'm')
2998 return time_base::ydm;
2999 break;
3000 }
3001 break;
3002 case 'm':
3003 for (++i; i < __x_.size(); ++i)
3004 if (__x_[i] == '%')
3005 break;
3006 if (i == __x_.size())
3007 break;
3008 ++i;
3009 if (__x_[i] == 'd')
3010 {
3011 for (++i; i < __x_.size(); ++i)
3012 if (__x_[i] == '%')
3013 break;
3014 if (i == __x_.size())
3015 break;
3016 ++i;
3017 if (__x_[i] == 'y' || __x_[i] == 'Y')
3018 return time_base::mdy;
3019 break;
3020 }
3021 break;
3022 case 'd':
3023 for (++i; i < __x_.size(); ++i)
3024 if (__x_[i] == '%')
3025 break;
3026 if (i == __x_.size())
3027 break;
3028 ++i;
3029 if (__x_[i] == 'm')
3030 {
3031 for (++i; i < __x_.size(); ++i)
3032 if (__x_[i] == '%')
3033 break;
3034 if (i == __x_.size())
3035 break;
3036 ++i;
3037 if (__x_[i] == 'y' || __x_[i] == 'Y')
3038 return time_base::dmy;
3039 break;
3040 }
3041 break;
3042 }
3043 return time_base::no_order;
3044}
3045
3046template <>
3047time_base::dateorder
3048__time_get_storage<wchar_t>::__do_date_order() const
3049{
3050 unsigned i;
3051 for (i = 0; i < __x_.size(); ++i)
3052 if (__x_[i] == L'%')
3053 break;
3054 ++i;
3055 switch (__x_[i])
3056 {
3057 case L'y':
3058 case L'Y':
3059 for (++i; i < __x_.size(); ++i)
3060 if (__x_[i] == L'%')
3061 break;
3062 if (i == __x_.size())
3063 break;
3064 ++i;
3065 switch (__x_[i])
3066 {
3067 case L'm':
3068 for (++i; i < __x_.size(); ++i)
3069 if (__x_[i] == L'%')
3070 break;
3071 if (i == __x_.size())
3072 break;
3073 ++i;
3074 if (__x_[i] == L'd')
3075 return time_base::ymd;
3076 break;
3077 case L'd':
3078 for (++i; i < __x_.size(); ++i)
3079 if (__x_[i] == L'%')
3080 break;
3081 if (i == __x_.size())
3082 break;
3083 ++i;
3084 if (__x_[i] == L'm')
3085 return time_base::ydm;
3086 break;
3087 }
3088 break;
3089 case L'm':
3090 for (++i; i < __x_.size(); ++i)
3091 if (__x_[i] == L'%')
3092 break;
3093 if (i == __x_.size())
3094 break;
3095 ++i;
3096 if (__x_[i] == L'd')
3097 {
3098 for (++i; i < __x_.size(); ++i)
3099 if (__x_[i] == L'%')
3100 break;
3101 if (i == __x_.size())
3102 break;
3103 ++i;
3104 if (__x_[i] == L'y' || __x_[i] == L'Y')
3105 return time_base::mdy;
3106 break;
3107 }
3108 break;
3109 case L'd':
3110 for (++i; i < __x_.size(); ++i)
3111 if (__x_[i] == L'%')
3112 break;
3113 if (i == __x_.size())
3114 break;
3115 ++i;
3116 if (__x_[i] == L'm')
3117 {
3118 for (++i; i < __x_.size(); ++i)
3119 if (__x_[i] == L'%')
3120 break;
3121 if (i == __x_.size())
3122 break;
3123 ++i;
3124 if (__x_[i] == L'y' || __x_[i] == L'Y')
3125 return time_base::dmy;
3126 break;
3127 }
3128 break;
3129 }
3130 return time_base::no_order;
3131}
3132
3133// time_put
3134
3135__time_put::__time_put(const char* nm)
3136 : __loc_(newlocale(LC_ALL_MASK, nm, 0))
3137{
3138 if (__loc_ == 0)
3139 throw runtime_error("time_put_byname"
3140 " failed to construct for " + string(nm));
3141}
3142
3143__time_put::__time_put(const string& nm)
3144 : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0))
3145{
3146 if (__loc_ == 0)
3147 throw runtime_error("time_put_byname"
3148 " failed to construct for " + nm);
3149}
3150
3151__time_put::~__time_put()
3152{
3153 if (__loc_)
3154 freelocale(__loc_);
3155}
3156
3157void
3158__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm,
3159 char __fmt, char __mod) const
3160{
3161 char fmt[] = {'%', __fmt, __mod, 0};
3162 if (__mod != 0)
3163 swap(fmt[1], fmt[2]);
3164 size_t n = strftime_l(__nb, __ne-__nb, fmt, __tm, __loc_);
3165 __ne = __nb + n;
3166}
3167
3168void
3169__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm,
3170 char __fmt, char __mod) const
3171{
3172 char __nar[100];
3173 char* __ne = __nar + 100;
3174 __do_put(__nar, __ne, __tm, __fmt, __mod);
3175 mbstate_t mb = {0};
3176 const char* __nb = __nar;
3177 size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_);
3178 if (j == -1)
3179 __throw_runtime_error("locale not supported");
3180 __we = __wb + j;
3181}
3182
3183// moneypunct_byname
3184
3185static
3186void
3187__init_pat(money_base::pattern& pat, char cs_precedes, char sep_by_space, char sign_posn)
3188{
3189 const char sign = static_cast<char>(money_base::sign);
3190 const char space = static_cast<char>(money_base::space);
3191 const char none = static_cast<char>(money_base::none);
3192 const char symbol = static_cast<char>(money_base::symbol);
3193 const char value = static_cast<char>(money_base::value);
3194 switch (cs_precedes)
3195 {
3196 case 0:
3197 switch (sign_posn)
3198 {
3199 case 0:
3200 pat.field[0] = sign;
3201 pat.field[1] = value;
3202 pat.field[3] = symbol;
3203 switch (sep_by_space)
3204 {
3205 case 0:
3206 pat.field[2] = none;
3207 return;
3208 case 1:
3209 case 2:
3210 pat.field[2] = space;
3211 return;
3212 default:
3213 break;
3214 }
3215 break;
3216 case 1:
3217 pat.field[0] = sign;
3218 pat.field[3] = symbol;
3219 switch (sep_by_space)
3220 {
3221 case 0:
3222 pat.field[1] = value;
3223 pat.field[2] = none;
3224 return;
3225 case 1:
3226 pat.field[1] = value;
3227 pat.field[2] = space;
3228 return;
3229 case 2:
3230 pat.field[1] = space;
3231 pat.field[2] = value;
3232 return;
3233 default:
3234 break;
3235 }
3236 break;
3237 case 2:
3238 pat.field[0] = value;
3239 pat.field[3] = sign;
3240 switch (sep_by_space)
3241 {
3242 case 0:
3243 pat.field[1] = none;
3244 pat.field[2] = symbol;
3245 return;
3246 case 1:
3247 pat.field[1] = space;
3248 pat.field[2] = symbol;
3249 return;
3250 case 2:
3251 pat.field[1] = symbol;
3252 pat.field[2] = space;
3253 return;
3254 default:
3255 break;
3256 }
3257 break;
3258 case 3:
3259 pat.field[0] = value;
3260 pat.field[3] = symbol;
3261 switch (sep_by_space)
3262 {
3263 case 0:
3264 pat.field[1] = none;
3265 pat.field[2] = sign;
3266 return;
3267 case 1:
3268 pat.field[1] = space;
3269 pat.field[2] = sign;
3270 return;
3271 case 2:
3272 pat.field[1] = sign;
3273 pat.field[2] = space;
3274 return;
3275 default:
3276 break;
3277 }
3278 break;
3279 case 4:
3280 pat.field[0] = value;
3281 pat.field[3] = sign;
3282 switch (sep_by_space)
3283 {
3284 case 0:
3285 pat.field[1] = none;
3286 pat.field[2] = symbol;
3287 return;
3288 case 1:
3289 pat.field[1] = space;
3290 pat.field[2] = symbol;
3291 return;
3292 case 2:
3293 pat.field[1] = symbol;
3294 pat.field[2] = space;
3295 return;
3296 default:
3297 break;
3298 }
3299 break;
3300 default:
3301 break;
3302 }
3303 break;
3304 case 1:
3305 switch (sign_posn)
3306 {
3307 case 0:
3308 pat.field[0] = sign;
3309 pat.field[1] = symbol;
3310 pat.field[3] = value;
3311 switch (sep_by_space)
3312 {
3313 case 0:
3314 pat.field[2] = none;
3315 return;
3316 case 1:
3317 case 2:
3318 pat.field[2] = space;
3319 return;
3320 default:
3321 break;
3322 }
3323 break;
3324 case 1:
3325 pat.field[0] = sign;
3326 pat.field[3] = value;
3327 switch (sep_by_space)
3328 {
3329 case 0:
3330 pat.field[1] = symbol;
3331 pat.field[2] = none;
3332 return;
3333 case 1:
3334 pat.field[1] = symbol;
3335 pat.field[2] = space;
3336 return;
3337 case 2:
3338 pat.field[1] = space;
3339 pat.field[2] = symbol;
3340 return;
3341 default:
3342 break;
3343 }
3344 break;
3345 case 2:
3346 pat.field[0] = symbol;
3347 pat.field[3] = sign;
3348 switch (sep_by_space)
3349 {
3350 case 0:
3351 pat.field[1] = none;
3352 pat.field[2] = value;
3353 return;
3354 case 1:
3355 pat.field[1] = space;
3356 pat.field[2] = value;
3357 return;
3358 case 2:
3359 pat.field[1] = value;
3360 pat.field[2] = space;
3361 return;
3362 default:
3363 break;
3364 }
3365 break;
3366 case 3:
3367 pat.field[0] = sign;
3368 pat.field[3] = value;
3369 switch (sep_by_space)
3370 {
3371 case 0:
3372 pat.field[1] = symbol;
3373 pat.field[2] = none;
3374 return;
3375 case 1:
3376 pat.field[1] = symbol;
3377 pat.field[2] = space;
3378 return;
3379 case 2:
3380 pat.field[1] = space;
3381 pat.field[2] = symbol;
3382 return;
3383 default:
3384 break;
3385 }
3386 break;
3387 case 4:
3388 pat.field[0] = symbol;
3389 pat.field[3] = value;
3390 switch (sep_by_space)
3391 {
3392 case 0:
3393 pat.field[1] = sign;
3394 pat.field[2] = none;
3395 return;
3396 case 1:
3397 pat.field[1] = sign;
3398 pat.field[2] = space;
3399 return;
3400 case 2:
3401 pat.field[1] = space;
3402 pat.field[2] = sign;
3403 return;
3404 default:
3405 break;
3406 }
3407 break;
3408 default:
3409 break;
3410 }
3411 break;
3412 default:
3413 break;
3414 }
3415 pat.field[0] = symbol;
3416 pat.field[1] = sign;
3417 pat.field[2] = none;
3418 pat.field[3] = value;
3419}
3420
3421template<>
3422void
3423moneypunct_byname<char, false>::init(const char* nm)
3424{
3425 typedef moneypunct<char, false> base;
3426 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
3427 if (loc == 0)
3428 throw runtime_error("moneypunct_byname"
3429 " failed to construct for " + string(nm));
3430 lconv* lc = localeconv_l(loc.get());
3431 if (*lc->mon_decimal_point)
3432 __decimal_point_ = *lc->mon_decimal_point;
3433 else
3434 __decimal_point_ = base::do_decimal_point();
3435 if (*lc->mon_thousands_sep)
3436 __thousands_sep_ = *lc->mon_thousands_sep;
3437 else
3438 __thousands_sep_ = base::do_thousands_sep();
3439 __grouping_ = lc->mon_grouping;
3440 __curr_symbol_ = lc->currency_symbol;
3441 if (lc->frac_digits != CHAR_MAX)
3442 __frac_digits_ = lc->frac_digits;
3443 else
3444 __frac_digits_ = base::do_frac_digits();
3445 if (lc->p_sign_posn == 0)
3446 __positive_sign_ = "()";
3447 else
3448 __positive_sign_ = lc->positive_sign;
3449 if (lc->n_sign_posn == 0)
3450 __negative_sign_ = "()";
3451 else
3452 __negative_sign_ = lc->negative_sign;
3453 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
3454 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
3455}
3456
3457template<>
3458void
3459moneypunct_byname<char, true>::init(const char* nm)
3460{
3461 typedef moneypunct<char, true> base;
3462 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
3463 if (loc == 0)
3464 throw runtime_error("moneypunct_byname"
3465 " failed to construct for " + string(nm));
3466 lconv* lc = localeconv_l(loc.get());
3467 if (*lc->mon_decimal_point)
3468 __decimal_point_ = *lc->mon_decimal_point;
3469 else
3470 __decimal_point_ = base::do_decimal_point();
3471 if (*lc->mon_thousands_sep)
3472 __thousands_sep_ = *lc->mon_thousands_sep;
3473 else
3474 __thousands_sep_ = base::do_thousands_sep();
3475 __grouping_ = lc->mon_grouping;
3476 __curr_symbol_ = lc->int_curr_symbol;
3477 if (lc->int_frac_digits != CHAR_MAX)
3478 __frac_digits_ = lc->int_frac_digits;
3479 else
3480 __frac_digits_ = base::do_frac_digits();
3481 if (lc->int_p_sign_posn == 0)
3482 __positive_sign_ = "()";
3483 else
3484 __positive_sign_ = lc->positive_sign;
3485 if (lc->int_n_sign_posn == 0)
3486 __negative_sign_ = "()";
3487 else
3488 __negative_sign_ = lc->negative_sign;
3489 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
3490 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
3491}
3492
3493template<>
3494void
3495moneypunct_byname<wchar_t, false>::init(const char* nm)
3496{
3497 typedef moneypunct<wchar_t, false> base;
3498 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
3499 if (loc == 0)
3500 throw runtime_error("moneypunct_byname"
3501 " failed to construct for " + string(nm));
3502 lconv* lc = localeconv_l(loc.get());
3503 if (*lc->mon_decimal_point)
3504 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
3505 else
3506 __decimal_point_ = base::do_decimal_point();
3507 if (*lc->mon_thousands_sep)
3508 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
3509 else
3510 __thousands_sep_ = base::do_thousands_sep();
3511 __grouping_ = lc->mon_grouping;
3512 wchar_t wbuf[100];
3513 mbstate_t mb = {0};
3514 const char* bb = lc->currency_symbol;
3515 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
3516 if (j == -1)
3517 __throw_runtime_error("locale not supported");
3518 wchar_t* wbe = wbuf + j;
3519 __curr_symbol_.assign(wbuf, wbe);
3520 if (lc->frac_digits != CHAR_MAX)
3521 __frac_digits_ = lc->frac_digits;
3522 else
3523 __frac_digits_ = base::do_frac_digits();
3524 if (lc->p_sign_posn == 0)
3525 __positive_sign_ = L"()";
3526 else
3527 {
3528 mb = mbstate_t();
3529 bb = lc->positive_sign;
3530 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
3531 if (j == -1)
3532 __throw_runtime_error("locale not supported");
3533 wbe = wbuf + j;
3534 __positive_sign_.assign(wbuf, wbe);
3535 }
3536 if (lc->n_sign_posn == 0)
3537 __negative_sign_ = L"()";
3538 else
3539 {
3540 mb = mbstate_t();
3541 bb = lc->negative_sign;
3542 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
3543 if (j == -1)
3544 __throw_runtime_error("locale not supported");
3545 wbe = wbuf + j;
3546 __negative_sign_.assign(wbuf, wbe);
3547 }
3548 __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn);
3549 __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn);
3550}
3551
3552template<>
3553void
3554moneypunct_byname<wchar_t, true>::init(const char* nm)
3555{
3556 typedef moneypunct<wchar_t, true> base;
3557 unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
3558 if (loc == 0)
3559 throw runtime_error("moneypunct_byname"
3560 " failed to construct for " + string(nm));
3561 lconv* lc = localeconv_l(loc.get());
3562 if (*lc->mon_decimal_point)
3563 __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point);
3564 else
3565 __decimal_point_ = base::do_decimal_point();
3566 if (*lc->mon_thousands_sep)
3567 __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep);
3568 else
3569 __thousands_sep_ = base::do_thousands_sep();
3570 __grouping_ = lc->mon_grouping;
3571 wchar_t wbuf[100];
3572 mbstate_t mb = {0};
3573 const char* bb = lc->int_curr_symbol;
3574 size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
3575 if (j == -1)
3576 __throw_runtime_error("locale not supported");
3577 wchar_t* wbe = wbuf + j;
3578 __curr_symbol_.assign(wbuf, wbe);
3579 if (lc->int_frac_digits != CHAR_MAX)
3580 __frac_digits_ = lc->int_frac_digits;
3581 else
3582 __frac_digits_ = base::do_frac_digits();
3583 if (lc->int_p_sign_posn == 0)
3584 __positive_sign_ = L"()";
3585 else
3586 {
3587 mb = mbstate_t();
3588 bb = lc->positive_sign;
3589 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
3590 if (j == -1)
3591 __throw_runtime_error("locale not supported");
3592 wbe = wbuf + j;
3593 __positive_sign_.assign(wbuf, wbe);
3594 }
3595 if (lc->int_n_sign_posn == 0)
3596 __negative_sign_ = L"()";
3597 else
3598 {
3599 mb = mbstate_t();
3600 bb = lc->negative_sign;
3601 j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get());
3602 if (j == -1)
3603 __throw_runtime_error("locale not supported");
3604 wbe = wbuf + j;
3605 __negative_sign_.assign(wbuf, wbe);
3606 }
3607 __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn);
3608 __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn);
3609}
3610
3611void __do_nothing(void*) {}
3612
3613void __throw_runtime_error(const char* msg)
3614{
3615 throw runtime_error(msg);
3616}
3617
3618template class collate<char>;
3619template class collate<wchar_t>;
3620
3621template class num_get<char>;
3622template class num_get<wchar_t>;
3623
3624template class __num_get<char>;
3625template class __num_get<wchar_t>;
3626
3627template class num_put<char>;
3628template class num_put<wchar_t>;
3629
3630template class __num_put<char>;
3631template class __num_put<wchar_t>;
3632
3633template class time_get<char>;
3634template class time_get<wchar_t>;
3635
3636template class time_get_byname<char>;
3637template class time_get_byname<wchar_t>;
3638
3639template class time_put<char>;
3640template class time_put<wchar_t>;
3641
3642template class time_put_byname<char>;
3643template class time_put_byname<wchar_t>;
3644
3645template class moneypunct<char, false>;
3646template class moneypunct<char, true>;
3647template class moneypunct<wchar_t, false>;
3648template class moneypunct<wchar_t, true>;
3649
3650template class moneypunct_byname<char, false>;
3651template class moneypunct_byname<char, true>;
3652template class moneypunct_byname<wchar_t, false>;
3653template class moneypunct_byname<wchar_t, true>;
3654
3655template class money_get<char>;
3656template class money_get<wchar_t>;
3657
3658template class __money_get<char>;
3659template class __money_get<wchar_t>;
3660
3661template class money_put<char>;
3662template class money_put<wchar_t>;
3663
3664template class __money_put<char>;
3665template class __money_put<wchar_t>;
3666
3667template class messages<char>;
3668template class messages<wchar_t>;
3669
3670template class messages_byname<char>;
3671template class messages_byname<wchar_t>;
3672
3673template class codecvt_byname<char, char, mbstate_t>;
3674template class codecvt_byname<wchar_t, char, mbstate_t>;
3675template class codecvt_byname<char16_t, char, mbstate_t>;
3676template class codecvt_byname<char32_t, char, mbstate_t>;
3677
3678template class __vector_base_common<true>;
3679
3680_LIBCPP_END_NAMESPACE_STD