xref: /freebsd/contrib/llvm-project/libcxx/include/__locale (revision 744bfb213144c63cbaf38d91a1c4f7aebb9b9fbc)
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 = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used
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// TODO: Remove the ifndef when the assert no longer fails on AIX.
550#ifndef _AIX
551    static_assert((__regex_word & ~(space | print | cntrl | upper | lower | alpha | digit | punct | xdigit | blank)) == __regex_word,
552                  "__regex_word can't overlap other bits");
553#endif
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
1501_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char, char, mbstate_t>)
1502#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1503_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<wchar_t, char, mbstate_t>)
1504#endif
1505_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
1506_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
1507#ifndef _LIBCPP_HAS_NO_CHAR8_T
1508_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char8_t, mbstate_t>) // C++20
1509_LIBCPP_EXTERN_TEMPLATE_EVEN_IN_DEBUG_MODE(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