1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___LOCALE
11#define _LIBCPP___LOCALE
12
13#include <__availability>
14#include <__config>
15#include <cctype>
16#include <cstdint>
17#include <locale.h>
18#include <memory>
19#include <mutex>
20#include <string>
21
22#include <utility> // TODO: Remove this
23
24#if defined(_LIBCPP_MSVCRT_LIKE)
25# include <__support/win32/locale_win32.h>
26# include <cstring>
27#elif defined(_AIX) || defined(__MVS__)
28# include <__support/ibm/xlocale.h>
29#elif defined(__ANDROID__)
30# include <__support/android/locale_bionic.h>
31#elif defined(__sun__)
32# include <__support/solaris/xlocale.h>
33# include <xlocale.h>
34#elif defined(_NEWLIB_VERSION)
35# include <__support/newlib/xlocale.h>
36#elif defined(__OpenBSD__)
37# include <__support/openbsd/xlocale.h>
38#elif (defined(__APPLE__)      || defined(__FreeBSD__) \
39    || defined(__EMSCRIPTEN__) || defined(__IBMCPP__))
40# include <xlocale.h>
41#elif defined(__Fuchsia__)
42# include <__support/fuchsia/xlocale.h>
43#elif defined(__wasi__)
44// WASI libc uses musl's locales support.
45# include <__support/musl/xlocale.h>
46#elif defined(_LIBCPP_HAS_MUSL_LIBC)
47# include <__support/musl/xlocale.h>
48#endif
49
50#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
51#  pragma GCC system_header
52#endif
53
54_LIBCPP_BEGIN_NAMESPACE_STD
55
56#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS)
57struct __libcpp_locale_guard {
58  _LIBCPP_INLINE_VISIBILITY
59  __libcpp_locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {}
60
61  _LIBCPP_INLINE_VISIBILITY
62  ~__libcpp_locale_guard() {
63    if (__old_loc_)
64      uselocale(__old_loc_);
65  }
66
67  locale_t __old_loc_;
68private:
69  __libcpp_locale_guard(__libcpp_locale_guard const&);
70  __libcpp_locale_guard& operator=(__libcpp_locale_guard const&);
71};
72#elif defined(_LIBCPP_MSVCRT_LIKE)
73struct __libcpp_locale_guard {
74    __libcpp_locale_guard(locale_t __l) :
75        __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) {
76      // Setting the locale can be expensive even when the locale given is
77      // already the current locale, so do an explicit check to see if the
78      // current locale is already the one we want.
79      const char* __lc = __setlocale(nullptr);
80      // If every category is the same, the locale string will simply be the
81      // locale name, otherwise it will be a semicolon-separated string listing
82      // each category.  In the second case, we know at least one category won't
83      // be what we want, so we only have to check the first case.
84      if (_VSTD::strcmp(__l.__get_locale(), __lc) != 0) {
85        __locale_all = _strdup(__lc);
86        if (__locale_all == nullptr)
87          __throw_bad_alloc();
88        __setlocale(__l.__get_locale());
89      }
90    }
91    ~__libcpp_locale_guard() {
92      // The CRT documentation doesn't explicitly say, but setlocale() does the
93      // right thing when given a semicolon-separated list of locale settings
94      // for the different categories in the same format as returned by
95      // setlocale(LC_ALL, nullptr).
96      if (__locale_all != nullptr) {
97        __setlocale(__locale_all);
98        free(__locale_all);
99      }
100      _configthreadlocale(__status);
101    }
102    static const char* __setlocale(const char* __locale) {
103      const char* __new_locale = setlocale(LC_ALL, __locale);
104      if (__new_locale == nullptr)
105        __throw_bad_alloc();
106      return __new_locale;
107    }
108    int __status;
109    char* __locale_all = nullptr;
110};
111#endif
112
113class _LIBCPP_TYPE_VIS locale;
114
115template <class _Facet>
116_LIBCPP_INLINE_VISIBILITY
117bool
118has_facet(const locale&) _NOEXCEPT;
119
120template <class _Facet>
121_LIBCPP_INLINE_VISIBILITY
122const _Facet&
123use_facet(const locale&);
124
125class _LIBCPP_TYPE_VIS locale
126{
127public:
128    // types:
129    class _LIBCPP_TYPE_VIS facet;
130    class _LIBCPP_TYPE_VIS id;
131
132    typedef int category;
133    _LIBCPP_AVAILABILITY_LOCALE_CATEGORY
134    static const category // values assigned here are for exposition only
135        none     = 0,
136        collate  = LC_COLLATE_MASK,
137        ctype    = LC_CTYPE_MASK,
138        monetary = LC_MONETARY_MASK,
139        numeric  = LC_NUMERIC_MASK,
140        time     = LC_TIME_MASK,
141        messages = LC_MESSAGES_MASK,
142        all = collate | ctype | monetary | numeric | time | messages;
143
144    // construct/copy/destroy:
145    locale()  _NOEXCEPT;
146    locale(const locale&)  _NOEXCEPT;
147    explicit locale(const char*);
148    explicit locale(const string&);
149    locale(const locale&, const char*, category);
150    locale(const locale&, const string&, category);
151    template <class _Facet>
152        _LIBCPP_INLINE_VISIBILITY locale(const locale&, _Facet*);
153    locale(const locale&, const locale&, category);
154
155    ~locale();
156
157    const locale& operator=(const locale&)  _NOEXCEPT;
158
159    template <class _Facet>
160      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
161      locale combine(const locale&) const;
162
163    // locale operations:
164    string name() const;
165    bool operator==(const locale&) const;
166    bool operator!=(const locale& __y) const {return !(*this == __y);}
167    template <class _CharT, class _Traits, class _Allocator>
168      _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
169      bool operator()(const basic_string<_CharT, _Traits, _Allocator>&,
170                      const basic_string<_CharT, _Traits, _Allocator>&) const;
171
172    // global locale objects:
173    static locale global(const locale&);
174    static const locale& classic();
175
176private:
177    class __imp;
178    __imp* __locale_;
179
180    void __install_ctor(const locale&, facet*, long);
181    static locale& __global();
182    bool has_facet(id&) const;
183    const facet* use_facet(id&) const;
184
185    template <class _Facet> friend bool has_facet(const locale&)  _NOEXCEPT;
186    template <class _Facet> friend const _Facet& use_facet(const locale&);
187};
188
189class _LIBCPP_TYPE_VIS locale::facet
190    : public __shared_count
191{
192protected:
193    _LIBCPP_INLINE_VISIBILITY
194    explicit facet(size_t __refs = 0)
195        : __shared_count(static_cast<long>(__refs)-1) {}
196
197    virtual ~facet();
198
199//    facet(const facet&) = delete;     // effectively done in __shared_count
200//    void operator=(const facet&) = delete;
201private:
202    virtual void __on_zero_shared() _NOEXCEPT;
203};
204
205class _LIBCPP_TYPE_VIS locale::id
206{
207    once_flag      __flag_;
208    int32_t        __id_;
209
210    static int32_t __next_id;
211public:
212    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR id() :__id_(0) {}
213    void operator=(const id&) = delete;
214    id(const id&) = delete;
215
216private:
217    void __init();
218public:  // only needed for tests
219    long __get();
220
221    friend class locale;
222    friend class locale::__imp;
223};
224
225template <class _Facet>
226inline _LIBCPP_INLINE_VISIBILITY
227locale::locale(const locale& __other, _Facet* __f)
228{
229    __install_ctor(__other, __f, __f ? __f->id.__get() : 0);
230}
231
232template <class _Facet>
233locale
234locale::combine(const locale& __other) const
235{
236    if (!_VSTD::has_facet<_Facet>(__other))
237        __throw_runtime_error("locale::combine: locale missing facet");
238
239    return locale(*this, &const_cast<_Facet&>(_VSTD::use_facet<_Facet>(__other)));
240}
241
242template <class _Facet>
243inline _LIBCPP_INLINE_VISIBILITY
244bool
245has_facet(const locale& __l)  _NOEXCEPT
246{
247    return __l.has_facet(_Facet::id);
248}
249
250template <class _Facet>
251inline _LIBCPP_INLINE_VISIBILITY
252const _Facet&
253use_facet(const locale& __l)
254{
255    return static_cast<const _Facet&>(*__l.use_facet(_Facet::id));
256}
257
258// template <class _CharT> class collate;
259
260template <class _CharT>
261class _LIBCPP_TEMPLATE_VIS collate
262    : public locale::facet
263{
264public:
265    typedef _CharT char_type;
266    typedef basic_string<char_type> string_type;
267
268    _LIBCPP_INLINE_VISIBILITY
269    explicit collate(size_t __refs = 0)
270        : locale::facet(__refs) {}
271
272    _LIBCPP_INLINE_VISIBILITY
273    int compare(const char_type* __lo1, const char_type* __hi1,
274                const char_type* __lo2, const char_type* __hi2) const
275    {
276        return do_compare(__lo1, __hi1, __lo2, __hi2);
277    }
278
279    // FIXME(EricWF): The _LIBCPP_ALWAYS_INLINE is needed on Windows to work
280    // around a dllimport bug that expects an external instantiation.
281    _LIBCPP_INLINE_VISIBILITY
282    _LIBCPP_ALWAYS_INLINE
283    string_type transform(const char_type* __lo, const char_type* __hi) const
284    {
285        return do_transform(__lo, __hi);
286    }
287
288    _LIBCPP_INLINE_VISIBILITY
289    long hash(const char_type* __lo, const char_type* __hi) const
290    {
291        return do_hash(__lo, __hi);
292    }
293
294    static locale::id id;
295
296protected:
297    ~collate();
298    virtual int do_compare(const char_type* __lo1, const char_type* __hi1,
299                           const char_type* __lo2, const char_type* __hi2) const;
300    virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const
301        {return string_type(__lo, __hi);}
302    virtual long do_hash(const char_type* __lo, const char_type* __hi) const;
303};
304
305template <class _CharT> locale::id collate<_CharT>::id;
306
307template <class _CharT>
308collate<_CharT>::~collate()
309{
310}
311
312template <class _CharT>
313int
314collate<_CharT>::do_compare(const char_type* __lo1, const char_type* __hi1,
315                            const char_type* __lo2, const char_type* __hi2) const
316{
317    for (; __lo2 != __hi2; ++__lo1, ++__lo2)
318    {
319        if (__lo1 == __hi1 || *__lo1 < *__lo2)
320            return -1;
321        if (*__lo2 < *__lo1)
322            return 1;
323    }
324    return __lo1 != __hi1;
325}
326
327template <class _CharT>
328long
329collate<_CharT>::do_hash(const char_type* __lo, const char_type* __hi) const
330{
331    size_t __h = 0;
332    const size_t __sr = __CHAR_BIT__ * sizeof(size_t) - 8;
333    const size_t __mask = size_t(0xF) << (__sr + 4);
334    for(const char_type* __p = __lo; __p != __hi; ++__p)
335    {
336        __h = (__h << 4) + static_cast<size_t>(*__p);
337        size_t __g = __h & __mask;
338        __h ^= __g | (__g >> __sr);
339    }
340    return static_cast<long>(__h);
341}
342
343_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate<char>)
344#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
345_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate<wchar_t>)
346#endif
347
348// template <class CharT> class collate_byname;
349
350template <class _CharT> class _LIBCPP_TEMPLATE_VIS collate_byname;
351
352template <>
353class _LIBCPP_TYPE_VIS collate_byname<char>
354    : public collate<char>
355{
356    locale_t __l;
357public:
358    typedef char char_type;
359    typedef basic_string<char_type> string_type;
360
361    explicit collate_byname(const char* __n, size_t __refs = 0);
362    explicit collate_byname(const string& __n, size_t __refs = 0);
363
364protected:
365    ~collate_byname();
366    virtual int do_compare(const char_type* __lo1, const char_type* __hi1,
367                           const char_type* __lo2, const char_type* __hi2) const;
368    virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const;
369};
370
371#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
372template <>
373class _LIBCPP_TYPE_VIS collate_byname<wchar_t>
374    : public collate<wchar_t>
375{
376    locale_t __l;
377public:
378    typedef wchar_t char_type;
379    typedef basic_string<char_type> string_type;
380
381    explicit collate_byname(const char* __n, size_t __refs = 0);
382    explicit collate_byname(const string& __n, size_t __refs = 0);
383
384protected:
385    ~collate_byname();
386
387    virtual int do_compare(const char_type* __lo1, const char_type* __hi1,
388                           const char_type* __lo2, const char_type* __hi2) const;
389    virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const;
390};
391#endif
392
393template <class _CharT, class _Traits, class _Allocator>
394bool
395locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x,
396                   const basic_string<_CharT, _Traits, _Allocator>& __y) const
397{
398    return _VSTD::use_facet<_VSTD::collate<_CharT> >(*this).compare(
399                                       __x.data(), __x.data() + __x.size(),
400                                       __y.data(), __y.data() + __y.size()) < 0;
401}
402
403// template <class charT> class ctype
404
405class _LIBCPP_TYPE_VIS ctype_base
406{
407public:
408#if defined(_LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE)
409    typedef unsigned long mask;
410    static const mask space  = 1<<0;
411    static const mask print  = 1<<1;
412    static const mask cntrl  = 1<<2;
413    static const mask upper  = 1<<3;
414    static const mask lower  = 1<<4;
415    static const mask alpha  = 1<<5;
416    static const mask digit  = 1<<6;
417    static const mask punct  = 1<<7;
418    static const mask xdigit = 1<<8;
419    static const mask blank  = 1<<9;
420#if defined(__BIONIC__)
421    // Historically this was a part of regex_traits rather than ctype_base. The
422    // historical value of the constant is preserved for ABI compatibility.
423    static const mask __regex_word = 0x8000;
424#else
425    static const mask __regex_word = 1<<10;
426#endif // defined(__BIONIC__)
427#elif defined(__GLIBC__)
428    typedef unsigned short mask;
429    static const mask space  = _ISspace;
430    static const mask print  = _ISprint;
431    static const mask cntrl  = _IScntrl;
432    static const mask upper  = _ISupper;
433    static const mask lower  = _ISlower;
434    static const mask alpha  = _ISalpha;
435    static const mask digit  = _ISdigit;
436    static const mask punct  = _ISpunct;
437    static const mask xdigit = _ISxdigit;
438    static const mask blank  = _ISblank;
439#if defined(__mips__)
440    static const mask __regex_word = static_cast<mask>(_ISbit(15));
441#else
442    static const mask __regex_word = 0x80;
443#endif
444#elif defined(_LIBCPP_MSVCRT_LIKE)
445    typedef unsigned short mask;
446    static const mask space  = _SPACE;
447    static const mask print  = _BLANK|_PUNCT|_ALPHA|_DIGIT;
448    static const mask cntrl  = _CONTROL;
449    static const mask upper  = _UPPER;
450    static const mask lower  = _LOWER;
451    static const mask alpha  = _ALPHA;
452    static const mask digit  = _DIGIT;
453    static const mask punct  = _PUNCT;
454    static const mask xdigit = _HEX;
455    static const mask blank  = _BLANK;
456    static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used
457# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
458# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
459#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
460# ifdef __APPLE__
461    typedef __uint32_t mask;
462# elif defined(__FreeBSD__)
463    typedef unsigned long mask;
464# elif defined(__EMSCRIPTEN__) || defined(__NetBSD__)
465    typedef unsigned short mask;
466# endif
467    static const mask space  = _CTYPE_S;
468    static const mask print  = _CTYPE_R;
469    static const mask cntrl  = _CTYPE_C;
470    static const mask upper  = _CTYPE_U;
471    static const mask lower  = _CTYPE_L;
472    static const mask alpha  = _CTYPE_A;
473    static const mask digit  = _CTYPE_D;
474    static const mask punct  = _CTYPE_P;
475    static const mask xdigit = _CTYPE_X;
476
477# if defined(__NetBSD__)
478    static const mask blank  = _CTYPE_BL;
479    // NetBSD defines classes up to 0x2000
480    // see sys/ctype_bits.h, _CTYPE_Q
481    static const mask __regex_word = 0x8000;
482# else
483    static const mask blank  = _CTYPE_B;
484    static const mask __regex_word = 0x80;
485# endif
486#elif defined(__sun__) || defined(_AIX)
487    typedef unsigned int mask;
488    static const mask space  = _ISSPACE;
489    static const mask print  = _ISPRINT;
490    static const mask cntrl  = _ISCNTRL;
491    static const mask upper  = _ISUPPER;
492    static const mask lower  = _ISLOWER;
493    static const mask alpha  = _ISALPHA;
494    static const mask digit  = _ISDIGIT;
495    static const mask punct  = _ISPUNCT;
496    static const mask xdigit = _ISXDIGIT;
497    static const mask blank  = _ISBLANK;
498    static const mask __regex_word = 0x80;
499#elif defined(_NEWLIB_VERSION)
500    // Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h.
501    typedef char mask;
502    static const mask space  = _S;
503    static const mask print  = _P | _U | _L | _N | _B;
504    static const mask cntrl  = _C;
505    static const mask upper  = _U;
506    static const mask lower  = _L;
507    static const mask alpha  = _U | _L;
508    static const mask digit  = _N;
509    static const mask punct  = _P;
510    static const mask xdigit = _X | _N;
511    static const mask blank  = _B;
512    static const mask __regex_word = 0x80;
513# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
514# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
515# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
516#elif defined(__MVS__)
517# if defined(__NATIVE_ASCII_F)
518    typedef unsigned int mask;
519    static const mask space  = _ISSPACE_A;
520    static const mask print  = _ISPRINT_A;
521    static const mask cntrl  = _ISCNTRL_A;
522    static const mask upper  = _ISUPPER_A;
523    static const mask lower  = _ISLOWER_A;
524    static const mask alpha  = _ISALPHA_A;
525    static const mask digit  = _ISDIGIT_A;
526    static const mask punct  = _ISPUNCT_A;
527    static const mask xdigit = _ISXDIGIT_A;
528    static const mask blank  = _ISBLANK_A;
529# else
530    typedef unsigned short mask;
531    static const mask space  = __ISSPACE;
532    static const mask print  = __ISPRINT;
533    static const mask cntrl  = __ISCNTRL;
534    static const mask upper  = __ISUPPER;
535    static const mask lower  = __ISLOWER;
536    static const mask alpha  = __ISALPHA;
537    static const mask digit  = __ISDIGIT;
538    static const mask punct  = __ISPUNCT;
539    static const mask xdigit = __ISXDIGIT;
540    static const mask blank  = __ISBLANK;
541# endif
542    static const mask __regex_word = 0x8000;
543#else
544# error unknown rune table for this platform -- do you mean to define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE?
545#endif
546    static const mask alnum  = alpha | digit;
547    static const mask graph  = alnum | punct;
548
549    _LIBCPP_INLINE_VISIBILITY ctype_base() {}
550
551// TODO: Remove the ifndef when the assert no longer fails on AIX.
552#ifndef _AIX
553    static_assert((__regex_word & ~(space | print | cntrl | upper | lower | alpha | digit | punct | xdigit | blank)) == __regex_word,
554                  "__regex_word can't overlap other bits");
555#endif
556};
557
558template <class _CharT> class _LIBCPP_TEMPLATE_VIS ctype;
559
560#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
561template <>
562class _LIBCPP_TYPE_VIS ctype<wchar_t>
563    : public locale::facet,
564      public ctype_base
565{
566public:
567    typedef wchar_t char_type;
568
569    _LIBCPP_INLINE_VISIBILITY
570    explicit ctype(size_t __refs = 0)
571        : locale::facet(__refs) {}
572
573    _LIBCPP_INLINE_VISIBILITY
574    bool is(mask __m, char_type __c) const
575    {
576        return do_is(__m, __c);
577    }
578
579    _LIBCPP_INLINE_VISIBILITY
580    const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const
581    {
582        return do_is(__low, __high, __vec);
583    }
584
585    _LIBCPP_INLINE_VISIBILITY
586    const char_type* scan_is(mask __m, const char_type* __low, const char_type* __high) const
587    {
588        return do_scan_is(__m, __low, __high);
589    }
590
591    _LIBCPP_INLINE_VISIBILITY
592    const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const
593    {
594        return do_scan_not(__m, __low, __high);
595    }
596
597    _LIBCPP_INLINE_VISIBILITY
598    char_type toupper(char_type __c) const
599    {
600        return do_toupper(__c);
601    }
602
603    _LIBCPP_INLINE_VISIBILITY
604    const char_type* toupper(char_type* __low, const char_type* __high) const
605    {
606        return do_toupper(__low, __high);
607    }
608
609    _LIBCPP_INLINE_VISIBILITY
610    char_type tolower(char_type __c) const
611    {
612        return do_tolower(__c);
613    }
614
615    _LIBCPP_INLINE_VISIBILITY
616    const char_type* tolower(char_type* __low, const char_type* __high) const
617    {
618        return do_tolower(__low, __high);
619    }
620
621    _LIBCPP_INLINE_VISIBILITY
622    char_type widen(char __c) const
623    {
624        return do_widen(__c);
625    }
626
627    _LIBCPP_INLINE_VISIBILITY
628    const char* widen(const char* __low, const char* __high, char_type* __to) const
629    {
630        return do_widen(__low, __high, __to);
631    }
632
633    _LIBCPP_INLINE_VISIBILITY
634    char narrow(char_type __c, char __dfault) const
635    {
636        return do_narrow(__c, __dfault);
637    }
638
639    _LIBCPP_INLINE_VISIBILITY
640    const char_type* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const
641    {
642        return do_narrow(__low, __high, __dfault, __to);
643    }
644
645    static locale::id id;
646
647protected:
648    ~ctype();
649    virtual bool do_is(mask __m, char_type __c) const;
650    virtual const char_type* do_is(const char_type* __low, const char_type* __high, mask* __vec) const;
651    virtual const char_type* do_scan_is(mask __m, const char_type* __low, const char_type* __high) const;
652    virtual const char_type* do_scan_not(mask __m, const char_type* __low, const char_type* __high) const;
653    virtual char_type do_toupper(char_type) const;
654    virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
655    virtual char_type do_tolower(char_type) const;
656    virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
657    virtual char_type do_widen(char) const;
658    virtual const char* do_widen(const char* __low, const char* __high, char_type* __dest) const;
659    virtual char do_narrow(char_type, char __dfault) const;
660    virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const;
661};
662#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
663
664template <>
665class _LIBCPP_TYPE_VIS ctype<char>
666    : public locale::facet, public ctype_base
667{
668    const mask* __tab_;
669    bool        __del_;
670public:
671    typedef char char_type;
672
673    explicit ctype(const mask* __tab = nullptr, bool __del = false, size_t __refs = 0);
674
675    _LIBCPP_INLINE_VISIBILITY
676    bool is(mask __m, char_type __c) const
677    {
678        return isascii(__c) ? (__tab_[static_cast<int>(__c)] & __m) !=0 : false;
679    }
680
681    _LIBCPP_INLINE_VISIBILITY
682    const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const
683    {
684        for (; __low != __high; ++__low, ++__vec)
685            *__vec = isascii(*__low) ? __tab_[static_cast<int>(*__low)] : 0;
686        return __low;
687    }
688
689    _LIBCPP_INLINE_VISIBILITY
690    const char_type* scan_is (mask __m, const char_type* __low, const char_type* __high) const
691    {
692        for (; __low != __high; ++__low)
693            if (isascii(*__low) && (__tab_[static_cast<int>(*__low)] & __m))
694                break;
695        return __low;
696    }
697
698    _LIBCPP_INLINE_VISIBILITY
699    const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const
700    {
701        for (; __low != __high; ++__low)
702            if (!(isascii(*__low) && (__tab_[static_cast<int>(*__low)] & __m)))
703                break;
704        return __low;
705    }
706
707    _LIBCPP_INLINE_VISIBILITY
708    char_type toupper(char_type __c) const
709    {
710        return do_toupper(__c);
711    }
712
713    _LIBCPP_INLINE_VISIBILITY
714    const char_type* toupper(char_type* __low, const char_type* __high) const
715    {
716        return do_toupper(__low, __high);
717    }
718
719    _LIBCPP_INLINE_VISIBILITY
720    char_type tolower(char_type __c) const
721    {
722        return do_tolower(__c);
723    }
724
725    _LIBCPP_INLINE_VISIBILITY
726    const char_type* tolower(char_type* __low, const char_type* __high) const
727    {
728        return do_tolower(__low, __high);
729    }
730
731    _LIBCPP_INLINE_VISIBILITY
732    char_type widen(char __c) const
733    {
734        return do_widen(__c);
735    }
736
737    _LIBCPP_INLINE_VISIBILITY
738    const char* widen(const char* __low, const char* __high, char_type* __to) const
739    {
740        return do_widen(__low, __high, __to);
741    }
742
743    _LIBCPP_INLINE_VISIBILITY
744    char narrow(char_type __c, char __dfault) const
745    {
746        return do_narrow(__c, __dfault);
747    }
748
749    _LIBCPP_INLINE_VISIBILITY
750    const char* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const
751    {
752        return do_narrow(__low, __high, __dfault, __to);
753    }
754
755    static locale::id id;
756
757#ifdef _CACHED_RUNES
758    static const size_t table_size = _CACHED_RUNES;
759#else
760    static const size_t table_size = 256;  // FIXME: Don't hardcode this.
761#endif
762    _LIBCPP_INLINE_VISIBILITY const mask* table() const  _NOEXCEPT {return __tab_;}
763    static const mask* classic_table()  _NOEXCEPT;
764#if defined(__GLIBC__) || defined(__EMSCRIPTEN__)
765    static const int* __classic_upper_table() _NOEXCEPT;
766    static const int* __classic_lower_table() _NOEXCEPT;
767#endif
768#if defined(__NetBSD__)
769    static const short* __classic_upper_table() _NOEXCEPT;
770    static const short* __classic_lower_table() _NOEXCEPT;
771#endif
772#if defined(__MVS__)
773    static const unsigned short* __classic_upper_table() _NOEXCEPT;
774    static const unsigned short* __classic_lower_table() _NOEXCEPT;
775#endif
776
777protected:
778    ~ctype();
779    virtual char_type do_toupper(char_type __c) const;
780    virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
781    virtual char_type do_tolower(char_type __c) const;
782    virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
783    virtual char_type do_widen(char __c) const;
784    virtual const char* do_widen(const char* __low, const char* __high, char_type* __to) const;
785    virtual char do_narrow(char_type __c, char __dfault) const;
786    virtual const char* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const;
787};
788
789// template <class CharT> class ctype_byname;
790
791template <class _CharT> class _LIBCPP_TEMPLATE_VIS ctype_byname;
792
793template <>
794class _LIBCPP_TYPE_VIS ctype_byname<char>
795    : public ctype<char>
796{
797    locale_t __l;
798
799public:
800    explicit ctype_byname(const char*, size_t = 0);
801    explicit ctype_byname(const string&, size_t = 0);
802
803protected:
804    ~ctype_byname();
805    virtual char_type do_toupper(char_type) const;
806    virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
807    virtual char_type do_tolower(char_type) const;
808    virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
809};
810
811#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
812template <>
813class _LIBCPP_TYPE_VIS ctype_byname<wchar_t>
814    : public ctype<wchar_t>
815{
816    locale_t __l;
817
818public:
819    explicit ctype_byname(const char*, size_t = 0);
820    explicit ctype_byname(const string&, size_t = 0);
821
822protected:
823    ~ctype_byname();
824    virtual bool do_is(mask __m, char_type __c) const;
825    virtual const char_type* do_is(const char_type* __low, const char_type* __high, mask* __vec) const;
826    virtual const char_type* do_scan_is(mask __m, const char_type* __low, const char_type* __high) const;
827    virtual const char_type* do_scan_not(mask __m, const char_type* __low, const char_type* __high) const;
828    virtual char_type do_toupper(char_type) const;
829    virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
830    virtual char_type do_tolower(char_type) const;
831    virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
832    virtual char_type do_widen(char) const;
833    virtual const char* do_widen(const char* __low, const char* __high, char_type* __dest) const;
834    virtual char do_narrow(char_type, char __dfault) const;
835    virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const;
836};
837#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
838
839template <class _CharT>
840inline _LIBCPP_INLINE_VISIBILITY
841bool
842isspace(_CharT __c, const locale& __loc)
843{
844    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::space, __c);
845}
846
847template <class _CharT>
848inline _LIBCPP_INLINE_VISIBILITY
849bool
850isprint(_CharT __c, const locale& __loc)
851{
852    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::print, __c);
853}
854
855template <class _CharT>
856inline _LIBCPP_INLINE_VISIBILITY
857bool
858iscntrl(_CharT __c, const locale& __loc)
859{
860    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::cntrl, __c);
861}
862
863template <class _CharT>
864inline _LIBCPP_INLINE_VISIBILITY
865bool
866isupper(_CharT __c, const locale& __loc)
867{
868    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::upper, __c);
869}
870
871template <class _CharT>
872inline _LIBCPP_INLINE_VISIBILITY
873bool
874islower(_CharT __c, const locale& __loc)
875{
876    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::lower, __c);
877}
878
879template <class _CharT>
880inline _LIBCPP_INLINE_VISIBILITY
881bool
882isalpha(_CharT __c, const locale& __loc)
883{
884    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alpha, __c);
885}
886
887template <class _CharT>
888inline _LIBCPP_INLINE_VISIBILITY
889bool
890isdigit(_CharT __c, const locale& __loc)
891{
892    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::digit, __c);
893}
894
895template <class _CharT>
896inline _LIBCPP_INLINE_VISIBILITY
897bool
898ispunct(_CharT __c, const locale& __loc)
899{
900    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::punct, __c);
901}
902
903template <class _CharT>
904inline _LIBCPP_INLINE_VISIBILITY
905bool
906isxdigit(_CharT __c, const locale& __loc)
907{
908    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::xdigit, __c);
909}
910
911template <class _CharT>
912inline _LIBCPP_INLINE_VISIBILITY
913bool
914isalnum(_CharT __c, const locale& __loc)
915{
916    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alnum, __c);
917}
918
919template <class _CharT>
920inline _LIBCPP_INLINE_VISIBILITY
921bool
922isgraph(_CharT __c, const locale& __loc)
923{
924    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::graph, __c);
925}
926
927template <class _CharT>
928inline _LIBCPP_INLINE_VISIBILITY
929_CharT
930toupper(_CharT __c, const locale& __loc)
931{
932    return use_facet<ctype<_CharT> >(__loc).toupper(__c);
933}
934
935template <class _CharT>
936inline _LIBCPP_INLINE_VISIBILITY
937_CharT
938tolower(_CharT __c, const locale& __loc)
939{
940    return use_facet<ctype<_CharT> >(__loc).tolower(__c);
941}
942
943// codecvt_base
944
945class _LIBCPP_TYPE_VIS codecvt_base
946{
947public:
948    _LIBCPP_INLINE_VISIBILITY codecvt_base() {}
949    enum result {ok, partial, error, noconv};
950};
951
952// template <class internT, class externT, class stateT> class codecvt;
953
954template <class _InternT, class _ExternT, class _StateT> class _LIBCPP_TEMPLATE_VIS codecvt;
955
956// template <> class codecvt<char, char, mbstate_t>
957
958template <>
959class _LIBCPP_TYPE_VIS codecvt<char, char, mbstate_t>
960    : public locale::facet,
961      public codecvt_base
962{
963public:
964    typedef char      intern_type;
965    typedef char      extern_type;
966    typedef mbstate_t state_type;
967
968    _LIBCPP_INLINE_VISIBILITY
969    explicit codecvt(size_t __refs = 0)
970        : locale::facet(__refs) {}
971
972    _LIBCPP_INLINE_VISIBILITY
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_INLINE_VISIBILITY
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_INLINE_VISIBILITY
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_INLINE_VISIBILITY
996    int encoding() const  _NOEXCEPT
997    {
998        return do_encoding();
999    }
1000
1001    _LIBCPP_INLINE_VISIBILITY
1002    bool always_noconv() const  _NOEXCEPT
1003    {
1004        return do_always_noconv();
1005    }
1006
1007    _LIBCPP_INLINE_VISIBILITY
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_INLINE_VISIBILITY
1014    int max_length() const  _NOEXCEPT
1015    {
1016        return do_max_length();
1017    }
1018
1019    static locale::id id;
1020
1021protected:
1022    _LIBCPP_INLINE_VISIBILITY
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& __st, 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<wchar_t, char, mbstate_t>
1043
1044#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1045template <>
1046class _LIBCPP_TYPE_VIS codecvt<wchar_t, char, mbstate_t>
1047    : public locale::facet,
1048      public codecvt_base
1049{
1050    locale_t __l;
1051public:
1052    typedef wchar_t   intern_type;
1053    typedef char      extern_type;
1054    typedef mbstate_t state_type;
1055
1056    explicit codecvt(size_t __refs = 0);
1057
1058    _LIBCPP_INLINE_VISIBILITY
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_INLINE_VISIBILITY
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_INLINE_VISIBILITY
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_INLINE_VISIBILITY
1082    int encoding() const  _NOEXCEPT
1083    {
1084        return do_encoding();
1085    }
1086
1087    _LIBCPP_INLINE_VISIBILITY
1088    bool always_noconv() const  _NOEXCEPT
1089    {
1090        return do_always_noconv();
1091    }
1092
1093    _LIBCPP_INLINE_VISIBILITY
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_INLINE_VISIBILITY
1100    int max_length() const  _NOEXCEPT
1101    {
1102        return do_max_length();
1103    }
1104
1105    static locale::id id;
1106
1107protected:
1108    explicit codecvt(const char*, size_t __refs = 0);
1109
1110    ~codecvt();
1111
1112    virtual result do_out(state_type& __st,
1113                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1114                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1115    virtual result do_in(state_type& __st,
1116                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1117                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1118    virtual result do_unshift(state_type& __st,
1119                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1120    virtual int do_encoding() const  _NOEXCEPT;
1121    virtual bool do_always_noconv() const  _NOEXCEPT;
1122    virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1123    virtual int do_max_length() const  _NOEXCEPT;
1124};
1125#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1126
1127// template <> class codecvt<char16_t, char, mbstate_t> // deprecated in C++20
1128
1129template <>
1130class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_TYPE_VIS codecvt<char16_t, char, mbstate_t>
1131    : public locale::facet,
1132      public codecvt_base
1133{
1134public:
1135    typedef char16_t  intern_type;
1136    typedef char      extern_type;
1137    typedef mbstate_t state_type;
1138
1139    _LIBCPP_INLINE_VISIBILITY
1140    explicit codecvt(size_t __refs = 0)
1141        : locale::facet(__refs) {}
1142
1143    _LIBCPP_INLINE_VISIBILITY
1144    result out(state_type& __st,
1145               const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1146               extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1147    {
1148        return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1149    }
1150
1151    _LIBCPP_INLINE_VISIBILITY
1152    result unshift(state_type& __st,
1153                   extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1154    {
1155        return do_unshift(__st, __to, __to_end, __to_nxt);
1156    }
1157
1158    _LIBCPP_INLINE_VISIBILITY
1159    result in(state_type& __st,
1160              const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1161              intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
1162    {
1163        return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1164    }
1165
1166    _LIBCPP_INLINE_VISIBILITY
1167    int encoding() const  _NOEXCEPT
1168    {
1169        return do_encoding();
1170    }
1171
1172    _LIBCPP_INLINE_VISIBILITY
1173    bool always_noconv() const  _NOEXCEPT
1174    {
1175        return do_always_noconv();
1176    }
1177
1178    _LIBCPP_INLINE_VISIBILITY
1179    int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1180    {
1181        return do_length(__st, __frm, __end, __mx);
1182    }
1183
1184    _LIBCPP_INLINE_VISIBILITY
1185    int max_length() const  _NOEXCEPT
1186    {
1187        return do_max_length();
1188    }
1189
1190    static locale::id id;
1191
1192protected:
1193    _LIBCPP_INLINE_VISIBILITY
1194    explicit codecvt(const char*, size_t __refs = 0)
1195        : locale::facet(__refs) {}
1196
1197    ~codecvt();
1198
1199    virtual result do_out(state_type& __st,
1200                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1201                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1202    virtual result do_in(state_type& __st,
1203                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1204                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1205    virtual result do_unshift(state_type& __st,
1206                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1207    virtual int do_encoding() const  _NOEXCEPT;
1208    virtual bool do_always_noconv() const  _NOEXCEPT;
1209    virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1210    virtual int do_max_length() const  _NOEXCEPT;
1211};
1212
1213#ifndef _LIBCPP_HAS_NO_CHAR8_T
1214
1215// template <> class codecvt<char16_t, char8_t, mbstate_t> // C++20
1216
1217template <>
1218class _LIBCPP_TYPE_VIS codecvt<char16_t, char8_t, mbstate_t>
1219    : public locale::facet,
1220      public codecvt_base
1221{
1222public:
1223    typedef char16_t  intern_type;
1224    typedef char8_t   extern_type;
1225    typedef mbstate_t state_type;
1226
1227    _LIBCPP_INLINE_VISIBILITY
1228    explicit codecvt(size_t __refs = 0)
1229        : locale::facet(__refs) {}
1230
1231    _LIBCPP_INLINE_VISIBILITY
1232    result out(state_type& __st,
1233               const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1234               extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1235    {
1236        return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1237    }
1238
1239    _LIBCPP_INLINE_VISIBILITY
1240    result unshift(state_type& __st,
1241                   extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1242    {
1243        return do_unshift(__st, __to, __to_end, __to_nxt);
1244    }
1245
1246    _LIBCPP_INLINE_VISIBILITY
1247    result in(state_type& __st,
1248              const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1249              intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
1250    {
1251        return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1252    }
1253
1254    _LIBCPP_INLINE_VISIBILITY
1255    int encoding() const  _NOEXCEPT
1256    {
1257        return do_encoding();
1258    }
1259
1260    _LIBCPP_INLINE_VISIBILITY
1261    bool always_noconv() const  _NOEXCEPT
1262    {
1263        return do_always_noconv();
1264    }
1265
1266    _LIBCPP_INLINE_VISIBILITY
1267    int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1268    {
1269        return do_length(__st, __frm, __end, __mx);
1270    }
1271
1272    _LIBCPP_INLINE_VISIBILITY
1273    int max_length() const  _NOEXCEPT
1274    {
1275        return do_max_length();
1276    }
1277
1278    static locale::id id;
1279
1280protected:
1281    _LIBCPP_INLINE_VISIBILITY
1282    explicit codecvt(const char*, size_t __refs = 0)
1283        : locale::facet(__refs) {}
1284
1285    ~codecvt();
1286
1287    virtual result do_out(state_type& __st,
1288                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1289                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1290    virtual result do_in(state_type& __st,
1291                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1292                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1293    virtual result do_unshift(state_type& __st,
1294                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1295    virtual int do_encoding() const  _NOEXCEPT;
1296    virtual bool do_always_noconv() const  _NOEXCEPT;
1297    virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1298    virtual int do_max_length() const  _NOEXCEPT;
1299};
1300
1301#endif
1302
1303// template <> class codecvt<char32_t, char, mbstate_t> // deprecated in C++20
1304
1305template <>
1306class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_TYPE_VIS codecvt<char32_t, char, mbstate_t>
1307    : public locale::facet,
1308      public codecvt_base
1309{
1310public:
1311    typedef char32_t  intern_type;
1312    typedef char      extern_type;
1313    typedef mbstate_t state_type;
1314
1315    _LIBCPP_INLINE_VISIBILITY
1316    explicit codecvt(size_t __refs = 0)
1317        : locale::facet(__refs) {}
1318
1319    _LIBCPP_INLINE_VISIBILITY
1320    result out(state_type& __st,
1321               const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1322               extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1323    {
1324        return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1325    }
1326
1327    _LIBCPP_INLINE_VISIBILITY
1328    result unshift(state_type& __st,
1329                   extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1330    {
1331        return do_unshift(__st, __to, __to_end, __to_nxt);
1332    }
1333
1334    _LIBCPP_INLINE_VISIBILITY
1335    result in(state_type& __st,
1336              const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1337              intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
1338    {
1339        return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1340    }
1341
1342    _LIBCPP_INLINE_VISIBILITY
1343    int encoding() const  _NOEXCEPT
1344    {
1345        return do_encoding();
1346    }
1347
1348    _LIBCPP_INLINE_VISIBILITY
1349    bool always_noconv() const  _NOEXCEPT
1350    {
1351        return do_always_noconv();
1352    }
1353
1354    _LIBCPP_INLINE_VISIBILITY
1355    int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1356    {
1357        return do_length(__st, __frm, __end, __mx);
1358    }
1359
1360    _LIBCPP_INLINE_VISIBILITY
1361    int max_length() const  _NOEXCEPT
1362    {
1363        return do_max_length();
1364    }
1365
1366    static locale::id id;
1367
1368protected:
1369    _LIBCPP_INLINE_VISIBILITY
1370    explicit codecvt(const char*, size_t __refs = 0)
1371        : locale::facet(__refs) {}
1372
1373    ~codecvt();
1374
1375    virtual result do_out(state_type& __st,
1376                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1377                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1378    virtual result do_in(state_type& __st,
1379                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1380                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1381    virtual result do_unshift(state_type& __st,
1382                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1383    virtual int do_encoding() const  _NOEXCEPT;
1384    virtual bool do_always_noconv() const  _NOEXCEPT;
1385    virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1386    virtual int do_max_length() const  _NOEXCEPT;
1387};
1388
1389#ifndef _LIBCPP_HAS_NO_CHAR8_T
1390
1391// template <> class codecvt<char32_t, char8_t, mbstate_t> // C++20
1392
1393template <>
1394class _LIBCPP_TYPE_VIS codecvt<char32_t, char8_t, mbstate_t>
1395    : public locale::facet,
1396      public codecvt_base
1397{
1398public:
1399    typedef char32_t  intern_type;
1400    typedef char8_t   extern_type;
1401    typedef mbstate_t state_type;
1402
1403    _LIBCPP_INLINE_VISIBILITY
1404    explicit codecvt(size_t __refs = 0)
1405        : locale::facet(__refs) {}
1406
1407    _LIBCPP_INLINE_VISIBILITY
1408    result out(state_type& __st,
1409               const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1410               extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1411    {
1412        return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1413    }
1414
1415    _LIBCPP_INLINE_VISIBILITY
1416    result unshift(state_type& __st,
1417                   extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1418    {
1419        return do_unshift(__st, __to, __to_end, __to_nxt);
1420    }
1421
1422    _LIBCPP_INLINE_VISIBILITY
1423    result in(state_type& __st,
1424              const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1425              intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
1426    {
1427        return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1428    }
1429
1430    _LIBCPP_INLINE_VISIBILITY
1431    int encoding() const  _NOEXCEPT
1432    {
1433        return do_encoding();
1434    }
1435
1436    _LIBCPP_INLINE_VISIBILITY
1437    bool always_noconv() const  _NOEXCEPT
1438    {
1439        return do_always_noconv();
1440    }
1441
1442    _LIBCPP_INLINE_VISIBILITY
1443    int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1444    {
1445        return do_length(__st, __frm, __end, __mx);
1446    }
1447
1448    _LIBCPP_INLINE_VISIBILITY
1449    int max_length() const  _NOEXCEPT
1450    {
1451        return do_max_length();
1452    }
1453
1454    static locale::id id;
1455
1456protected:
1457    _LIBCPP_INLINE_VISIBILITY
1458    explicit codecvt(const char*, size_t __refs = 0)
1459        : locale::facet(__refs) {}
1460
1461    ~codecvt();
1462
1463    virtual result do_out(state_type& __st,
1464                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1465                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1466    virtual result do_in(state_type& __st,
1467                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1468                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1469    virtual result do_unshift(state_type& __st,
1470                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1471    virtual int do_encoding() const  _NOEXCEPT;
1472    virtual bool do_always_noconv() const  _NOEXCEPT;
1473    virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1474    virtual int do_max_length() const  _NOEXCEPT;
1475};
1476
1477#endif
1478
1479// template <class _InternT, class _ExternT, class _StateT> class codecvt_byname
1480
1481template <class _InternT, class _ExternT, class _StateT>
1482class _LIBCPP_TEMPLATE_VIS codecvt_byname
1483    : public codecvt<_InternT, _ExternT, _StateT>
1484{
1485public:
1486    _LIBCPP_INLINE_VISIBILITY
1487    explicit codecvt_byname(const char* __nm, size_t __refs = 0)
1488        : codecvt<_InternT, _ExternT, _StateT>(__nm, __refs) {}
1489    _LIBCPP_INLINE_VISIBILITY
1490    explicit codecvt_byname(const string& __nm, size_t __refs = 0)
1491        : codecvt<_InternT, _ExternT, _StateT>(__nm.c_str(), __refs) {}
1492protected:
1493    ~codecvt_byname();
1494};
1495
1496_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1497template <class _InternT, class _ExternT, class _StateT>
1498codecvt_byname<_InternT, _ExternT, _StateT>::~codecvt_byname()
1499{
1500}
1501_LIBCPP_SUPPRESS_DEPRECATED_POP
1502
1503_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char, char, mbstate_t>)
1504#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1505_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<wchar_t, char, mbstate_t>)
1506#endif
1507_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char, mbstate_t>) // deprecated in C++20
1508_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char, mbstate_t>) // deprecated in C++20
1509#ifndef _LIBCPP_HAS_NO_CHAR8_T
1510_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char8_t, mbstate_t>) // C++20
1511_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char8_t, mbstate_t>) // C++20
1512#endif
1513
1514template <size_t _Np>
1515struct __narrow_to_utf8
1516{
1517    template <class _OutputIterator, class _CharT>
1518    _OutputIterator
1519    operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const;
1520};
1521
1522template <>
1523struct __narrow_to_utf8<8>
1524{
1525    template <class _OutputIterator, class _CharT>
1526    _LIBCPP_INLINE_VISIBILITY
1527    _OutputIterator
1528    operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
1529    {
1530        for (; __wb < __we; ++__wb, ++__s)
1531            *__s = *__wb;
1532        return __s;
1533    }
1534};
1535
1536_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1537template <>
1538struct _LIBCPP_TYPE_VIS __narrow_to_utf8<16>
1539    : public codecvt<char16_t, char, mbstate_t>
1540{
1541    _LIBCPP_INLINE_VISIBILITY
1542    __narrow_to_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
1543_LIBCPP_SUPPRESS_DEPRECATED_POP
1544
1545    ~__narrow_to_utf8();
1546
1547    template <class _OutputIterator, class _CharT>
1548    _LIBCPP_INLINE_VISIBILITY
1549    _OutputIterator
1550    operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
1551    {
1552        result __r = ok;
1553        mbstate_t __mb;
1554        while (__wb < __we && __r != error)
1555        {
1556            const int __sz = 32;
1557            char __buf[__sz];
1558            char* __bn;
1559            const char16_t* __wn = (const char16_t*)__wb;
1560            __r = do_out(__mb, (const char16_t*)__wb, (const char16_t*)__we, __wn,
1561                         __buf, __buf+__sz, __bn);
1562            if (__r == codecvt_base::error || __wn == (const char16_t*)__wb)
1563                __throw_runtime_error("locale not supported");
1564            for (const char* __p = __buf; __p < __bn; ++__p, ++__s)
1565                *__s = *__p;
1566            __wb = (const _CharT*)__wn;
1567        }
1568        return __s;
1569    }
1570};
1571
1572_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1573template <>
1574struct _LIBCPP_TYPE_VIS __narrow_to_utf8<32>
1575    : public codecvt<char32_t, char, mbstate_t>
1576{
1577    _LIBCPP_INLINE_VISIBILITY
1578    __narrow_to_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
1579_LIBCPP_SUPPRESS_DEPRECATED_POP
1580
1581    ~__narrow_to_utf8();
1582
1583    template <class _OutputIterator, class _CharT>
1584    _LIBCPP_INLINE_VISIBILITY
1585    _OutputIterator
1586    operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
1587    {
1588        result __r = ok;
1589        mbstate_t __mb;
1590        while (__wb < __we && __r != error)
1591        {
1592            const int __sz = 32;
1593            char __buf[__sz];
1594            char* __bn;
1595            const char32_t* __wn = (const char32_t*)__wb;
1596            __r = do_out(__mb, (const char32_t*)__wb, (const char32_t*)__we, __wn,
1597                         __buf, __buf+__sz, __bn);
1598            if (__r == codecvt_base::error || __wn == (const char32_t*)__wb)
1599                __throw_runtime_error("locale not supported");
1600            for (const char* __p = __buf; __p < __bn; ++__p, ++__s)
1601                *__s = *__p;
1602            __wb = (const _CharT*)__wn;
1603        }
1604        return __s;
1605    }
1606};
1607
1608template <size_t _Np>
1609struct __widen_from_utf8
1610{
1611    template <class _OutputIterator>
1612    _OutputIterator
1613    operator()(_OutputIterator __s, const char* __nb, const char* __ne) const;
1614};
1615
1616template <>
1617struct __widen_from_utf8<8>
1618{
1619    template <class _OutputIterator>
1620    _LIBCPP_INLINE_VISIBILITY
1621    _OutputIterator
1622    operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
1623    {
1624        for (; __nb < __ne; ++__nb, ++__s)
1625            *__s = *__nb;
1626        return __s;
1627    }
1628};
1629
1630_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1631template <>
1632struct _LIBCPP_TYPE_VIS __widen_from_utf8<16>
1633    : public codecvt<char16_t, char, mbstate_t>
1634{
1635    _LIBCPP_INLINE_VISIBILITY
1636    __widen_from_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
1637_LIBCPP_SUPPRESS_DEPRECATED_POP
1638
1639    ~__widen_from_utf8();
1640
1641    template <class _OutputIterator>
1642    _LIBCPP_INLINE_VISIBILITY
1643    _OutputIterator
1644    operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
1645    {
1646        result __r = ok;
1647        mbstate_t __mb;
1648        while (__nb < __ne && __r != error)
1649        {
1650            const int __sz = 32;
1651            char16_t __buf[__sz];
1652            char16_t* __bn;
1653            const char* __nn = __nb;
1654            __r = do_in(__mb, __nb, __ne - __nb > __sz ? __nb+__sz : __ne, __nn,
1655                        __buf, __buf+__sz, __bn);
1656            if (__r == codecvt_base::error || __nn == __nb)
1657                __throw_runtime_error("locale not supported");
1658            for (const char16_t* __p = __buf; __p < __bn; ++__p, ++__s)
1659                *__s = *__p;
1660            __nb = __nn;
1661        }
1662        return __s;
1663    }
1664};
1665
1666_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1667template <>
1668struct _LIBCPP_TYPE_VIS __widen_from_utf8<32>
1669    : public codecvt<char32_t, char, mbstate_t>
1670{
1671    _LIBCPP_INLINE_VISIBILITY
1672    __widen_from_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
1673_LIBCPP_SUPPRESS_DEPRECATED_POP
1674
1675    ~__widen_from_utf8();
1676
1677    template <class _OutputIterator>
1678    _LIBCPP_INLINE_VISIBILITY
1679    _OutputIterator
1680    operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
1681    {
1682        result __r = ok;
1683        mbstate_t __mb;
1684        while (__nb < __ne && __r != error)
1685        {
1686            const int __sz = 32;
1687            char32_t __buf[__sz];
1688            char32_t* __bn;
1689            const char* __nn = __nb;
1690            __r = do_in(__mb, __nb, __ne - __nb > __sz ? __nb+__sz : __ne, __nn,
1691                        __buf, __buf+__sz, __bn);
1692            if (__r == codecvt_base::error || __nn == __nb)
1693                __throw_runtime_error("locale not supported");
1694            for (const char32_t* __p = __buf; __p < __bn; ++__p, ++__s)
1695                *__s = *__p;
1696            __nb = __nn;
1697        }
1698        return __s;
1699    }
1700};
1701
1702// template <class charT> class numpunct
1703
1704template <class _CharT> class _LIBCPP_TEMPLATE_VIS numpunct;
1705
1706template <>
1707class _LIBCPP_TYPE_VIS numpunct<char>
1708    : public locale::facet
1709{
1710public:
1711    typedef char char_type;
1712    typedef basic_string<char_type> string_type;
1713
1714    explicit numpunct(size_t __refs = 0);
1715
1716    _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();}
1717    _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();}
1718    _LIBCPP_INLINE_VISIBILITY string grouping() const         {return do_grouping();}
1719    _LIBCPP_INLINE_VISIBILITY string_type truename() const    {return do_truename();}
1720    _LIBCPP_INLINE_VISIBILITY string_type falsename() const   {return do_falsename();}
1721
1722    static locale::id id;
1723
1724protected:
1725    ~numpunct();
1726    virtual char_type do_decimal_point() const;
1727    virtual char_type do_thousands_sep() const;
1728    virtual string do_grouping() const;
1729    virtual string_type do_truename() const;
1730    virtual string_type do_falsename() const;
1731
1732    char_type __decimal_point_;
1733    char_type __thousands_sep_;
1734    string __grouping_;
1735};
1736
1737#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1738template <>
1739class _LIBCPP_TYPE_VIS numpunct<wchar_t>
1740    : public locale::facet
1741{
1742public:
1743    typedef wchar_t char_type;
1744    typedef basic_string<char_type> string_type;
1745
1746    explicit numpunct(size_t __refs = 0);
1747
1748    _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();}
1749    _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();}
1750    _LIBCPP_INLINE_VISIBILITY string grouping() const         {return do_grouping();}
1751    _LIBCPP_INLINE_VISIBILITY string_type truename() const    {return do_truename();}
1752    _LIBCPP_INLINE_VISIBILITY string_type falsename() const   {return do_falsename();}
1753
1754    static locale::id id;
1755
1756protected:
1757    ~numpunct();
1758    virtual char_type do_decimal_point() const;
1759    virtual char_type do_thousands_sep() const;
1760    virtual string do_grouping() const;
1761    virtual string_type do_truename() const;
1762    virtual string_type do_falsename() const;
1763
1764    char_type __decimal_point_;
1765    char_type __thousands_sep_;
1766    string __grouping_;
1767};
1768#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1769
1770// template <class charT> class numpunct_byname
1771
1772template <class _CharT> class _LIBCPP_TEMPLATE_VIS numpunct_byname;
1773
1774template <>
1775class _LIBCPP_TYPE_VIS numpunct_byname<char>
1776: public numpunct<char>
1777{
1778public:
1779    typedef char char_type;
1780    typedef basic_string<char_type> string_type;
1781
1782    explicit numpunct_byname(const char* __nm, size_t __refs = 0);
1783    explicit numpunct_byname(const string& __nm, size_t __refs = 0);
1784
1785protected:
1786    ~numpunct_byname();
1787
1788private:
1789    void __init(const char*);
1790};
1791
1792#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1793template <>
1794class _LIBCPP_TYPE_VIS numpunct_byname<wchar_t>
1795: public numpunct<wchar_t>
1796{
1797public:
1798    typedef wchar_t char_type;
1799    typedef basic_string<char_type> string_type;
1800
1801    explicit numpunct_byname(const char* __nm, size_t __refs = 0);
1802    explicit numpunct_byname(const string& __nm, size_t __refs = 0);
1803
1804protected:
1805    ~numpunct_byname();
1806
1807private:
1808    void __init(const char*);
1809};
1810#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1811
1812_LIBCPP_END_NAMESPACE_STD
1813
1814#endif // _LIBCPP___LOCALE
1815