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