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