xref: /freebsd-src/contrib/llvm-project/libcxx/include/__locale (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
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#include <utility>
22
23#if defined(_LIBCPP_MSVCRT_LIKE)
24# include <cstring>
25# include <__support/win32/locale_win32.h>
26#elif defined(_AIX) || defined(__MVS__)
27# include <__support/ibm/xlocale.h>
28#elif defined(__ANDROID__)
29# include <__support/android/locale_bionic.h>
30#elif defined(__sun__)
31# include <xlocale.h>
32# include <__support/solaris/xlocale.h>
33#elif defined(_NEWLIB_VERSION)
34# include <__support/newlib/xlocale.h>
35#elif defined(__OpenBSD__)
36# include <__support/openbsd/xlocale.h>
37#elif (defined(__APPLE__)      || defined(__FreeBSD__) \
38    || defined(__EMSCRIPTEN__) || defined(__IBMCPP__))
39# include <xlocale.h>
40#elif defined(__Fuchsia__)
41# include <__support/fuchsia/xlocale.h>
42#elif defined(__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    virtual ~facet();
197
198//    facet(const facet&) = delete;     // effectively done in __shared_count
199//    void operator=(const facet&) = delete;
200private:
201    virtual void __on_zero_shared() _NOEXCEPT;
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();
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
342_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate<char>)
343#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
344_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(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();
365    virtual int do_compare(const char_type* __lo1, const char_type* __hi1,
366                           const char_type* __lo2, const char_type* __hi2) const;
367    virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const;
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();
385
386    virtual int do_compare(const char_type* __lo1, const char_type* __hi1,
387                           const char_type* __lo2, const char_type* __hi2) const;
388    virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const;
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 = 0x80;
456# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
457#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
458# ifdef __APPLE__
459    typedef __uint32_t mask;
460# elif defined(__FreeBSD__)
461    typedef unsigned long mask;
462# elif defined(__EMSCRIPTEN__) || defined(__NetBSD__)
463    typedef unsigned short mask;
464# endif
465    static const mask space  = _CTYPE_S;
466    static const mask print  = _CTYPE_R;
467    static const mask cntrl  = _CTYPE_C;
468    static const mask upper  = _CTYPE_U;
469    static const mask lower  = _CTYPE_L;
470    static const mask alpha  = _CTYPE_A;
471    static const mask digit  = _CTYPE_D;
472    static const mask punct  = _CTYPE_P;
473    static const mask xdigit = _CTYPE_X;
474
475# if defined(__NetBSD__)
476    static const mask blank  = _CTYPE_BL;
477    // NetBSD defines classes up to 0x2000
478    // see sys/ctype_bits.h, _CTYPE_Q
479    static const mask __regex_word = 0x8000;
480# else
481    static const mask blank  = _CTYPE_B;
482    static const mask __regex_word = 0x80;
483# endif
484#elif defined(__sun__) || defined(_AIX)
485    typedef unsigned int mask;
486    static const mask space  = _ISSPACE;
487    static const mask print  = _ISPRINT;
488    static const mask cntrl  = _ISCNTRL;
489    static const mask upper  = _ISUPPER;
490    static const mask lower  = _ISLOWER;
491    static const mask alpha  = _ISALPHA;
492    static const mask digit  = _ISDIGIT;
493    static const mask punct  = _ISPUNCT;
494    static const mask xdigit = _ISXDIGIT;
495    static const mask blank  = _ISBLANK;
496    static const mask __regex_word = 0x80;
497#elif defined(_NEWLIB_VERSION)
498    // Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h.
499    typedef char mask;
500    static const mask space  = _S;
501    static const mask print  = _P | _U | _L | _N | _B;
502    static const mask cntrl  = _C;
503    static const mask upper  = _U;
504    static const mask lower  = _L;
505    static const mask alpha  = _U | _L;
506    static const mask digit  = _N;
507    static const mask punct  = _P;
508    static const mask xdigit = _X | _N;
509    static const mask blank  = _B;
510    static const mask __regex_word = 0x80;
511# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
512# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
513# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
514#elif defined(__MVS__)
515# if defined(__NATIVE_ASCII_F)
516    typedef unsigned int mask;
517    static const mask space  = _ISSPACE_A;
518    static const mask print  = _ISPRINT_A;
519    static const mask cntrl  = _ISCNTRL_A;
520    static const mask upper  = _ISUPPER_A;
521    static const mask lower  = _ISLOWER_A;
522    static const mask alpha  = _ISALPHA_A;
523    static const mask digit  = _ISDIGIT_A;
524    static const mask punct  = _ISPUNCT_A;
525    static const mask xdigit = _ISXDIGIT_A;
526    static const mask blank  = _ISBLANK_A;
527# else
528    typedef unsigned short mask;
529    static const mask space  = __ISSPACE;
530    static const mask print  = __ISPRINT;
531    static const mask cntrl  = __ISCNTRL;
532    static const mask upper  = __ISUPPER;
533    static const mask lower  = __ISLOWER;
534    static const mask alpha  = __ISALPHA;
535    static const mask digit  = __ISDIGIT;
536    static const mask punct  = __ISPUNCT;
537    static const mask xdigit = __ISXDIGIT;
538    static const mask blank  = __ISBLANK;
539# endif
540    static const mask __regex_word = 0x8000;
541#else
542# error unknown rune table for this platform -- do you mean to define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE?
543#endif
544    static const mask alnum  = alpha | digit;
545    static const mask graph  = alnum | punct;
546
547    _LIBCPP_INLINE_VISIBILITY ctype_base() {}
548};
549
550template <class _CharT> class _LIBCPP_TEMPLATE_VIS ctype;
551
552#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
553template <>
554class _LIBCPP_TYPE_VIS ctype<wchar_t>
555    : public locale::facet,
556      public ctype_base
557{
558public:
559    typedef wchar_t char_type;
560
561    _LIBCPP_INLINE_VISIBILITY
562    explicit ctype(size_t __refs = 0)
563        : locale::facet(__refs) {}
564
565    _LIBCPP_INLINE_VISIBILITY
566    bool is(mask __m, char_type __c) const
567    {
568        return do_is(__m, __c);
569    }
570
571    _LIBCPP_INLINE_VISIBILITY
572    const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const
573    {
574        return do_is(__low, __high, __vec);
575    }
576
577    _LIBCPP_INLINE_VISIBILITY
578    const char_type* scan_is(mask __m, const char_type* __low, const char_type* __high) const
579    {
580        return do_scan_is(__m, __low, __high);
581    }
582
583    _LIBCPP_INLINE_VISIBILITY
584    const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const
585    {
586        return do_scan_not(__m, __low, __high);
587    }
588
589    _LIBCPP_INLINE_VISIBILITY
590    char_type toupper(char_type __c) const
591    {
592        return do_toupper(__c);
593    }
594
595    _LIBCPP_INLINE_VISIBILITY
596    const char_type* toupper(char_type* __low, const char_type* __high) const
597    {
598        return do_toupper(__low, __high);
599    }
600
601    _LIBCPP_INLINE_VISIBILITY
602    char_type tolower(char_type __c) const
603    {
604        return do_tolower(__c);
605    }
606
607    _LIBCPP_INLINE_VISIBILITY
608    const char_type* tolower(char_type* __low, const char_type* __high) const
609    {
610        return do_tolower(__low, __high);
611    }
612
613    _LIBCPP_INLINE_VISIBILITY
614    char_type widen(char __c) const
615    {
616        return do_widen(__c);
617    }
618
619    _LIBCPP_INLINE_VISIBILITY
620    const char* widen(const char* __low, const char* __high, char_type* __to) const
621    {
622        return do_widen(__low, __high, __to);
623    }
624
625    _LIBCPP_INLINE_VISIBILITY
626    char narrow(char_type __c, char __dfault) const
627    {
628        return do_narrow(__c, __dfault);
629    }
630
631    _LIBCPP_INLINE_VISIBILITY
632    const char_type* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const
633    {
634        return do_narrow(__low, __high, __dfault, __to);
635    }
636
637    static locale::id id;
638
639protected:
640    ~ctype();
641    virtual bool do_is(mask __m, char_type __c) const;
642    virtual const char_type* do_is(const char_type* __low, const char_type* __high, mask* __vec) const;
643    virtual const char_type* do_scan_is(mask __m, const char_type* __low, const char_type* __high) const;
644    virtual const char_type* do_scan_not(mask __m, const char_type* __low, const char_type* __high) const;
645    virtual char_type do_toupper(char_type) const;
646    virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
647    virtual char_type do_tolower(char_type) const;
648    virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
649    virtual char_type do_widen(char) const;
650    virtual const char* do_widen(const char* __low, const char* __high, char_type* __dest) const;
651    virtual char do_narrow(char_type, char __dfault) const;
652    virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const;
653};
654#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
655
656template <>
657class _LIBCPP_TYPE_VIS ctype<char>
658    : public locale::facet, public ctype_base
659{
660    const mask* __tab_;
661    bool        __del_;
662public:
663    typedef char char_type;
664
665    explicit ctype(const mask* __tab = nullptr, bool __del = false, size_t __refs = 0);
666
667    _LIBCPP_INLINE_VISIBILITY
668    bool is(mask __m, char_type __c) const
669    {
670        return isascii(__c) ? (__tab_[static_cast<int>(__c)] & __m) !=0 : false;
671    }
672
673    _LIBCPP_INLINE_VISIBILITY
674    const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const
675    {
676        for (; __low != __high; ++__low, ++__vec)
677            *__vec = isascii(*__low) ? __tab_[static_cast<int>(*__low)] : 0;
678        return __low;
679    }
680
681    _LIBCPP_INLINE_VISIBILITY
682    const char_type* scan_is (mask __m, const char_type* __low, const char_type* __high) const
683    {
684        for (; __low != __high; ++__low)
685            if (isascii(*__low) && (__tab_[static_cast<int>(*__low)] & __m))
686                break;
687        return __low;
688    }
689
690    _LIBCPP_INLINE_VISIBILITY
691    const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const
692    {
693        for (; __low != __high; ++__low)
694            if (!(isascii(*__low) && (__tab_[static_cast<int>(*__low)] & __m)))
695                break;
696        return __low;
697    }
698
699    _LIBCPP_INLINE_VISIBILITY
700    char_type toupper(char_type __c) const
701    {
702        return do_toupper(__c);
703    }
704
705    _LIBCPP_INLINE_VISIBILITY
706    const char_type* toupper(char_type* __low, const char_type* __high) const
707    {
708        return do_toupper(__low, __high);
709    }
710
711    _LIBCPP_INLINE_VISIBILITY
712    char_type tolower(char_type __c) const
713    {
714        return do_tolower(__c);
715    }
716
717    _LIBCPP_INLINE_VISIBILITY
718    const char_type* tolower(char_type* __low, const char_type* __high) const
719    {
720        return do_tolower(__low, __high);
721    }
722
723    _LIBCPP_INLINE_VISIBILITY
724    char_type widen(char __c) const
725    {
726        return do_widen(__c);
727    }
728
729    _LIBCPP_INLINE_VISIBILITY
730    const char* widen(const char* __low, const char* __high, char_type* __to) const
731    {
732        return do_widen(__low, __high, __to);
733    }
734
735    _LIBCPP_INLINE_VISIBILITY
736    char narrow(char_type __c, char __dfault) const
737    {
738        return do_narrow(__c, __dfault);
739    }
740
741    _LIBCPP_INLINE_VISIBILITY
742    const char* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const
743    {
744        return do_narrow(__low, __high, __dfault, __to);
745    }
746
747    static locale::id id;
748
749#ifdef _CACHED_RUNES
750    static const size_t table_size = _CACHED_RUNES;
751#else
752    static const size_t table_size = 256;  // FIXME: Don't hardcode this.
753#endif
754    _LIBCPP_INLINE_VISIBILITY const mask* table() const  _NOEXCEPT {return __tab_;}
755    static const mask* classic_table()  _NOEXCEPT;
756#if defined(__GLIBC__) || defined(__EMSCRIPTEN__)
757    static const int* __classic_upper_table() _NOEXCEPT;
758    static const int* __classic_lower_table() _NOEXCEPT;
759#endif
760#if defined(__NetBSD__)
761    static const short* __classic_upper_table() _NOEXCEPT;
762    static const short* __classic_lower_table() _NOEXCEPT;
763#endif
764#if defined(__MVS__)
765    static const unsigned short* __classic_upper_table() _NOEXCEPT;
766    static const unsigned short* __classic_lower_table() _NOEXCEPT;
767#endif
768
769protected:
770    ~ctype();
771    virtual char_type do_toupper(char_type __c) const;
772    virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
773    virtual char_type do_tolower(char_type __c) const;
774    virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
775    virtual char_type do_widen(char __c) const;
776    virtual const char* do_widen(const char* __low, const char* __high, char_type* __to) const;
777    virtual char do_narrow(char_type __c, char __dfault) const;
778    virtual const char* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const;
779};
780
781// template <class CharT> class ctype_byname;
782
783template <class _CharT> class _LIBCPP_TEMPLATE_VIS ctype_byname;
784
785template <>
786class _LIBCPP_TYPE_VIS ctype_byname<char>
787    : public ctype<char>
788{
789    locale_t __l;
790
791public:
792    explicit ctype_byname(const char*, size_t = 0);
793    explicit ctype_byname(const string&, size_t = 0);
794
795protected:
796    ~ctype_byname();
797    virtual char_type do_toupper(char_type) const;
798    virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
799    virtual char_type do_tolower(char_type) const;
800    virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
801};
802
803#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
804template <>
805class _LIBCPP_TYPE_VIS ctype_byname<wchar_t>
806    : public ctype<wchar_t>
807{
808    locale_t __l;
809
810public:
811    explicit ctype_byname(const char*, size_t = 0);
812    explicit ctype_byname(const string&, size_t = 0);
813
814protected:
815    ~ctype_byname();
816    virtual bool do_is(mask __m, char_type __c) const;
817    virtual const char_type* do_is(const char_type* __low, const char_type* __high, mask* __vec) const;
818    virtual const char_type* do_scan_is(mask __m, const char_type* __low, const char_type* __high) const;
819    virtual const char_type* do_scan_not(mask __m, const char_type* __low, const char_type* __high) const;
820    virtual char_type do_toupper(char_type) const;
821    virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
822    virtual char_type do_tolower(char_type) const;
823    virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
824    virtual char_type do_widen(char) const;
825    virtual const char* do_widen(const char* __low, const char* __high, char_type* __dest) const;
826    virtual char do_narrow(char_type, char __dfault) const;
827    virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const;
828};
829#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
830
831template <class _CharT>
832inline _LIBCPP_INLINE_VISIBILITY
833bool
834isspace(_CharT __c, const locale& __loc)
835{
836    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::space, __c);
837}
838
839template <class _CharT>
840inline _LIBCPP_INLINE_VISIBILITY
841bool
842isprint(_CharT __c, const locale& __loc)
843{
844    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::print, __c);
845}
846
847template <class _CharT>
848inline _LIBCPP_INLINE_VISIBILITY
849bool
850iscntrl(_CharT __c, const locale& __loc)
851{
852    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::cntrl, __c);
853}
854
855template <class _CharT>
856inline _LIBCPP_INLINE_VISIBILITY
857bool
858isupper(_CharT __c, const locale& __loc)
859{
860    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::upper, __c);
861}
862
863template <class _CharT>
864inline _LIBCPP_INLINE_VISIBILITY
865bool
866islower(_CharT __c, const locale& __loc)
867{
868    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::lower, __c);
869}
870
871template <class _CharT>
872inline _LIBCPP_INLINE_VISIBILITY
873bool
874isalpha(_CharT __c, const locale& __loc)
875{
876    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alpha, __c);
877}
878
879template <class _CharT>
880inline _LIBCPP_INLINE_VISIBILITY
881bool
882isdigit(_CharT __c, const locale& __loc)
883{
884    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::digit, __c);
885}
886
887template <class _CharT>
888inline _LIBCPP_INLINE_VISIBILITY
889bool
890ispunct(_CharT __c, const locale& __loc)
891{
892    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::punct, __c);
893}
894
895template <class _CharT>
896inline _LIBCPP_INLINE_VISIBILITY
897bool
898isxdigit(_CharT __c, const locale& __loc)
899{
900    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::xdigit, __c);
901}
902
903template <class _CharT>
904inline _LIBCPP_INLINE_VISIBILITY
905bool
906isalnum(_CharT __c, const locale& __loc)
907{
908    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alnum, __c);
909}
910
911template <class _CharT>
912inline _LIBCPP_INLINE_VISIBILITY
913bool
914isgraph(_CharT __c, const locale& __loc)
915{
916    return use_facet<ctype<_CharT> >(__loc).is(ctype_base::graph, __c);
917}
918
919template <class _CharT>
920inline _LIBCPP_INLINE_VISIBILITY
921_CharT
922toupper(_CharT __c, const locale& __loc)
923{
924    return use_facet<ctype<_CharT> >(__loc).toupper(__c);
925}
926
927template <class _CharT>
928inline _LIBCPP_INLINE_VISIBILITY
929_CharT
930tolower(_CharT __c, const locale& __loc)
931{
932    return use_facet<ctype<_CharT> >(__loc).tolower(__c);
933}
934
935// codecvt_base
936
937class _LIBCPP_TYPE_VIS codecvt_base
938{
939public:
940    _LIBCPP_INLINE_VISIBILITY codecvt_base() {}
941    enum result {ok, partial, error, noconv};
942};
943
944// template <class internT, class externT, class stateT> class codecvt;
945
946template <class _InternT, class _ExternT, class _StateT> class _LIBCPP_TEMPLATE_VIS codecvt;
947
948// template <> class codecvt<char, char, mbstate_t>
949
950template <>
951class _LIBCPP_TYPE_VIS codecvt<char, char, mbstate_t>
952    : public locale::facet,
953      public codecvt_base
954{
955public:
956    typedef char      intern_type;
957    typedef char      extern_type;
958    typedef mbstate_t state_type;
959
960    _LIBCPP_INLINE_VISIBILITY
961    explicit codecvt(size_t __refs = 0)
962        : locale::facet(__refs) {}
963
964    _LIBCPP_INLINE_VISIBILITY
965    result out(state_type& __st,
966               const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
967               extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
968    {
969        return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
970    }
971
972    _LIBCPP_INLINE_VISIBILITY
973    result unshift(state_type& __st,
974                   extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
975    {
976        return do_unshift(__st, __to, __to_end, __to_nxt);
977    }
978
979    _LIBCPP_INLINE_VISIBILITY
980    result in(state_type& __st,
981              const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
982              intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
983    {
984        return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
985    }
986
987    _LIBCPP_INLINE_VISIBILITY
988    int encoding() const  _NOEXCEPT
989    {
990        return do_encoding();
991    }
992
993    _LIBCPP_INLINE_VISIBILITY
994    bool always_noconv() const  _NOEXCEPT
995    {
996        return do_always_noconv();
997    }
998
999    _LIBCPP_INLINE_VISIBILITY
1000    int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1001    {
1002        return do_length(__st, __frm, __end, __mx);
1003    }
1004
1005    _LIBCPP_INLINE_VISIBILITY
1006    int max_length() const  _NOEXCEPT
1007    {
1008        return do_max_length();
1009    }
1010
1011    static locale::id id;
1012
1013protected:
1014    _LIBCPP_INLINE_VISIBILITY
1015    explicit codecvt(const char*, size_t __refs = 0)
1016        : locale::facet(__refs) {}
1017
1018    ~codecvt();
1019
1020    virtual result do_out(state_type& __st,
1021                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1022                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1023    virtual result do_in(state_type& __st,
1024                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1025                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1026    virtual result do_unshift(state_type& __st,
1027                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1028    virtual int do_encoding() const  _NOEXCEPT;
1029    virtual bool do_always_noconv() const  _NOEXCEPT;
1030    virtual int do_length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1031    virtual int do_max_length() const  _NOEXCEPT;
1032};
1033
1034// template <> class codecvt<wchar_t, char, mbstate_t>
1035
1036#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1037template <>
1038class _LIBCPP_TYPE_VIS codecvt<wchar_t, char, mbstate_t>
1039    : public locale::facet,
1040      public codecvt_base
1041{
1042    locale_t __l;
1043public:
1044    typedef wchar_t   intern_type;
1045    typedef char      extern_type;
1046    typedef mbstate_t state_type;
1047
1048    explicit codecvt(size_t __refs = 0);
1049
1050    _LIBCPP_INLINE_VISIBILITY
1051    result out(state_type& __st,
1052               const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1053               extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1054    {
1055        return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1056    }
1057
1058    _LIBCPP_INLINE_VISIBILITY
1059    result unshift(state_type& __st,
1060                   extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1061    {
1062        return do_unshift(__st, __to, __to_end, __to_nxt);
1063    }
1064
1065    _LIBCPP_INLINE_VISIBILITY
1066    result in(state_type& __st,
1067              const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1068              intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
1069    {
1070        return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1071    }
1072
1073    _LIBCPP_INLINE_VISIBILITY
1074    int encoding() const  _NOEXCEPT
1075    {
1076        return do_encoding();
1077    }
1078
1079    _LIBCPP_INLINE_VISIBILITY
1080    bool always_noconv() const  _NOEXCEPT
1081    {
1082        return do_always_noconv();
1083    }
1084
1085    _LIBCPP_INLINE_VISIBILITY
1086    int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1087    {
1088        return do_length(__st, __frm, __end, __mx);
1089    }
1090
1091    _LIBCPP_INLINE_VISIBILITY
1092    int max_length() const  _NOEXCEPT
1093    {
1094        return do_max_length();
1095    }
1096
1097    static locale::id id;
1098
1099protected:
1100    explicit codecvt(const char*, size_t __refs = 0);
1101
1102    ~codecvt();
1103
1104    virtual result do_out(state_type& __st,
1105                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1106                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1107    virtual result do_in(state_type& __st,
1108                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1109                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1110    virtual result do_unshift(state_type& __st,
1111                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1112    virtual int do_encoding() const  _NOEXCEPT;
1113    virtual bool do_always_noconv() const  _NOEXCEPT;
1114    virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1115    virtual int do_max_length() const  _NOEXCEPT;
1116};
1117#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1118
1119// template <> class codecvt<char16_t, char, mbstate_t> // deprecated in C++20
1120
1121template <>
1122class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_TYPE_VIS codecvt<char16_t, char, mbstate_t>
1123    : public locale::facet,
1124      public codecvt_base
1125{
1126public:
1127    typedef char16_t  intern_type;
1128    typedef char      extern_type;
1129    typedef mbstate_t state_type;
1130
1131    _LIBCPP_INLINE_VISIBILITY
1132    explicit codecvt(size_t __refs = 0)
1133        : locale::facet(__refs) {}
1134
1135    _LIBCPP_INLINE_VISIBILITY
1136    result out(state_type& __st,
1137               const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1138               extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1139    {
1140        return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1141    }
1142
1143    _LIBCPP_INLINE_VISIBILITY
1144    result unshift(state_type& __st,
1145                   extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1146    {
1147        return do_unshift(__st, __to, __to_end, __to_nxt);
1148    }
1149
1150    _LIBCPP_INLINE_VISIBILITY
1151    result in(state_type& __st,
1152              const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1153              intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
1154    {
1155        return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1156    }
1157
1158    _LIBCPP_INLINE_VISIBILITY
1159    int encoding() const  _NOEXCEPT
1160    {
1161        return do_encoding();
1162    }
1163
1164    _LIBCPP_INLINE_VISIBILITY
1165    bool always_noconv() const  _NOEXCEPT
1166    {
1167        return do_always_noconv();
1168    }
1169
1170    _LIBCPP_INLINE_VISIBILITY
1171    int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1172    {
1173        return do_length(__st, __frm, __end, __mx);
1174    }
1175
1176    _LIBCPP_INLINE_VISIBILITY
1177    int max_length() const  _NOEXCEPT
1178    {
1179        return do_max_length();
1180    }
1181
1182    static locale::id id;
1183
1184protected:
1185    _LIBCPP_INLINE_VISIBILITY
1186    explicit codecvt(const char*, size_t __refs = 0)
1187        : locale::facet(__refs) {}
1188
1189    ~codecvt();
1190
1191    virtual result do_out(state_type& __st,
1192                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1193                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1194    virtual result do_in(state_type& __st,
1195                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1196                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1197    virtual result do_unshift(state_type& __st,
1198                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1199    virtual int do_encoding() const  _NOEXCEPT;
1200    virtual bool do_always_noconv() const  _NOEXCEPT;
1201    virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1202    virtual int do_max_length() const  _NOEXCEPT;
1203};
1204
1205#ifndef _LIBCPP_HAS_NO_CHAR8_T
1206
1207// template <> class codecvt<char16_t, char8_t, mbstate_t> // C++20
1208
1209template <>
1210class _LIBCPP_TYPE_VIS codecvt<char16_t, char8_t, mbstate_t>
1211    : public locale::facet,
1212      public codecvt_base
1213{
1214public:
1215    typedef char16_t  intern_type;
1216    typedef char8_t   extern_type;
1217    typedef mbstate_t state_type;
1218
1219    _LIBCPP_INLINE_VISIBILITY
1220    explicit codecvt(size_t __refs = 0)
1221        : locale::facet(__refs) {}
1222
1223    _LIBCPP_INLINE_VISIBILITY
1224    result out(state_type& __st,
1225               const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1226               extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1227    {
1228        return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1229    }
1230
1231    _LIBCPP_INLINE_VISIBILITY
1232    result unshift(state_type& __st,
1233                   extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1234    {
1235        return do_unshift(__st, __to, __to_end, __to_nxt);
1236    }
1237
1238    _LIBCPP_INLINE_VISIBILITY
1239    result in(state_type& __st,
1240              const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1241              intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
1242    {
1243        return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1244    }
1245
1246    _LIBCPP_INLINE_VISIBILITY
1247    int encoding() const  _NOEXCEPT
1248    {
1249        return do_encoding();
1250    }
1251
1252    _LIBCPP_INLINE_VISIBILITY
1253    bool always_noconv() const  _NOEXCEPT
1254    {
1255        return do_always_noconv();
1256    }
1257
1258    _LIBCPP_INLINE_VISIBILITY
1259    int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1260    {
1261        return do_length(__st, __frm, __end, __mx);
1262    }
1263
1264    _LIBCPP_INLINE_VISIBILITY
1265    int max_length() const  _NOEXCEPT
1266    {
1267        return do_max_length();
1268    }
1269
1270    static locale::id id;
1271
1272protected:
1273    _LIBCPP_INLINE_VISIBILITY
1274    explicit codecvt(const char*, size_t __refs = 0)
1275        : locale::facet(__refs) {}
1276
1277    ~codecvt();
1278
1279    virtual result do_out(state_type& __st,
1280                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1281                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1282    virtual result do_in(state_type& __st,
1283                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1284                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1285    virtual result do_unshift(state_type& __st,
1286                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1287    virtual int do_encoding() const  _NOEXCEPT;
1288    virtual bool do_always_noconv() const  _NOEXCEPT;
1289    virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1290    virtual int do_max_length() const  _NOEXCEPT;
1291};
1292
1293#endif
1294
1295// template <> class codecvt<char32_t, char, mbstate_t> // deprecated in C++20
1296
1297template <>
1298class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_TYPE_VIS codecvt<char32_t, char, mbstate_t>
1299    : public locale::facet,
1300      public codecvt_base
1301{
1302public:
1303    typedef char32_t  intern_type;
1304    typedef char      extern_type;
1305    typedef mbstate_t state_type;
1306
1307    _LIBCPP_INLINE_VISIBILITY
1308    explicit codecvt(size_t __refs = 0)
1309        : locale::facet(__refs) {}
1310
1311    _LIBCPP_INLINE_VISIBILITY
1312    result out(state_type& __st,
1313               const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1314               extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1315    {
1316        return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1317    }
1318
1319    _LIBCPP_INLINE_VISIBILITY
1320    result unshift(state_type& __st,
1321                   extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1322    {
1323        return do_unshift(__st, __to, __to_end, __to_nxt);
1324    }
1325
1326    _LIBCPP_INLINE_VISIBILITY
1327    result in(state_type& __st,
1328              const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1329              intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
1330    {
1331        return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1332    }
1333
1334    _LIBCPP_INLINE_VISIBILITY
1335    int encoding() const  _NOEXCEPT
1336    {
1337        return do_encoding();
1338    }
1339
1340    _LIBCPP_INLINE_VISIBILITY
1341    bool always_noconv() const  _NOEXCEPT
1342    {
1343        return do_always_noconv();
1344    }
1345
1346    _LIBCPP_INLINE_VISIBILITY
1347    int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1348    {
1349        return do_length(__st, __frm, __end, __mx);
1350    }
1351
1352    _LIBCPP_INLINE_VISIBILITY
1353    int max_length() const  _NOEXCEPT
1354    {
1355        return do_max_length();
1356    }
1357
1358    static locale::id id;
1359
1360protected:
1361    _LIBCPP_INLINE_VISIBILITY
1362    explicit codecvt(const char*, size_t __refs = 0)
1363        : locale::facet(__refs) {}
1364
1365    ~codecvt();
1366
1367    virtual result do_out(state_type& __st,
1368                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1369                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1370    virtual result do_in(state_type& __st,
1371                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1372                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1373    virtual result do_unshift(state_type& __st,
1374                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1375    virtual int do_encoding() const  _NOEXCEPT;
1376    virtual bool do_always_noconv() const  _NOEXCEPT;
1377    virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1378    virtual int do_max_length() const  _NOEXCEPT;
1379};
1380
1381#ifndef _LIBCPP_HAS_NO_CHAR8_T
1382
1383// template <> class codecvt<char32_t, char8_t, mbstate_t> // C++20
1384
1385template <>
1386class _LIBCPP_TYPE_VIS codecvt<char32_t, char8_t, mbstate_t>
1387    : public locale::facet,
1388      public codecvt_base
1389{
1390public:
1391    typedef char32_t  intern_type;
1392    typedef char8_t   extern_type;
1393    typedef mbstate_t state_type;
1394
1395    _LIBCPP_INLINE_VISIBILITY
1396    explicit codecvt(size_t __refs = 0)
1397        : locale::facet(__refs) {}
1398
1399    _LIBCPP_INLINE_VISIBILITY
1400    result out(state_type& __st,
1401               const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1402               extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1403    {
1404        return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1405    }
1406
1407    _LIBCPP_INLINE_VISIBILITY
1408    result unshift(state_type& __st,
1409                   extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const
1410    {
1411        return do_unshift(__st, __to, __to_end, __to_nxt);
1412    }
1413
1414    _LIBCPP_INLINE_VISIBILITY
1415    result in(state_type& __st,
1416              const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1417              intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const
1418    {
1419        return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
1420    }
1421
1422    _LIBCPP_INLINE_VISIBILITY
1423    int encoding() const  _NOEXCEPT
1424    {
1425        return do_encoding();
1426    }
1427
1428    _LIBCPP_INLINE_VISIBILITY
1429    bool always_noconv() const  _NOEXCEPT
1430    {
1431        return do_always_noconv();
1432    }
1433
1434    _LIBCPP_INLINE_VISIBILITY
1435    int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const
1436    {
1437        return do_length(__st, __frm, __end, __mx);
1438    }
1439
1440    _LIBCPP_INLINE_VISIBILITY
1441    int max_length() const  _NOEXCEPT
1442    {
1443        return do_max_length();
1444    }
1445
1446    static locale::id id;
1447
1448protected:
1449    _LIBCPP_INLINE_VISIBILITY
1450    explicit codecvt(const char*, size_t __refs = 0)
1451        : locale::facet(__refs) {}
1452
1453    ~codecvt();
1454
1455    virtual result do_out(state_type& __st,
1456                          const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt,
1457                          extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1458    virtual result do_in(state_type& __st,
1459                         const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt,
1460                         intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const;
1461    virtual result do_unshift(state_type& __st,
1462                              extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
1463    virtual int do_encoding() const  _NOEXCEPT;
1464    virtual bool do_always_noconv() const  _NOEXCEPT;
1465    virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
1466    virtual int do_max_length() const  _NOEXCEPT;
1467};
1468
1469#endif
1470
1471// template <class _InternT, class _ExternT, class _StateT> class codecvt_byname
1472
1473template <class _InternT, class _ExternT, class _StateT>
1474class _LIBCPP_TEMPLATE_VIS codecvt_byname
1475    : public codecvt<_InternT, _ExternT, _StateT>
1476{
1477public:
1478    _LIBCPP_INLINE_VISIBILITY
1479    explicit codecvt_byname(const char* __nm, size_t __refs = 0)
1480        : codecvt<_InternT, _ExternT, _StateT>(__nm, __refs) {}
1481    _LIBCPP_INLINE_VISIBILITY
1482    explicit codecvt_byname(const string& __nm, size_t __refs = 0)
1483        : codecvt<_InternT, _ExternT, _StateT>(__nm.c_str(), __refs) {}
1484protected:
1485    ~codecvt_byname();
1486};
1487
1488_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1489template <class _InternT, class _ExternT, class _StateT>
1490codecvt_byname<_InternT, _ExternT, _StateT>::~codecvt_byname()
1491{
1492}
1493_LIBCPP_SUPPRESS_DEPRECATED_POP
1494
1495_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char, char, mbstate_t>)
1496#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1497_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<wchar_t, char, mbstate_t>)
1498#endif
1499_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
1500_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
1501#ifndef _LIBCPP_HAS_NO_CHAR8_T
1502_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char8_t, mbstate_t>) // C++20
1503_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char8_t, mbstate_t>) // C++20
1504#endif
1505
1506template <size_t _Np>
1507struct __narrow_to_utf8
1508{
1509    template <class _OutputIterator, class _CharT>
1510    _OutputIterator
1511    operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const;
1512};
1513
1514template <>
1515struct __narrow_to_utf8<8>
1516{
1517    template <class _OutputIterator, class _CharT>
1518    _LIBCPP_INLINE_VISIBILITY
1519    _OutputIterator
1520    operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
1521    {
1522        for (; __wb < __we; ++__wb, ++__s)
1523            *__s = *__wb;
1524        return __s;
1525    }
1526};
1527
1528_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1529template <>
1530struct _LIBCPP_TYPE_VIS __narrow_to_utf8<16>
1531    : public codecvt<char16_t, char, mbstate_t>
1532{
1533    _LIBCPP_INLINE_VISIBILITY
1534    __narrow_to_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
1535_LIBCPP_SUPPRESS_DEPRECATED_POP
1536
1537    ~__narrow_to_utf8();
1538
1539    template <class _OutputIterator, class _CharT>
1540    _LIBCPP_INLINE_VISIBILITY
1541    _OutputIterator
1542    operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
1543    {
1544        result __r = ok;
1545        mbstate_t __mb;
1546        while (__wb < __we && __r != error)
1547        {
1548            const int __sz = 32;
1549            char __buf[__sz];
1550            char* __bn;
1551            const char16_t* __wn = (const char16_t*)__wb;
1552            __r = do_out(__mb, (const char16_t*)__wb, (const char16_t*)__we, __wn,
1553                         __buf, __buf+__sz, __bn);
1554            if (__r == codecvt_base::error || __wn == (const char16_t*)__wb)
1555                __throw_runtime_error("locale not supported");
1556            for (const char* __p = __buf; __p < __bn; ++__p, ++__s)
1557                *__s = *__p;
1558            __wb = (const _CharT*)__wn;
1559        }
1560        return __s;
1561    }
1562};
1563
1564_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1565template <>
1566struct _LIBCPP_TYPE_VIS __narrow_to_utf8<32>
1567    : public codecvt<char32_t, char, mbstate_t>
1568{
1569    _LIBCPP_INLINE_VISIBILITY
1570    __narrow_to_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
1571_LIBCPP_SUPPRESS_DEPRECATED_POP
1572
1573    ~__narrow_to_utf8();
1574
1575    template <class _OutputIterator, class _CharT>
1576    _LIBCPP_INLINE_VISIBILITY
1577    _OutputIterator
1578    operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const
1579    {
1580        result __r = ok;
1581        mbstate_t __mb;
1582        while (__wb < __we && __r != error)
1583        {
1584            const int __sz = 32;
1585            char __buf[__sz];
1586            char* __bn;
1587            const char32_t* __wn = (const char32_t*)__wb;
1588            __r = do_out(__mb, (const char32_t*)__wb, (const char32_t*)__we, __wn,
1589                         __buf, __buf+__sz, __bn);
1590            if (__r == codecvt_base::error || __wn == (const char32_t*)__wb)
1591                __throw_runtime_error("locale not supported");
1592            for (const char* __p = __buf; __p < __bn; ++__p, ++__s)
1593                *__s = *__p;
1594            __wb = (const _CharT*)__wn;
1595        }
1596        return __s;
1597    }
1598};
1599
1600template <size_t _Np>
1601struct __widen_from_utf8
1602{
1603    template <class _OutputIterator>
1604    _OutputIterator
1605    operator()(_OutputIterator __s, const char* __nb, const char* __ne) const;
1606};
1607
1608template <>
1609struct __widen_from_utf8<8>
1610{
1611    template <class _OutputIterator>
1612    _LIBCPP_INLINE_VISIBILITY
1613    _OutputIterator
1614    operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
1615    {
1616        for (; __nb < __ne; ++__nb, ++__s)
1617            *__s = *__nb;
1618        return __s;
1619    }
1620};
1621
1622_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1623template <>
1624struct _LIBCPP_TYPE_VIS __widen_from_utf8<16>
1625    : public codecvt<char16_t, char, mbstate_t>
1626{
1627    _LIBCPP_INLINE_VISIBILITY
1628    __widen_from_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
1629_LIBCPP_SUPPRESS_DEPRECATED_POP
1630
1631    ~__widen_from_utf8();
1632
1633    template <class _OutputIterator>
1634    _LIBCPP_INLINE_VISIBILITY
1635    _OutputIterator
1636    operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
1637    {
1638        result __r = ok;
1639        mbstate_t __mb;
1640        while (__nb < __ne && __r != error)
1641        {
1642            const int __sz = 32;
1643            char16_t __buf[__sz];
1644            char16_t* __bn;
1645            const char* __nn = __nb;
1646            __r = do_in(__mb, __nb, __ne - __nb > __sz ? __nb+__sz : __ne, __nn,
1647                        __buf, __buf+__sz, __bn);
1648            if (__r == codecvt_base::error || __nn == __nb)
1649                __throw_runtime_error("locale not supported");
1650            for (const char16_t* __p = __buf; __p < __bn; ++__p, ++__s)
1651                *__s = *__p;
1652            __nb = __nn;
1653        }
1654        return __s;
1655    }
1656};
1657
1658_LIBCPP_SUPPRESS_DEPRECATED_PUSH
1659template <>
1660struct _LIBCPP_TYPE_VIS __widen_from_utf8<32>
1661    : public codecvt<char32_t, char, mbstate_t>
1662{
1663    _LIBCPP_INLINE_VISIBILITY
1664    __widen_from_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
1665_LIBCPP_SUPPRESS_DEPRECATED_POP
1666
1667    ~__widen_from_utf8();
1668
1669    template <class _OutputIterator>
1670    _LIBCPP_INLINE_VISIBILITY
1671    _OutputIterator
1672    operator()(_OutputIterator __s, const char* __nb, const char* __ne) const
1673    {
1674        result __r = ok;
1675        mbstate_t __mb;
1676        while (__nb < __ne && __r != error)
1677        {
1678            const int __sz = 32;
1679            char32_t __buf[__sz];
1680            char32_t* __bn;
1681            const char* __nn = __nb;
1682            __r = do_in(__mb, __nb, __ne - __nb > __sz ? __nb+__sz : __ne, __nn,
1683                        __buf, __buf+__sz, __bn);
1684            if (__r == codecvt_base::error || __nn == __nb)
1685                __throw_runtime_error("locale not supported");
1686            for (const char32_t* __p = __buf; __p < __bn; ++__p, ++__s)
1687                *__s = *__p;
1688            __nb = __nn;
1689        }
1690        return __s;
1691    }
1692};
1693
1694// template <class charT> class numpunct
1695
1696template <class _CharT> class _LIBCPP_TEMPLATE_VIS numpunct;
1697
1698template <>
1699class _LIBCPP_TYPE_VIS numpunct<char>
1700    : public locale::facet
1701{
1702public:
1703    typedef char char_type;
1704    typedef basic_string<char_type> string_type;
1705
1706    explicit numpunct(size_t __refs = 0);
1707
1708    _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();}
1709    _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();}
1710    _LIBCPP_INLINE_VISIBILITY string grouping() const         {return do_grouping();}
1711    _LIBCPP_INLINE_VISIBILITY string_type truename() const    {return do_truename();}
1712    _LIBCPP_INLINE_VISIBILITY string_type falsename() const   {return do_falsename();}
1713
1714    static locale::id id;
1715
1716protected:
1717    ~numpunct();
1718    virtual char_type do_decimal_point() const;
1719    virtual char_type do_thousands_sep() const;
1720    virtual string do_grouping() const;
1721    virtual string_type do_truename() const;
1722    virtual string_type do_falsename() const;
1723
1724    char_type __decimal_point_;
1725    char_type __thousands_sep_;
1726    string __grouping_;
1727};
1728
1729#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1730template <>
1731class _LIBCPP_TYPE_VIS numpunct<wchar_t>
1732    : public locale::facet
1733{
1734public:
1735    typedef wchar_t char_type;
1736    typedef basic_string<char_type> string_type;
1737
1738    explicit numpunct(size_t __refs = 0);
1739
1740    _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();}
1741    _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();}
1742    _LIBCPP_INLINE_VISIBILITY string grouping() const         {return do_grouping();}
1743    _LIBCPP_INLINE_VISIBILITY string_type truename() const    {return do_truename();}
1744    _LIBCPP_INLINE_VISIBILITY string_type falsename() const   {return do_falsename();}
1745
1746    static locale::id id;
1747
1748protected:
1749    ~numpunct();
1750    virtual char_type do_decimal_point() const;
1751    virtual char_type do_thousands_sep() const;
1752    virtual string do_grouping() const;
1753    virtual string_type do_truename() const;
1754    virtual string_type do_falsename() const;
1755
1756    char_type __decimal_point_;
1757    char_type __thousands_sep_;
1758    string __grouping_;
1759};
1760#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1761
1762// template <class charT> class numpunct_byname
1763
1764template <class _CharT> class _LIBCPP_TEMPLATE_VIS numpunct_byname;
1765
1766template <>
1767class _LIBCPP_TYPE_VIS numpunct_byname<char>
1768: public numpunct<char>
1769{
1770public:
1771    typedef char char_type;
1772    typedef basic_string<char_type> string_type;
1773
1774    explicit numpunct_byname(const char* __nm, size_t __refs = 0);
1775    explicit numpunct_byname(const string& __nm, size_t __refs = 0);
1776
1777protected:
1778    ~numpunct_byname();
1779
1780private:
1781    void __init(const char*);
1782};
1783
1784#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1785template <>
1786class _LIBCPP_TYPE_VIS numpunct_byname<wchar_t>
1787: public numpunct<wchar_t>
1788{
1789public:
1790    typedef wchar_t char_type;
1791    typedef basic_string<char_type> string_type;
1792
1793    explicit numpunct_byname(const char* __nm, size_t __refs = 0);
1794    explicit numpunct_byname(const string& __nm, size_t __refs = 0);
1795
1796protected:
1797    ~numpunct_byname();
1798
1799private:
1800    void __init(const char*);
1801};
1802#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
1803
1804_LIBCPP_END_NAMESPACE_STD
1805
1806#endif // _LIBCPP___LOCALE
1807