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