blob: 743b393550074397fd1ad7a33c61e21750585b1d [file] [log] [blame]
Howard Hinnant3e519522010-05-11 19:42:161// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnant5b08a8a2010-05-11 21:36:014// The LLVM Compiler Infrastructure
Howard Hinnant3e519522010-05-11 19:42:165//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP___LOCALE
12#define _LIBCPP___LOCALE
13
14#include <__config>
15#include <string>
16#include <memory>
17#include <utility>
18#include <mutex>
19#include <cstdint>
20#include <cctype>
Howard Hinnant128ba712010-05-24 17:49:4121#include <locale.h>
Howard Hinnant3e519522010-05-11 19:42:1622#include <xlocale.h>
23
24#pragma GCC system_header
25
26_LIBCPP_BEGIN_NAMESPACE_STD
27
28class locale;
29
30template <class _Facet> bool has_facet(const locale&) throw();
31template <class _Facet> const _Facet& use_facet(const locale&);
32
33class locale
34{
35public:
36 // types:
37 class facet;
38 class id;
39
40 typedef int category;
41 static const category // values assigned here are for exposition only
42 none = 0,
43 collate = LC_COLLATE_MASK,
44 ctype = LC_CTYPE_MASK,
45 monetary = LC_MONETARY_MASK,
46 numeric = LC_NUMERIC_MASK,
47 time = LC_TIME_MASK,
48 messages = LC_MESSAGES_MASK,
49 all = collate | ctype | monetary | numeric | time | messages;
50
51 // construct/copy/destroy:
52 locale() throw();
53 locale(const locale&) throw();
54 explicit locale(const char*);
55 explicit locale(const string&);
56 locale(const locale&, const char*, category);
57 locale(const locale&, const string&, category);
58 template <class _Facet> locale(const locale&, _Facet*);
59 locale(const locale&, const locale&, category);
60
61 ~locale() throw();
62
63 const locale& operator=(const locale&) throw();
64
65 template <class _Facet> locale combine(const locale&) const;
66
67 // locale operations:
68 string name() const;
69 bool operator==(const locale&) const;
70 bool operator!=(const locale& __y) const {return !(*this == __y);}
71 template <class _CharT, class _Traits, class _Allocator>
72 bool operator()(const basic_string<_CharT, _Traits, _Allocator>&,
73 const basic_string<_CharT, _Traits, _Allocator>&) const;
74
75 // global locale objects:
76 static locale global(const locale&);
77 static const locale& classic();
78
79private:
80 class __imp;
81 __imp* __locale_;
82
83 void __install_ctor(const locale&, facet*, long);
84 static locale& __global();
85 bool has_facet(id&) const;
86 const facet* use_facet(id&) const;
87
88 template <class _Facet> friend bool has_facet(const locale&) throw();
89 template <class _Facet> friend const _Facet& use_facet(const locale&);
90};
91
92class locale::facet
93 : public __shared_count
94{
95protected:
96 explicit facet(size_t __refs = 0)
97 : __shared_count(static_cast<long>(__refs)-1) {}
98
99 virtual ~facet();
100
101// facet(const facet&) = delete; // effectively done in __shared_count
102// void operator=(const facet&) = delete;
103private:
104 virtual void __on_zero_shared();
105};
106
107class locale::id
108{
109 once_flag __flag_;
110 int32_t __id_;
111
112 static int32_t __next_id;
113public:
114 id() {}
115private:
116 void __init();
117 void operator=(const id&); // = delete;
118 id(const id&); // = delete;
119public: // only needed for tests
120 long __get();
121
122 friend class locale;
123 friend class locale::__imp;
124};
125
126template <class _Facet>
127inline _LIBCPP_INLINE_VISIBILITY
128locale::locale(const locale& __other, _Facet* __f)
129{
130 __install_ctor(__other, __f, __f ? __f->id.__get() : 0);
131}
132
133template <class _Facet>
134locale
135locale::combine(const locale& __other) const
136{
Howard Hinnant54b409f2010-08-11 17:04:31137#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16138 if (!_STD::has_facet<_Facet>(__other))
139 throw runtime_error("locale::combine: locale missing facet");
Howard Hinnant54b409f2010-08-11 17:04:31140#endif
Howard Hinnant3e519522010-05-11 19:42:16141 return locale(*this, &const_cast<_Facet&>(_STD::use_facet<_Facet>(__other)));
142}
143
144template <class _Facet>
145inline _LIBCPP_INLINE_VISIBILITY
146bool
147has_facet(const locale& __l) throw()
148{
149 return __l.has_facet(_Facet::id);
150}
151
152template <class _Facet>
153inline _LIBCPP_INLINE_VISIBILITY
154const _Facet&
155use_facet(const locale& __l)
156{
157 return static_cast<const _Facet&>(*__l.use_facet(_Facet::id));
158}
159
160// template <class _CharT> class collate;
161
162template <class _CharT>
163class collate
164 : public locale::facet
165{
166public:
167 typedef _CharT char_type;
168 typedef basic_string<char_type> string_type;
169
170 explicit collate(size_t __refs = 0)
171 : locale::facet(__refs) {}
172
173 int compare(const char_type* __lo1, const char_type* __hi1,
174 const char_type* __lo2, const char_type* __hi2) const
175 {
176 return do_compare(__lo1, __hi1, __lo2, __hi2);
177 }
178
179 string_type transform(const char_type* __lo, const char_type* __hi) const
180 {
181 return do_transform(__lo, __hi);
182 }
183
184 long hash(const char_type* __lo, const char_type* __hi) const
185 {
186 return do_hash(__lo, __hi);
187 }
188
189 static locale::id id;
190
191protected:
192 ~collate();
193 virtual int do_compare(const char_type* __lo1, const char_type* __hi1,
194 const char_type* __lo2, const char_type* __hi2) const;
195 virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const
196 {return string_type(__lo, __hi);}
197 virtual long do_hash(const char_type* __lo, const char_type* __hi) const;
198};
199
200template <class _CharT> locale::id collate<_CharT>::id;
201
202template <class _CharT>
203collate<_CharT>::~collate()
204{
205}
206
207template <class _CharT>
208int
209collate<_CharT>::do_compare(const char_type* __lo1, const char_type* __hi1,
210 const char_type* __lo2, const char_type* __hi2) const
211{
212 for (; __lo2 != __hi2; ++__lo1, ++__lo2)
213 {
214 if (__lo1 == __hi1 || *__lo1 < *__lo2)
215 return -1;
216 if (*__lo2 < *__lo1)
217 return 1;
218 }
219 return __lo1 != __hi1;
220}
221
222template <class _CharT>
223long
224collate<_CharT>::do_hash(const char_type* lo, const char_type* hi) const
225{
226 size_t h = 0;
227 const size_t sr = __CHAR_BIT__ * sizeof(size_t) - 8;
228 const size_t mask = size_t(0xF) << (sr + 4);
229 for(const char_type* p = lo; p != hi; ++p)
230 {
231 h = (h << 4) + *p;
232 size_t g = h & mask;
233 h ^= g | (g >> sr);
234 }
235 return static_cast<long>(h);
236}
237
238extern template class collate<char>;
239extern template class collate<wchar_t>;
240
241// template <class CharT> class collate_byname;
242
243template <class _CharT> class collate_byname;
244
245template <>
246class collate_byname<char>
247 : public collate<char>
248{
249 locale_t __l;
250public:
251 typedef char char_type;
252 typedef basic_string<char_type> string_type;
253
254 explicit collate_byname(const char* __n, size_t __refs = 0);
255 explicit collate_byname(const string& __n, size_t __refs = 0);
256
257protected:
258 ~collate_byname();
259 virtual int do_compare(const char_type* __lo1, const char_type* __hi1,
260 const char_type* __lo2, const char_type* __hi2) const;
261 virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const;
262};
263
264template <>
265class collate_byname<wchar_t>
266 : public collate<wchar_t>
267{
268 locale_t __l;
269public:
270 typedef wchar_t char_type;
271 typedef basic_string<char_type> string_type;
272
273 explicit collate_byname(const char* __n, size_t __refs = 0);
274 explicit collate_byname(const string& __n, size_t __refs = 0);
275
276protected:
277 ~collate_byname();
278
279 virtual int do_compare(const char_type* __lo1, const char_type* __hi1,
280 const char_type* __lo2, const char_type* __hi2) const;
281 virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const;
282};
283
284template <class _CharT, class _Traits, class _Allocator>
285bool
286locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x,
287 const basic_string<_CharT, _Traits, _Allocator>& __y) const
288{
289 return _STD::use_facet<_STD::collate<_CharT> >(*this).compare(
290 __x.data(), __x.data() + __x.size(),
291 __y.data(), __y.data() + __y.size()) < 0;
292}
293
294// template <class charT> class ctype
295
296class ctype_base {
297public:
298 typedef __uint32_t mask;
299
Howard Hinnant128ba712010-05-24 17:49:41300#if __APPLE__
Howard Hinnant3e519522010-05-11 19:42:16301 static const mask space = _CTYPE_S;
302 static const mask print = _CTYPE_R;
303 static const mask cntrl = _CTYPE_C;
304 static const mask upper = _CTYPE_U;
305 static const mask lower = _CTYPE_L;
306 static const mask alpha = _CTYPE_A;
307 static const mask digit = _CTYPE_D;
308 static const mask punct = _CTYPE_P;
309 static const mask xdigit = _CTYPE_X;
310 static const mask blank = _CTYPE_B;
Howard Hinnant128ba712010-05-24 17:49:41311#else /* !__APPLE__ */
312 static const mask space = _ISspace;
313 static const mask print = _ISprint;
314 static const mask cntrl = _IScntrl;
315 static const mask upper = _ISupper;
316 static const mask lower = _ISlower;
317 static const mask alpha = _ISalpha;
318 static const mask digit = _ISdigit;
319 static const mask punct = _ISpunct;
320 static const mask xdigit = _ISxdigit;
321 static const mask blank = _ISblank;
322#endif /* __APPLE__ */
Howard Hinnant3e519522010-05-11 19:42:16323 static const mask alnum = alpha | digit;
324 static const mask graph = alnum | punct;
325
326 _LIBCPP_ALWAYS_INLINE ctype_base() {}
327};
328
329template <class _CharT> class ctype;
330
331template <>
332class ctype<wchar_t>
333 : public locale::facet,
334 public ctype_base
335{
336public:
337 typedef wchar_t char_type;
338
339 _LIBCPP_ALWAYS_INLINE
340 explicit ctype(size_t __refs = 0)
341 : locale::facet(__refs) {}
342
343 _LIBCPP_ALWAYS_INLINE
344 bool is(mask __m, char_type __c) const
345 {
346 return do_is(__m, __c);
347 }
348
349 _LIBCPP_ALWAYS_INLINE
350 const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const
351 {
352 return do_is(__low, __high, __vec);
353 }
354
355 _LIBCPP_ALWAYS_INLINE
356 const char_type* scan_is(mask __m, const char_type* __low, const char_type* __high) const
357 {
358 return do_scan_is(__m, __low, __high);
359 }
360
361 _LIBCPP_ALWAYS_INLINE
362 const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const
363 {
364 return do_scan_not(__m, __low, __high);
365 }
366
367 _LIBCPP_ALWAYS_INLINE
368 char_type toupper(char_type __c) const
369 {
370 return do_toupper(__c);
371 }
372
373 _LIBCPP_ALWAYS_INLINE
374 const char_type* toupper(char_type* __low, const char_type* __high) const
375 {
376 return do_toupper(__low, __high);
377 }
378
379 _LIBCPP_ALWAYS_INLINE
380 char_type tolower(char_type __c) const
381 {
382 return do_tolower(__c);
383 }
384
385 _LIBCPP_ALWAYS_INLINE
386 const char_type* tolower(char_type* __low, const char_type* __high) const
387 {
388 return do_tolower(__low, __high);
389 }
390
391 _LIBCPP_ALWAYS_INLINE
392 char_type widen(char __c) const
393 {
394 return do_widen(__c);
395 }
396
397 _LIBCPP_ALWAYS_INLINE
398 const char* widen(const char* __low, const char* __high, char_type* __to) const
399 {
400 return do_widen(__low, __high, __to);
401 }
402
403 _LIBCPP_ALWAYS_INLINE
404 char narrow(char_type __c, char __dfault) const
405 {
406 return do_narrow(__c, __dfault);
407 }
408
409 _LIBCPP_ALWAYS_INLINE
410 const char_type* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const
411 {
412 return do_narrow(__low, __high, __dfault, __to);
413 }
414
415 static locale::id id;
416
417protected:
418 ~ctype();
419 virtual bool do_is(mask __m, char_type __c) const;
420 virtual const char_type* do_is(const char_type* __low, const char_type* __high, mask* __vec) const;
421 virtual const char_type* do_scan_is(mask __m, const char_type* __low, const char_type* __high) const;
422 virtual const char_type* do_scan_not(mask __m, const char_type* __low, const char_type* __high) const;
423 virtual char_type do_toupper(char_type) const;
424 virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
425 virtual char_type do_tolower(char_type) const;
426 virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
427 virtual char_type do_widen(char) const;
428 virtual const char* do_widen(const char* __low, const char* __high, char_type* __dest) const;
429 virtual char do_narrow(char_type, char __dfault) const;
430 virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const;
431};
432
433template <>
434class ctype<char>
435 : public locale::facet, public ctype_base
436{
437 const mask* __tab_;
438 bool __del_;
439public:
440 typedef char char_type;
441
442 explicit ctype(const mask* __tab = 0, bool __del = false, size_t __refs = 0);
443
444 _LIBCPP_ALWAYS_INLINE
445 bool is(mask __m, char_type __c) const
446 {
447 return isascii(__c) ? __tab_[__c] & __m : false;
448 }
449
450 _LIBCPP_ALWAYS_INLINE
451 const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const
452 {
453 for (; __low != __high; ++__low, ++__vec)
454 *__vec = isascii(*__low) ? __tab_[*__low] : 0;
455 return __low;
456 }
457
458 _LIBCPP_ALWAYS_INLINE
459 const char_type* scan_is (mask __m, const char_type* __low, const char_type* __high) const
460 {
461 for (; __low != __high; ++__low)
462 if (isascii(*__low) && (__tab_[*__low] & __m))
463 break;
464 return __low;
465 }
466
467 _LIBCPP_ALWAYS_INLINE
468 const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const
469 {
470 for (; __low != __high; ++__low)
471 if (!(isascii(*__low) && (__tab_[*__low] & __m)))
472 break;
473 return __low;
474 }
475
476 _LIBCPP_ALWAYS_INLINE
477 char_type toupper(char_type __c) const
478 {
479 return do_toupper(__c);
480 }
481
482 _LIBCPP_ALWAYS_INLINE
483 const char_type* toupper(char_type* __low, const char_type* __high) const
484 {
485 return do_toupper(__low, __high);
486 }
487
488 _LIBCPP_ALWAYS_INLINE
489 char_type tolower(char_type __c) const
490 {
491 return do_tolower(__c);
492 }
493
494 _LIBCPP_ALWAYS_INLINE
495 const char_type* tolower(char_type* __low, const char_type* __high) const
496 {
497 return do_tolower(__low, __high);
498 }
499
500 _LIBCPP_ALWAYS_INLINE
501 char_type widen(char __c) const
502 {
503 return do_widen(__c);
504 }
505
506 _LIBCPP_ALWAYS_INLINE
507 const char* widen(const char* __low, const char* __high, char_type* __to) const
508 {
509 return do_widen(__low, __high, __to);
510 }
511
512 _LIBCPP_ALWAYS_INLINE
513 char narrow(char_type __c, char __dfault) const
514 {
515 return do_narrow(__c, __dfault);
516 }
517
518 _LIBCPP_ALWAYS_INLINE
519 const char* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const
520 {
521 return do_narrow(__low, __high, __dfault, __to);
522 }
523
524 static locale::id id;
525
Howard Hinnant128ba712010-05-24 17:49:41526#ifdef _CACHED_RUNES
Howard Hinnant3e519522010-05-11 19:42:16527 static const size_t table_size = _CACHED_RUNES;
Howard Hinnant128ba712010-05-24 17:49:41528#else
529 static const size_t table_size = 256; // FIXME: Don't hardcode this.
530#endif
Howard Hinnant3e519522010-05-11 19:42:16531 const mask* table() const throw() {return __tab_;}
532 static const mask* classic_table() throw();
533
534protected:
535 ~ctype();
536 virtual char_type do_toupper(char_type __c) const;
537 virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
538 virtual char_type do_tolower(char_type __c) const;
539 virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
540 virtual char_type do_widen(char __c) const;
541 virtual const char* do_widen(const char* __low, const char* __high, char_type* __to) const;
542 virtual char do_narrow(char_type __c, char __dfault) const;
543 virtual const char* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const;
544};
545
546// template <class CharT> class ctype_byname;
547
548template <class _CharT> class ctype_byname;
549
550template <>
551class ctype_byname<char>
552 : public ctype<char>
553{
554 locale_t __l;
555
556public:
557 explicit ctype_byname(const char*, size_t = 0);
558 explicit ctype_byname(const string&, size_t = 0);
559
560protected:
561 ~ctype_byname();
562 virtual char_type do_toupper(char_type) const;
563 virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
564 virtual char_type do_tolower(char_type) const;
565 virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
566};
567
568template <>
569class ctype_byname<wchar_t>
570 : public ctype<wchar_t>
571{
572 locale_t __l;
573
574public:
575 explicit ctype_byname(const char*, size_t = 0);
576 explicit ctype_byname(const string&, size_t = 0);
577
578protected:
579 ~ctype_byname();
580 virtual bool do_is(mask __m, char_type __c) const;
581 virtual const char_type* do_is(const char_type* __low, const char_type* __high, mask* __vec) const;
582 virtual const char_type* do_scan_is(mask __m, const char_type* __low, const char_type* __high) const;
583 virtual const char_type* do_scan_not(mask __m, const char_type* __low, const char_type* __high) const;
584 virtual char_type do_toupper(char_type) const;
585 virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
586 virtual char_type do_tolower(char_type) const;
587 virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
588 virtual char_type do_widen(char) const;
589 virtual const char* do_widen(const char* __low, const char* __high, char_type* __dest) const;
590 virtual char do_narrow(char_type, char __dfault) const;
591 virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const;
592};
593
594template <class _CharT>
595inline _LIBCPP_INLINE_VISIBILITY
596bool
597isspace(_CharT __c, const locale& __loc)
598{
599 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::space, __c);
600}
601
602template <class _CharT>
603inline _LIBCPP_INLINE_VISIBILITY
604bool
605isprint(_CharT __c, const locale& __loc)
606{
607 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::print, __c);
608}
609
610template <class _CharT>
611inline _LIBCPP_INLINE_VISIBILITY
612bool
613iscntrl(_CharT __c, const locale& __loc)
614{
615 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::cntrl, __c);
616}
617
618template <class _CharT>
619inline _LIBCPP_INLINE_VISIBILITY
620bool
621isupper(_CharT __c, const locale& __loc)
622{
623 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::upper, __c);
624}
625
626template <class _CharT>
627inline _LIBCPP_INLINE_VISIBILITY
628bool
629islower(_CharT __c, const locale& __loc)
630{
631 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::lower, __c);
632}
633
634template <class _CharT>
635inline _LIBCPP_INLINE_VISIBILITY
636bool
637isalpha(_CharT __c, const locale& __loc)
638{
639 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alpha, __c);
640}
641
642template <class _CharT>
643inline _LIBCPP_INLINE_VISIBILITY
644bool
645isdigit(_CharT __c, const locale& __loc)
646{
647 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::digit, __c);
648}
649
650template <class _CharT>
651inline _LIBCPP_INLINE_VISIBILITY
652bool
653ispunct(_CharT __c, const locale& __loc)
654{
655 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::punct, __c);
656}
657
658template <class _CharT>
659inline _LIBCPP_INLINE_VISIBILITY
660bool
661isxdigit(_CharT __c, const locale& __loc)
662{
663 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::xdigit, __c);
664}
665
666template <class _CharT>
667inline _LIBCPP_INLINE_VISIBILITY
668bool
669isalnum(_CharT __c, const locale& __loc)
670{
671 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alnum, __c);
672}
673
674template <class _CharT>
675inline _LIBCPP_INLINE_VISIBILITY
676bool
677isgraph(_CharT __c, const locale& __loc)
678{
679 return use_facet<ctype<_CharT> >(__loc).is(ctype_base::graph, __c);
680}
681
682template <class _CharT>
683inline _LIBCPP_INLINE_VISIBILITY
684_CharT
685toupper(_CharT __c, const locale& __loc)
686{
687 return use_facet<ctype<_CharT> >(__loc).toupper(__c);
688}
689
690template <class _CharT>
691inline _LIBCPP_INLINE_VISIBILITY
692_CharT
693tolower(_CharT __c, const locale& __loc)
694{
695 return use_facet<ctype<_CharT> >(__loc).tolower(__c);
696}
697
698// codecvt_base
699
700class codecvt_base
701{
702public:
703 _LIBCPP_ALWAYS_INLINE codecvt_base() {}
704 enum result {ok, partial, error, noconv};
705};
706
707// template <class internT, class externT, class stateT> class codecvt;
708
709template <class _InternT, class _ExternT, class _StateT> class codecvt;
710
711// template <> class codecvt<char, char, mbstate_t>
712
713template <>
714class codecvt<char, char, mbstate_t>
715 : public locale::facet,
716 public codecvt_base
717{
718public:
719 typedef char intern_type;
720 typedef char extern_type;
721 typedef mbstate_t state_type;
722
723 _LIBCPP_ALWAYS_INLINE
724 explicit codecvt(size_t __refs = 0)
725 : locale::facet(__refs) {}
726
727 _LIBCPP_ALWAYS_INLINE
728 result out(state_type& __st,
729 const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
730 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
731 {
732 return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
733 }
734
735 _LIBCPP_ALWAYS_INLINE
736 result unshift(state_type& __st,
737 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
738 {
739 return do_unshift(__st, __to, __to_end, __to_nxt);
740 }
741
742 _LIBCPP_ALWAYS_INLINE
743 result in(state_type& __st,
744 const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
745 intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
746 {
747 return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
748 }
749
750 _LIBCPP_ALWAYS_INLINE
751 int encoding() const throw()
752 {
753 return do_encoding();
754 }
755
756 _LIBCPP_ALWAYS_INLINE
757 bool always_noconv() const throw()
758 {
759 return do_always_noconv();
760 }
761
762 _LIBCPP_ALWAYS_INLINE
763 int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
764 {
765 return do_length(__st, __frm, __end, __mx);
766 }
767
768 _LIBCPP_ALWAYS_INLINE
769 int max_length() const throw()
770 {
771 return do_max_length();
772 }
773
774 static locale::id id;
775
776protected:
777 _LIBCPP_ALWAYS_INLINE
778 explicit codecvt(const char*, size_t __refs = 0)
779 : locale::facet(__refs) {}
780
781 ~codecvt();
782
783 virtual result do_out(state_type& __st,
784 const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
785 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
786 virtual result do_in(state_type& __st,
787 const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
788 intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
789 virtual result do_unshift(state_type& __st,
790 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
791 virtual int do_encoding() const throw();
792 virtual bool do_always_noconv() const throw();
793 virtual int do_length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
794 virtual int do_max_length() const throw();
795};
796
797// template <> class codecvt<wchar_t, char, mbstate_t>
798
799template <>
800class codecvt<wchar_t, char, mbstate_t>
801 : public locale::facet,
802 public codecvt_base
803{
804 locale_t __l;
805public:
806 typedef wchar_t intern_type;
807 typedef char extern_type;
808 typedef mbstate_t state_type;
809
810 explicit codecvt(size_t __refs = 0);
811
812 _LIBCPP_ALWAYS_INLINE
813 result out(state_type& __st,
814 const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
815 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
816 {
817 return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
818 }
819
820 _LIBCPP_ALWAYS_INLINE
821 result unshift(state_type& __st,
822 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
823 {
824 return do_unshift(__st, __to, __to_end, __to_nxt);
825 }
826
827 _LIBCPP_ALWAYS_INLINE
828 result in(state_type& __st,
829 const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
830 intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
831 {
832 return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
833 }
834
835 _LIBCPP_ALWAYS_INLINE
836 int encoding() const throw()
837 {
838 return do_encoding();
839 }
840
841 _LIBCPP_ALWAYS_INLINE
842 bool always_noconv() const throw()
843 {
844 return do_always_noconv();
845 }
846
847 _LIBCPP_ALWAYS_INLINE
848 int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
849 {
850 return do_length(__st, __frm, __end, __mx);
851 }
852
853 _LIBCPP_ALWAYS_INLINE
854 int max_length() const throw()
855 {
856 return do_max_length();
857 }
858
859 static locale::id id;
860
861protected:
862 explicit codecvt(const char*, size_t __refs = 0);
863
864 ~codecvt();
865
866 virtual result do_out(state_type& __st,
867 const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
868 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
869 virtual result do_in(state_type& __st,
870 const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
871 intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
872 virtual result do_unshift(state_type& __st,
873 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
874 virtual int do_encoding() const throw();
875 virtual bool do_always_noconv() const throw();
876 virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
877 virtual int do_max_length() const throw();
878};
879
880// template <> class codecvt<char16_t, char, mbstate_t>
881
882template <>
883class codecvt<char16_t, char, mbstate_t>
884 : public locale::facet,
885 public codecvt_base
886{
887public:
888 typedef char16_t intern_type;
889 typedef char extern_type;
890 typedef mbstate_t state_type;
891
892 _LIBCPP_ALWAYS_INLINE
893 explicit codecvt(size_t __refs = 0)
894 : locale::facet(__refs) {}
895
896 _LIBCPP_ALWAYS_INLINE
897 result out(state_type& __st,
898 const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
899 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
900 {
901 return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
902 }
903
904 _LIBCPP_ALWAYS_INLINE
905 result unshift(state_type& __st,
906 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
907 {
908 return do_unshift(__st, __to, __to_end, __to_nxt);
909 }
910
911 _LIBCPP_ALWAYS_INLINE
912 result in(state_type& __st,
913 const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
914 intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
915 {
916 return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
917 }
918
919 _LIBCPP_ALWAYS_INLINE
920 int encoding() const throw()
921 {
922 return do_encoding();
923 }
924
925 _LIBCPP_ALWAYS_INLINE
926 bool always_noconv() const throw()
927 {
928 return do_always_noconv();
929 }
930
931 _LIBCPP_ALWAYS_INLINE
932 int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
933 {
934 return do_length(__st, __frm, __end, __mx);
935 }
936
937 _LIBCPP_ALWAYS_INLINE
938 int max_length() const throw()
939 {
940 return do_max_length();
941 }
942
943 static locale::id id;
944
945protected:
946 _LIBCPP_ALWAYS_INLINE
947 explicit codecvt(const char*, size_t __refs = 0)
948 : locale::facet(__refs) {}
949
950 ~codecvt();
951
952 virtual result do_out(state_type& __st,
953 const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
954 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
955 virtual result do_in(state_type& __st,
956 const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
957 intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
958 virtual result do_unshift(state_type& __st,
959 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
960 virtual int do_encoding() const throw();
961 virtual bool do_always_noconv() const throw();
962 virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
963 virtual int do_max_length() const throw();
964};
965
966// template <> class codecvt<char32_t, char, mbstate_t>
967
968template <>
969class codecvt<char32_t, char, mbstate_t>
970 : public locale::facet,
971 public codecvt_base
972{
973public:
974 typedef char32_t intern_type;
975 typedef char extern_type;
976 typedef mbstate_t state_type;
977
978 _LIBCPP_ALWAYS_INLINE
979 explicit codecvt(size_t __refs = 0)
980 : locale::facet(__refs) {}
981
982 _LIBCPP_ALWAYS_INLINE
983 result out(state_type& __st,
984 const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
985 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
986 {
987 return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
988 }
989
990 _LIBCPP_ALWAYS_INLINE
991 result unshift(state_type& __st,
992 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
993 {
994 return do_unshift(__st, __to, __to_end, __to_nxt);
995 }
996
997 _LIBCPP_ALWAYS_INLINE
998 result in(state_type& __st,
999 const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1000 intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
1001 {
1002 return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1003 }
1004
1005 _LIBCPP_ALWAYS_INLINE
1006 int encoding() const throw()
1007 {
1008 return do_encoding();
1009 }
1010
1011 _LIBCPP_ALWAYS_INLINE
1012 bool always_noconv() const throw()
1013 {
1014 return do_always_noconv();
1015 }
1016
1017 _LIBCPP_ALWAYS_INLINE
1018 int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1019 {
1020 return do_length(__st, __frm, __end, __mx);
1021 }
1022
1023 _LIBCPP_ALWAYS_INLINE
1024 int max_length() const throw()
1025 {
1026 return do_max_length();
1027 }
1028
1029 static locale::id id;
1030
1031protected:
1032 _LIBCPP_ALWAYS_INLINE
1033 explicit codecvt(const char*, size_t __refs = 0)
1034 : locale::facet(__refs) {}
1035
1036 ~codecvt();
1037
1038 virtual result do_out(state_type& __st,
1039 const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1040 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1041 virtual result do_in(state_type& __st,
1042 const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1043 intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1044 virtual result do_unshift(state_type& __st,
1045 extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1046 virtual int do_encoding() const throw();
1047 virtual bool do_always_noconv() const throw();
1048 virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1049 virtual int do_max_length() const throw();
1050};
1051
Howard Hinnant3e519522010-05-11 19:42:161052// template <class _InternT, class _ExternT, class _StateT> class codecvt_byname
1053
1054template <class _InternT, class _ExternT, class _StateT>
1055class codecvt_byname
1056 : public codecvt<_InternT, _ExternT, _StateT>
1057{
1058public:
1059 explicit codecvt_byname(const char* __nm, size_t __refs = 0)
1060 : codecvt<_InternT, _ExternT, _StateT>(__nm, __refs) {}
1061 explicit codecvt_byname(const string& __nm, size_t __refs = 0)
1062 : codecvt<_InternT, _ExternT, _StateT>(__nm.c_str(), __refs) {}
1063protected:
1064 ~codecvt_byname();
1065};
1066
1067template <class _InternT, class _ExternT, class _StateT>
1068codecvt_byname<_InternT, _ExternT, _StateT>::~codecvt_byname()
1069{
1070}
1071
1072extern template class codecvt_byname<char, char, mbstate_t>;
1073extern template class codecvt_byname<wchar_t, char, mbstate_t>;
1074extern template class codecvt_byname<char16_t, char, mbstate_t>;
1075extern template class codecvt_byname<char32_t, char, mbstate_t>;
1076
1077void __throw_runtime_error(const char*);
1078
1079template <size_t _N>
1080struct __narrow_to_utf8
1081{
1082 template <class _OutputIterator, class _CharT>
1083 _OutputIterator
1084 operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const;
1085};
1086
1087template <>
1088struct __narrow_to_utf8<8>
1089{
1090 template <class _OutputIterator, class _CharT>
1091 _LIBCPP_ALWAYS_INLINE
1092 _OutputIterator
1093 operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
1094 {
1095 for (; __wb < __we; ++__wb, ++__s)
1096 *__s = *__wb;
1097 return __s;
1098 }
1099};
1100
1101template <>
1102struct __narrow_to_utf8<16>
1103 : public codecvt<char16_t, char, mbstate_t>
1104{
1105 _LIBCPP_ALWAYS_INLINE
1106 __narrow_to_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
1107
1108 ~__narrow_to_utf8();
1109
1110 template <class _OutputIterator, class _CharT>
1111 _LIBCPP_ALWAYS_INLINE
1112 _OutputIterator
1113 operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
1114 {
1115 result __r = ok;
1116 mbstate_t __mb;
1117 while (__wb < __we && __r != error)
1118 {
1119 const int __sz = 32;
1120 char __buf[__sz];
1121 char* __bn;
1122 const char16_t* __wn = (const char16_t*)__wb;
1123 __r = do_out(__mb, (const char16_t*)__wb, (const char16_t*)__we, __wn,
1124 __buf, __buf+__sz, __bn);
1125 if (__r == codecvt_base::error || __wn == (const char16_t*)__wb)
1126 __throw_runtime_error("locale not supported");
1127 for (const char* __p = __buf; __p < __bn; ++__p, ++__s)
1128 *__s = *__p;
1129 __wb = (const _CharT*)__wn;
1130 }
1131 return __s;
1132 }
1133};
1134
1135template <>
1136struct __narrow_to_utf8<32>
1137 : public codecvt<char32_t, char, mbstate_t>
1138{
1139 _LIBCPP_ALWAYS_INLINE
1140 __narrow_to_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
1141
1142 ~__narrow_to_utf8();
1143
1144 template <class _OutputIterator, class _CharT>
1145 _LIBCPP_ALWAYS_INLINE
1146 _OutputIterator
1147 operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
1148 {
1149 result __r = ok;
1150 mbstate_t __mb;
1151 while (__wb < __we && __r != error)
1152 {
1153 const int __sz = 32;
1154 char __buf[__sz];
1155 char* __bn;
1156 const char32_t* __wn = (const char32_t*)__wb;
1157 __r = do_out(__mb, (const char32_t*)__wb, (const char32_t*)__we, __wn,
1158 __buf, __buf+__sz, __bn);
1159 if (__r == codecvt_base::error || __wn == (const char32_t*)__wb)
1160 __throw_runtime_error("locale not supported");
1161 for (const char* __p = __buf; __p < __bn; ++__p, ++__s)
1162 *__s = *__p;
1163 __wb = (const _CharT*)__wn;
1164 }
1165 return __s;
1166 }
1167};
1168
1169template <size_t _N>
1170struct __widen_from_utf8
1171{
1172 template <class _OutputIterator>
1173 _OutputIterator
1174 operator()(_OutputIterator __s, const char* __nb, const char* __ne) const;
1175};
1176
1177template <>
1178struct __widen_from_utf8<8>
1179{
1180 template <class _OutputIterator>
1181 _LIBCPP_ALWAYS_INLINE
1182 _OutputIterator
1183 operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
1184 {
1185 for (; __nb < __ne; ++__nb, ++__s)
1186 *__s = *__nb;
1187 return __s;
1188 }
1189};
1190
1191template <>
1192struct __widen_from_utf8<16>
1193 : public codecvt<char16_t, char, mbstate_t>
1194{
1195 _LIBCPP_ALWAYS_INLINE
1196 __widen_from_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
1197
1198 ~__widen_from_utf8();
1199
1200 template <class _OutputIterator>
1201 _LIBCPP_ALWAYS_INLINE
1202 _OutputIterator
1203 operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
1204 {
1205 result __r = ok;
1206 mbstate_t __mb;
1207 while (__nb < __ne && __r != error)
1208 {
1209 const int __sz = 32;
1210 char16_t __buf[__sz];
1211 char16_t* __bn;
1212 const char* __nn = __nb;
1213 __r = do_in(__mb, __nb, __ne - __nb > __sz ? __nb+__sz : __ne, __nn,
1214 __buf, __buf+__sz, __bn);
1215 if (__r == codecvt_base::error || __nn == __nb)
1216 __throw_runtime_error("locale not supported");
1217 for (const char16_t* __p = __buf; __p < __bn; ++__p, ++__s)
1218 *__s = (wchar_t)*__p;
1219 __nb = __nn;
1220 }
1221 return __s;
1222 }
1223};
1224
1225template <>
1226struct __widen_from_utf8<32>
1227 : public codecvt<char32_t, char, mbstate_t>
1228{
1229 _LIBCPP_ALWAYS_INLINE
1230 __widen_from_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
1231
1232 ~__widen_from_utf8();
1233
1234 template <class _OutputIterator>
1235 _LIBCPP_ALWAYS_INLINE
1236 _OutputIterator
1237 operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
1238 {
1239 result __r = ok;
1240 mbstate_t __mb;
1241 while (__nb < __ne && __r != error)
1242 {
1243 const int __sz = 32;
1244 char32_t __buf[__sz];
1245 char32_t* __bn;
1246 const char* __nn = __nb;
1247 __r = do_in(__mb, __nb, __ne - __nb > __sz ? __nb+__sz : __ne, __nn,
1248 __buf, __buf+__sz, __bn);
1249 if (__r == codecvt_base::error || __nn == __nb)
1250 __throw_runtime_error("locale not supported");
1251 for (const char32_t* __p = __buf; __p < __bn; ++__p, ++__s)
1252 *__s = (wchar_t)*__p;
1253 __nb = __nn;
1254 }
1255 return __s;
1256 }
1257};
1258
1259// template <class charT> class numpunct
1260
1261template <class _CharT> class numpunct;
1262
1263template <>
1264class numpunct<char>
1265 : public locale::facet
1266{
1267public:
1268 typedef char char_type;
1269 typedef basic_string<char_type> string_type;
1270
1271 explicit numpunct(size_t __refs = 0);
1272
1273 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
1274 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
1275 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
1276 _LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();}
1277 _LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();}
1278
1279 static locale::id id;
1280
1281protected:
1282 ~numpunct();
1283 virtual char_type do_decimal_point() const;
1284 virtual char_type do_thousands_sep() const;
1285 virtual string do_grouping() const;
1286 virtual string_type do_truename() const;
1287 virtual string_type do_falsename() const;
1288
1289 char_type __decimal_point_;
1290 char_type __thousands_sep_;
1291 string __grouping_;
1292};
1293
1294template <>
1295class numpunct<wchar_t>
1296 : public locale::facet
1297{
1298public:
1299 typedef wchar_t char_type;
1300 typedef basic_string<char_type> string_type;
1301
1302 explicit numpunct(size_t __refs = 0);
1303
1304 _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();}
1305 _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();}
1306 _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();}
1307 _LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();}
1308 _LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();}
1309
1310 static locale::id id;
1311
1312protected:
1313 ~numpunct();
1314 virtual char_type do_decimal_point() const;
1315 virtual char_type do_thousands_sep() const;
1316 virtual string do_grouping() const;
1317 virtual string_type do_truename() const;
1318 virtual string_type do_falsename() const;
1319
1320 char_type __decimal_point_;
1321 char_type __thousands_sep_;
1322 string __grouping_;
1323};
1324
1325// template <class charT> class numpunct_byname
1326
1327template <class charT> class numpunct_byname;
1328
1329template <>
1330class numpunct_byname<char>
1331: public numpunct<char>
1332{
1333public:
1334 typedef char char_type;
1335 typedef basic_string<char_type> string_type;
1336
1337 explicit numpunct_byname(const char* __nm, size_t __refs = 0);
1338 explicit numpunct_byname(const string& __nm, size_t __refs = 0);
1339
1340protected:
1341 ~numpunct_byname();
1342
1343private:
1344 void __init(const char*);
1345};
1346
1347template <>
1348class numpunct_byname<wchar_t>
1349: public numpunct<wchar_t>
1350{
1351public:
1352 typedef wchar_t char_type;
1353 typedef basic_string<char_type> string_type;
1354
1355 explicit numpunct_byname(const char* __nm, size_t __refs = 0);
1356 explicit numpunct_byname(const string& __nm, size_t __refs = 0);
1357
1358protected:
1359 ~numpunct_byname();
1360
1361private:
1362 void __init(const char*);
1363};
1364
1365_LIBCPP_END_NAMESPACE_STD
1366
1367#endif // _LIBCPP___LOCALE