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