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