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