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