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