Louis Dionne 5d8be4c036
[libc++] Define an internal locale API as a shim on top of the current one (#114596)
Our current locale base API is a mix of non-reserved system names that
we incorrectly (re)define and internal functions and macros starting
with __libcpp. This patch introduces a function-based internal interface
to isolate the rest of the code base from that mess, so that we can work
on refactoring how each platform implements the base API in subsequent
patches. This makes it possible to refactor how each platform implements
the base localization API without impacting the rest of the code base.
2024-11-06 09:57:08 -05:00

1514 lines
52 KiB
C++

// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___LOCALE
#define _LIBCPP___LOCALE
#include <__config>
#include <__locale_dir/locale_base_api.h>
#include <__memory/shared_ptr.h> // __shared_count
#include <__mutex/once_flag.h>
#include <__type_traits/make_unsigned.h>
#include <__utility/no_destroy.h>
#include <__utility/private_constructor_tag.h>
#include <cctype>
#include <clocale>
#include <cstdint>
#include <cstdlib>
#include <string>
// Some platforms require more includes than others. Keep the includes on all plaforms for now.
#include <cstddef>
#include <cstring>
#if _LIBCPP_HAS_WIDE_CHARACTERS
# include <cwchar>
#else
# include <__std_mbstate_t.h>
#endif
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
class _LIBCPP_EXPORTED_FROM_ABI locale;
template <class _Facet>
_LIBCPP_HIDE_FROM_ABI bool has_facet(const locale&) _NOEXCEPT;
template <class _Facet>
_LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale&);
class _LIBCPP_EXPORTED_FROM_ABI locale {
public:
// locale is essentially a shared_ptr that doesn't support weak_ptrs and never got a move constructor.
using __trivially_relocatable = locale;
// types:
class _LIBCPP_EXPORTED_FROM_ABI facet;
class _LIBCPP_EXPORTED_FROM_ABI id;
typedef int category;
static const category // values assigned here are for exposition only
none = 0,
collate = LC_COLLATE_MASK, ctype = LC_CTYPE_MASK, monetary = LC_MONETARY_MASK, numeric = LC_NUMERIC_MASK,
time = LC_TIME_MASK, messages = LC_MESSAGES_MASK, all = collate | ctype | monetary | numeric | time | messages;
// construct/copy/destroy:
locale() _NOEXCEPT;
locale(const locale&) _NOEXCEPT;
explicit locale(const char*);
explicit locale(const string&);
locale(const locale&, const char*, category);
locale(const locale&, const string&, category);
template <class _Facet>
_LIBCPP_HIDE_FROM_ABI locale(const locale&, _Facet*);
locale(const locale&, const locale&, category);
~locale();
const locale& operator=(const locale&) _NOEXCEPT;
template <class _Facet>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS locale combine(const locale&) const;
// locale operations:
string name() const;
bool operator==(const locale&) const;
#if _LIBCPP_STD_VER <= 17
_LIBCPP_HIDE_FROM_ABI bool operator!=(const locale& __y) const { return !(*this == __y); }
#endif
template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
operator()(const basic_string<_CharT, _Traits, _Allocator>&, const basic_string<_CharT, _Traits, _Allocator>&) const;
// global locale objects:
static locale global(const locale&);
static const locale& classic();
private:
class __imp;
__imp* __locale_;
template <class>
friend struct __no_destroy;
_LIBCPP_HIDE_FROM_ABI explicit locale(__private_constructor_tag, __imp* __loc) : __locale_(__loc) {}
void __install_ctor(const locale&, facet*, long);
static locale& __global();
bool has_facet(id&) const;
const facet* use_facet(id&) const;
template <class _Facet>
friend bool has_facet(const locale&) _NOEXCEPT;
template <class _Facet>
friend const _Facet& use_facet(const locale&);
};
class _LIBCPP_EXPORTED_FROM_ABI locale::facet : public __shared_count {
protected:
_LIBCPP_HIDE_FROM_ABI explicit facet(size_t __refs = 0) : __shared_count(static_cast<long>(__refs) - 1) {}
~facet() override;
// facet(const facet&) = delete; // effectively done in __shared_count
// void operator=(const facet&) = delete;
private:
void __on_zero_shared() _NOEXCEPT override;
};
class _LIBCPP_EXPORTED_FROM_ABI locale::id {
once_flag __flag_;
int32_t __id_;
static int32_t __next_id;
public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR id() : __id_(0) {}
void operator=(const id&) = delete;
id(const id&) = delete;
public: // only needed for tests
long __get();
friend class locale;
friend class locale::__imp;
};
template <class _Facet>
inline _LIBCPP_HIDE_FROM_ABI locale::locale(const locale& __other, _Facet* __f) {
__install_ctor(__other, __f, __f ? __f->id.__get() : 0);
}
template <class _Facet>
locale locale::combine(const locale& __other) const {
if (!std::has_facet<_Facet>(__other))
__throw_runtime_error("locale::combine: locale missing facet");
return locale(*this, &const_cast<_Facet&>(std::use_facet<_Facet>(__other)));
}
template <class _Facet>
inline _LIBCPP_HIDE_FROM_ABI bool has_facet(const locale& __l) _NOEXCEPT {
return __l.has_facet(_Facet::id);
}
template <class _Facet>
inline _LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale& __l) {
return static_cast<const _Facet&>(*__l.use_facet(_Facet::id));
}
// template <class _CharT> class collate;
template <class _CharT>
class _LIBCPP_TEMPLATE_VIS collate : public locale::facet {
public:
typedef _CharT char_type;
typedef basic_string<char_type> string_type;
_LIBCPP_HIDE_FROM_ABI explicit collate(size_t __refs = 0) : locale::facet(__refs) {}
_LIBCPP_HIDE_FROM_ABI int
compare(const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const {
return do_compare(__lo1, __hi1, __lo2, __hi2);
}
// FIXME(EricWF): The _LIBCPP_ALWAYS_INLINE is needed on Windows to work
// around a dllimport bug that expects an external instantiation.
_LIBCPP_HIDE_FROM_ABI _LIBCPP_ALWAYS_INLINE string_type
transform(const char_type* __lo, const char_type* __hi) const {
return do_transform(__lo, __hi);
}
_LIBCPP_HIDE_FROM_ABI long hash(const char_type* __lo, const char_type* __hi) const { return do_hash(__lo, __hi); }
static locale::id id;
protected:
~collate() override;
virtual int
do_compare(const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const;
virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const {
return string_type(__lo, __hi);
}
virtual long do_hash(const char_type* __lo, const char_type* __hi) const;
};
template <class _CharT>
locale::id collate<_CharT>::id;
template <class _CharT>
collate<_CharT>::~collate() {}
template <class _CharT>
int collate<_CharT>::do_compare(
const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const {
for (; __lo2 != __hi2; ++__lo1, ++__lo2) {
if (__lo1 == __hi1 || *__lo1 < *__lo2)
return -1;
if (*__lo2 < *__lo1)
return 1;
}
return __lo1 != __hi1;
}
template <class _CharT>
long collate<_CharT>::do_hash(const char_type* __lo, const char_type* __hi) const {
size_t __h = 0;
const size_t __sr = __CHAR_BIT__ * sizeof(size_t) - 8;
const size_t __mask = size_t(0xF) << (__sr + 4);
for (const char_type* __p = __lo; __p != __hi; ++__p) {
__h = (__h << 4) + static_cast<size_t>(*__p);
size_t __g = __h & __mask;
__h ^= __g | (__g >> __sr);
}
return static_cast<long>(__h);
}
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate<char>;
#if _LIBCPP_HAS_WIDE_CHARACTERS
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate<wchar_t>;
#endif
// template <class CharT> class collate_byname;
template <class _CharT>
class _LIBCPP_TEMPLATE_VIS collate_byname;
template <>
class _LIBCPP_EXPORTED_FROM_ABI collate_byname<char> : public collate<char> {
__locale::__locale_t __l_;
public:
typedef char char_type;
typedef basic_string<char_type> string_type;
explicit collate_byname(const char* __n, size_t __refs = 0);
explicit collate_byname(const string& __n, size_t __refs = 0);
protected:
~collate_byname() override;
int do_compare(
const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const override;
string_type do_transform(const char_type* __lo, const char_type* __hi) const override;
};
#if _LIBCPP_HAS_WIDE_CHARACTERS
template <>
class _LIBCPP_EXPORTED_FROM_ABI collate_byname<wchar_t> : public collate<wchar_t> {
__locale::__locale_t __l_;
public:
typedef wchar_t char_type;
typedef basic_string<char_type> string_type;
explicit collate_byname(const char* __n, size_t __refs = 0);
explicit collate_byname(const string& __n, size_t __refs = 0);
protected:
~collate_byname() override;
int do_compare(
const char_type* __lo1, const char_type* __hi1, const char_type* __lo2, const char_type* __hi2) const override;
string_type do_transform(const char_type* __lo, const char_type* __hi) const override;
};
#endif
template <class _CharT, class _Traits, class _Allocator>
bool locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x,
const basic_string<_CharT, _Traits, _Allocator>& __y) const {
return std::use_facet<std::collate<_CharT> >(*this).compare(
__x.data(), __x.data() + __x.size(), __y.data(), __y.data() + __y.size()) < 0;
}
// template <class charT> class ctype
class _LIBCPP_EXPORTED_FROM_ABI ctype_base {
public:
#if defined(_LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE)
typedef unsigned long mask;
static const mask space = 1 << 0;
static const mask print = 1 << 1;
static const mask cntrl = 1 << 2;
static const mask upper = 1 << 3;
static const mask lower = 1 << 4;
static const mask alpha = 1 << 5;
static const mask digit = 1 << 6;
static const mask punct = 1 << 7;
static const mask xdigit = 1 << 8;
static const mask blank = 1 << 9;
# if defined(__BIONIC__)
// Historically this was a part of regex_traits rather than ctype_base. The
// historical value of the constant is preserved for ABI compatibility.
static const mask __regex_word = 0x8000;
# else
static const mask __regex_word = 1 << 10;
# endif // defined(__BIONIC__)
#elif defined(__GLIBC__)
typedef unsigned short mask;
static const mask space = _ISspace;
static const mask print = _ISprint;
static const mask cntrl = _IScntrl;
static const mask upper = _ISupper;
static const mask lower = _ISlower;
static const mask alpha = _ISalpha;
static const mask digit = _ISdigit;
static const mask punct = _ISpunct;
static const mask xdigit = _ISxdigit;
static const mask blank = _ISblank;
# if defined(__mips__) || (BYTE_ORDER == BIG_ENDIAN)
static const mask __regex_word = static_cast<mask>(_ISbit(15));
# else
static const mask __regex_word = 0x80;
# endif
#elif defined(_LIBCPP_MSVCRT_LIKE)
typedef unsigned short mask;
static const mask space = _SPACE;
static const mask print = _BLANK | _PUNCT | _ALPHA | _DIGIT;
static const mask cntrl = _CONTROL;
static const mask upper = _UPPER;
static const mask lower = _LOWER;
static const mask alpha = _ALPHA;
static const mask digit = _DIGIT;
static const mask punct = _PUNCT;
static const mask xdigit = _HEX;
static const mask blank = _BLANK;
static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
# ifdef __APPLE__
typedef __uint32_t mask;
# elif defined(__FreeBSD__)
typedef unsigned long mask;
# elif defined(__NetBSD__)
typedef unsigned short mask;
# endif
static const mask space = _CTYPE_S;
static const mask print = _CTYPE_R;
static const mask cntrl = _CTYPE_C;
static const mask upper = _CTYPE_U;
static const mask lower = _CTYPE_L;
static const mask alpha = _CTYPE_A;
static const mask digit = _CTYPE_D;
static const mask punct = _CTYPE_P;
static const mask xdigit = _CTYPE_X;
# if defined(__NetBSD__)
static const mask blank = _CTYPE_BL;
// NetBSD defines classes up to 0x2000
// see sys/ctype_bits.h, _CTYPE_Q
static const mask __regex_word = 0x8000;
# else
static const mask blank = _CTYPE_B;
static const mask __regex_word = 0x80;
# endif
#elif defined(_AIX)
typedef unsigned int mask;
static const mask space = _ISSPACE;
static const mask print = _ISPRINT;
static const mask cntrl = _ISCNTRL;
static const mask upper = _ISUPPER;
static const mask lower = _ISLOWER;
static const mask alpha = _ISALPHA;
static const mask digit = _ISDIGIT;
static const mask punct = _ISPUNCT;
static const mask xdigit = _ISXDIGIT;
static const mask blank = _ISBLANK;
static const mask __regex_word = 0x8000;
#elif defined(_NEWLIB_VERSION)
// Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h.
typedef char mask;
// In case char is signed, static_cast is needed to avoid warning on
// positive value becomming negative.
static const mask space = static_cast<mask>(_S);
static const mask print = static_cast<mask>(_P | _U | _L | _N | _B);
static const mask cntrl = static_cast<mask>(_C);
static const mask upper = static_cast<mask>(_U);
static const mask lower = static_cast<mask>(_L);
static const mask alpha = static_cast<mask>(_U | _L);
static const mask digit = static_cast<mask>(_N);
static const mask punct = static_cast<mask>(_P);
static const mask xdigit = static_cast<mask>(_X | _N);
static const mask blank = static_cast<mask>(_B);
// mask is already fully saturated, use a different type in regex_type_traits.
static const unsigned short __regex_word = 0x100;
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT
#elif defined(__MVS__)
# if defined(__NATIVE_ASCII_F)
typedef unsigned int mask;
static const mask space = _ISSPACE_A;
static const mask print = _ISPRINT_A;
static const mask cntrl = _ISCNTRL_A;
static const mask upper = _ISUPPER_A;
static const mask lower = _ISLOWER_A;
static const mask alpha = _ISALPHA_A;
static const mask digit = _ISDIGIT_A;
static const mask punct = _ISPUNCT_A;
static const mask xdigit = _ISXDIGIT_A;
static const mask blank = _ISBLANK_A;
# else
typedef unsigned short mask;
static const mask space = __ISSPACE;
static const mask print = __ISPRINT;
static const mask cntrl = __ISCNTRL;
static const mask upper = __ISUPPER;
static const mask lower = __ISLOWER;
static const mask alpha = __ISALPHA;
static const mask digit = __ISDIGIT;
static const mask punct = __ISPUNCT;
static const mask xdigit = __ISXDIGIT;
static const mask blank = __ISBLANK;
# endif
static const mask __regex_word = 0x8000;
#else
# error unknown rune table for this platform -- do you mean to define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE?
#endif
static const mask alnum = alpha | digit;
static const mask graph = alnum | punct;
_LIBCPP_HIDE_FROM_ABI ctype_base() {}
static_assert((__regex_word & ~(std::make_unsigned<mask>::type)(space | print | cntrl | upper | lower | alpha |
digit | punct | xdigit | blank)) == __regex_word,
"__regex_word can't overlap other bits");
};
template <class _CharT>
class _LIBCPP_TEMPLATE_VIS ctype;
#if _LIBCPP_HAS_WIDE_CHARACTERS
template <>
class _LIBCPP_EXPORTED_FROM_ABI ctype<wchar_t> : public locale::facet, public ctype_base {
public:
typedef wchar_t char_type;
_LIBCPP_HIDE_FROM_ABI explicit ctype(size_t __refs = 0) : locale::facet(__refs) {}
_LIBCPP_HIDE_FROM_ABI bool is(mask __m, char_type __c) const { return do_is(__m, __c); }
_LIBCPP_HIDE_FROM_ABI const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const {
return do_is(__low, __high, __vec);
}
_LIBCPP_HIDE_FROM_ABI const char_type* scan_is(mask __m, const char_type* __low, const char_type* __high) const {
return do_scan_is(__m, __low, __high);
}
_LIBCPP_HIDE_FROM_ABI const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const {
return do_scan_not(__m, __low, __high);
}
_LIBCPP_HIDE_FROM_ABI char_type toupper(char_type __c) const { return do_toupper(__c); }
_LIBCPP_HIDE_FROM_ABI const char_type* toupper(char_type* __low, const char_type* __high) const {
return do_toupper(__low, __high);
}
_LIBCPP_HIDE_FROM_ABI char_type tolower(char_type __c) const { return do_tolower(__c); }
_LIBCPP_HIDE_FROM_ABI const char_type* tolower(char_type* __low, const char_type* __high) const {
return do_tolower(__low, __high);
}
_LIBCPP_HIDE_FROM_ABI char_type widen(char __c) const { return do_widen(__c); }
_LIBCPP_HIDE_FROM_ABI const char* widen(const char* __low, const char* __high, char_type* __to) const {
return do_widen(__low, __high, __to);
}
_LIBCPP_HIDE_FROM_ABI char narrow(char_type __c, char __dfault) const { return do_narrow(__c, __dfault); }
_LIBCPP_HIDE_FROM_ABI const char_type*
narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const {
return do_narrow(__low, __high, __dfault, __to);
}
static locale::id id;
protected:
~ctype() override;
virtual bool do_is(mask __m, char_type __c) const;
virtual const char_type* do_is(const char_type* __low, const char_type* __high, mask* __vec) const;
virtual const char_type* do_scan_is(mask __m, const char_type* __low, const char_type* __high) const;
virtual const char_type* do_scan_not(mask __m, const char_type* __low, const char_type* __high) const;
virtual char_type do_toupper(char_type) const;
virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
virtual char_type do_tolower(char_type) const;
virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
virtual char_type do_widen(char) const;
virtual const char* do_widen(const char* __low, const char* __high, char_type* __dest) const;
virtual char do_narrow(char_type, char __dfault) const;
virtual const char_type*
do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const;
};
#endif // _LIBCPP_HAS_WIDE_CHARACTERS
template <>
class _LIBCPP_EXPORTED_FROM_ABI ctype<char> : public locale::facet, public ctype_base {
const mask* __tab_;
bool __del_;
public:
typedef char char_type;
explicit ctype(const mask* __tab = nullptr, bool __del = false, size_t __refs = 0);
_LIBCPP_HIDE_FROM_ABI bool is(mask __m, char_type __c) const {
return isascii(__c) ? (__tab_[static_cast<int>(__c)] & __m) != 0 : false;
}
_LIBCPP_HIDE_FROM_ABI const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const {
for (; __low != __high; ++__low, ++__vec)
*__vec = isascii(*__low) ? __tab_[static_cast<int>(*__low)] : 0;
return __low;
}
_LIBCPP_HIDE_FROM_ABI const char_type* scan_is(mask __m, const char_type* __low, const char_type* __high) const {
for (; __low != __high; ++__low)
if (isascii(*__low) && (__tab_[static_cast<int>(*__low)] & __m))
break;
return __low;
}
_LIBCPP_HIDE_FROM_ABI const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const {
for (; __low != __high; ++__low)
if (!isascii(*__low) || !(__tab_[static_cast<int>(*__low)] & __m))
break;
return __low;
}
_LIBCPP_HIDE_FROM_ABI char_type toupper(char_type __c) const { return do_toupper(__c); }
_LIBCPP_HIDE_FROM_ABI const char_type* toupper(char_type* __low, const char_type* __high) const {
return do_toupper(__low, __high);
}
_LIBCPP_HIDE_FROM_ABI char_type tolower(char_type __c) const { return do_tolower(__c); }
_LIBCPP_HIDE_FROM_ABI const char_type* tolower(char_type* __low, const char_type* __high) const {
return do_tolower(__low, __high);
}
_LIBCPP_HIDE_FROM_ABI char_type widen(char __c) const { return do_widen(__c); }
_LIBCPP_HIDE_FROM_ABI const char* widen(const char* __low, const char* __high, char_type* __to) const {
return do_widen(__low, __high, __to);
}
_LIBCPP_HIDE_FROM_ABI char narrow(char_type __c, char __dfault) const { return do_narrow(__c, __dfault); }
_LIBCPP_HIDE_FROM_ABI const char*
narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const {
return do_narrow(__low, __high, __dfault, __to);
}
static locale::id id;
#ifdef _CACHED_RUNES
static const size_t table_size = _CACHED_RUNES;
#else
static const size_t table_size = 256; // FIXME: Don't hardcode this.
#endif
_LIBCPP_HIDE_FROM_ABI const mask* table() const _NOEXCEPT { return __tab_; }
static const mask* classic_table() _NOEXCEPT;
#if defined(__GLIBC__) || defined(__EMSCRIPTEN__)
static const int* __classic_upper_table() _NOEXCEPT;
static const int* __classic_lower_table() _NOEXCEPT;
#endif
#if defined(__NetBSD__)
static const short* __classic_upper_table() _NOEXCEPT;
static const short* __classic_lower_table() _NOEXCEPT;
#endif
#if defined(__MVS__)
static const unsigned short* __classic_upper_table() _NOEXCEPT;
static const unsigned short* __classic_lower_table() _NOEXCEPT;
#endif
protected:
~ctype() override;
virtual char_type do_toupper(char_type __c) const;
virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const;
virtual char_type do_tolower(char_type __c) const;
virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const;
virtual char_type do_widen(char __c) const;
virtual const char* do_widen(const char* __low, const char* __high, char_type* __to) const;
virtual char do_narrow(char_type __c, char __dfault) const;
virtual const char* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const;
};
// template <class CharT> class ctype_byname;
template <class _CharT>
class _LIBCPP_TEMPLATE_VIS ctype_byname;
template <>
class _LIBCPP_EXPORTED_FROM_ABI ctype_byname<char> : public ctype<char> {
__locale::__locale_t __l_;
public:
explicit ctype_byname(const char*, size_t = 0);
explicit ctype_byname(const string&, size_t = 0);
protected:
~ctype_byname() override;
char_type do_toupper(char_type) const override;
const char_type* do_toupper(char_type* __low, const char_type* __high) const override;
char_type do_tolower(char_type) const override;
const char_type* do_tolower(char_type* __low, const char_type* __high) const override;
};
#if _LIBCPP_HAS_WIDE_CHARACTERS
template <>
class _LIBCPP_EXPORTED_FROM_ABI ctype_byname<wchar_t> : public ctype<wchar_t> {
__locale::__locale_t __l_;
public:
explicit ctype_byname(const char*, size_t = 0);
explicit ctype_byname(const string&, size_t = 0);
protected:
~ctype_byname() override;
bool do_is(mask __m, char_type __c) const override;
const char_type* do_is(const char_type* __low, const char_type* __high, mask* __vec) const override;
const char_type* do_scan_is(mask __m, const char_type* __low, const char_type* __high) const override;
const char_type* do_scan_not(mask __m, const char_type* __low, const char_type* __high) const override;
char_type do_toupper(char_type) const override;
const char_type* do_toupper(char_type* __low, const char_type* __high) const override;
char_type do_tolower(char_type) const override;
const char_type* do_tolower(char_type* __low, const char_type* __high) const override;
char_type do_widen(char) const override;
const char* do_widen(const char* __low, const char* __high, char_type* __dest) const override;
char do_narrow(char_type, char __dfault) const override;
const char_type*
do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const override;
};
#endif // _LIBCPP_HAS_WIDE_CHARACTERS
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool isspace(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::space, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool isprint(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::print, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool iscntrl(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::cntrl, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool isupper(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::upper, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool islower(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::lower, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool isalpha(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::alpha, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool isdigit(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::digit, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool ispunct(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::punct, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool isxdigit(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::xdigit, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool isalnum(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::alnum, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI bool isgraph(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::graph, __c);
}
template <class _CharT>
_LIBCPP_HIDE_FROM_ABI bool isblank(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).is(ctype_base::blank, __c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI _CharT toupper(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).toupper(__c);
}
template <class _CharT>
inline _LIBCPP_HIDE_FROM_ABI _CharT tolower(_CharT __c, const locale& __loc) {
return std::use_facet<ctype<_CharT> >(__loc).tolower(__c);
}
// codecvt_base
class _LIBCPP_EXPORTED_FROM_ABI codecvt_base {
public:
_LIBCPP_HIDE_FROM_ABI codecvt_base() {}
enum result { ok, partial, error, noconv };
};
// template <class internT, class externT, class stateT> class codecvt;
template <class _InternT, class _ExternT, class _StateT>
class _LIBCPP_TEMPLATE_VIS codecvt;
// template <> class codecvt<char, char, mbstate_t>
template <>
class _LIBCPP_EXPORTED_FROM_ABI codecvt<char, char, mbstate_t> : public locale::facet, public codecvt_base {
public:
typedef char intern_type;
typedef char extern_type;
typedef mbstate_t state_type;
_LIBCPP_HIDE_FROM_ABI explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {}
_LIBCPP_HIDE_FROM_ABI result
out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const {
return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const {
return do_unshift(__st, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const {
return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI int encoding() const _NOEXCEPT { return do_encoding(); }
_LIBCPP_HIDE_FROM_ABI bool always_noconv() const _NOEXCEPT { return do_always_noconv(); }
_LIBCPP_HIDE_FROM_ABI int
length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const {
return do_length(__st, __frm, __end, __mx);
}
_LIBCPP_HIDE_FROM_ABI int max_length() const _NOEXCEPT { return do_max_length(); }
static locale::id id;
protected:
_LIBCPP_HIDE_FROM_ABI explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {}
~codecvt() override;
virtual result
do_out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const;
virtual result
do_in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const;
virtual result do_unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
virtual int do_encoding() const _NOEXCEPT;
virtual bool do_always_noconv() const _NOEXCEPT;
virtual int do_length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
virtual int do_max_length() const _NOEXCEPT;
};
// template <> class codecvt<wchar_t, char, mbstate_t>
#if _LIBCPP_HAS_WIDE_CHARACTERS
template <>
class _LIBCPP_EXPORTED_FROM_ABI codecvt<wchar_t, char, mbstate_t> : public locale::facet, public codecvt_base {
__locale::__locale_t __l_;
public:
typedef wchar_t intern_type;
typedef char extern_type;
typedef mbstate_t state_type;
explicit codecvt(size_t __refs = 0);
_LIBCPP_HIDE_FROM_ABI result
out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const {
return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const {
return do_unshift(__st, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const {
return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI int encoding() const _NOEXCEPT { return do_encoding(); }
_LIBCPP_HIDE_FROM_ABI bool always_noconv() const _NOEXCEPT { return do_always_noconv(); }
_LIBCPP_HIDE_FROM_ABI int
length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const {
return do_length(__st, __frm, __end, __mx);
}
_LIBCPP_HIDE_FROM_ABI int max_length() const _NOEXCEPT { return do_max_length(); }
static locale::id id;
protected:
explicit codecvt(const char*, size_t __refs = 0);
~codecvt() override;
virtual result
do_out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const;
virtual result
do_in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const;
virtual result do_unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
virtual int do_encoding() const _NOEXCEPT;
virtual bool do_always_noconv() const _NOEXCEPT;
virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
virtual int do_max_length() const _NOEXCEPT;
};
#endif // _LIBCPP_HAS_WIDE_CHARACTERS
// template <> class codecvt<char16_t, char, mbstate_t> // deprecated in C++20
template <>
class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXPORTED_FROM_ABI codecvt<char16_t, char, mbstate_t>
: public locale::facet, public codecvt_base {
public:
typedef char16_t intern_type;
typedef char extern_type;
typedef mbstate_t state_type;
_LIBCPP_HIDE_FROM_ABI explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {}
_LIBCPP_HIDE_FROM_ABI result
out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const {
return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const {
return do_unshift(__st, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const {
return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI int encoding() const _NOEXCEPT { return do_encoding(); }
_LIBCPP_HIDE_FROM_ABI bool always_noconv() const _NOEXCEPT { return do_always_noconv(); }
_LIBCPP_HIDE_FROM_ABI int
length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const {
return do_length(__st, __frm, __end, __mx);
}
_LIBCPP_HIDE_FROM_ABI int max_length() const _NOEXCEPT { return do_max_length(); }
static locale::id id;
protected:
_LIBCPP_HIDE_FROM_ABI explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {}
~codecvt() override;
virtual result
do_out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const;
virtual result
do_in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const;
virtual result do_unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
virtual int do_encoding() const _NOEXCEPT;
virtual bool do_always_noconv() const _NOEXCEPT;
virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
virtual int do_max_length() const _NOEXCEPT;
};
#if _LIBCPP_HAS_CHAR8_T
// template <> class codecvt<char16_t, char8_t, mbstate_t> // C++20
template <>
class _LIBCPP_EXPORTED_FROM_ABI codecvt<char16_t, char8_t, mbstate_t> : public locale::facet, public codecvt_base {
public:
typedef char16_t intern_type;
typedef char8_t extern_type;
typedef mbstate_t state_type;
_LIBCPP_HIDE_FROM_ABI explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {}
_LIBCPP_HIDE_FROM_ABI result
out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const {
return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const {
return do_unshift(__st, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const {
return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI int encoding() const _NOEXCEPT { return do_encoding(); }
_LIBCPP_HIDE_FROM_ABI bool always_noconv() const _NOEXCEPT { return do_always_noconv(); }
_LIBCPP_HIDE_FROM_ABI int
length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const {
return do_length(__st, __frm, __end, __mx);
}
_LIBCPP_HIDE_FROM_ABI int max_length() const _NOEXCEPT { return do_max_length(); }
static locale::id id;
protected:
_LIBCPP_HIDE_FROM_ABI explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {}
~codecvt() override;
virtual result
do_out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const;
virtual result
do_in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const;
virtual result do_unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
virtual int do_encoding() const _NOEXCEPT;
virtual bool do_always_noconv() const _NOEXCEPT;
virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
virtual int do_max_length() const _NOEXCEPT;
};
#endif
// template <> class codecvt<char32_t, char, mbstate_t> // deprecated in C++20
template <>
class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_EXPORTED_FROM_ABI codecvt<char32_t, char, mbstate_t>
: public locale::facet, public codecvt_base {
public:
typedef char32_t intern_type;
typedef char extern_type;
typedef mbstate_t state_type;
_LIBCPP_HIDE_FROM_ABI explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {}
_LIBCPP_HIDE_FROM_ABI result
out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const {
return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const {
return do_unshift(__st, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const {
return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI int encoding() const _NOEXCEPT { return do_encoding(); }
_LIBCPP_HIDE_FROM_ABI bool always_noconv() const _NOEXCEPT { return do_always_noconv(); }
_LIBCPP_HIDE_FROM_ABI int
length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const {
return do_length(__st, __frm, __end, __mx);
}
_LIBCPP_HIDE_FROM_ABI int max_length() const _NOEXCEPT { return do_max_length(); }
static locale::id id;
protected:
_LIBCPP_HIDE_FROM_ABI explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {}
~codecvt() override;
virtual result
do_out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const;
virtual result
do_in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const;
virtual result do_unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
virtual int do_encoding() const _NOEXCEPT;
virtual bool do_always_noconv() const _NOEXCEPT;
virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
virtual int do_max_length() const _NOEXCEPT;
};
#if _LIBCPP_HAS_CHAR8_T
// template <> class codecvt<char32_t, char8_t, mbstate_t> // C++20
template <>
class _LIBCPP_EXPORTED_FROM_ABI codecvt<char32_t, char8_t, mbstate_t> : public locale::facet, public codecvt_base {
public:
typedef char32_t intern_type;
typedef char8_t extern_type;
typedef mbstate_t state_type;
_LIBCPP_HIDE_FROM_ABI explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {}
_LIBCPP_HIDE_FROM_ABI result
out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const {
return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const {
return do_unshift(__st, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI result
in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const {
return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt);
}
_LIBCPP_HIDE_FROM_ABI int encoding() const _NOEXCEPT { return do_encoding(); }
_LIBCPP_HIDE_FROM_ABI bool always_noconv() const _NOEXCEPT { return do_always_noconv(); }
_LIBCPP_HIDE_FROM_ABI int
length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const {
return do_length(__st, __frm, __end, __mx);
}
_LIBCPP_HIDE_FROM_ABI int max_length() const _NOEXCEPT { return do_max_length(); }
static locale::id id;
protected:
_LIBCPP_HIDE_FROM_ABI explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {}
~codecvt() override;
virtual result
do_out(state_type& __st,
const intern_type* __frm,
const intern_type* __frm_end,
const intern_type*& __frm_nxt,
extern_type* __to,
extern_type* __to_end,
extern_type*& __to_nxt) const;
virtual result
do_in(state_type& __st,
const extern_type* __frm,
const extern_type* __frm_end,
const extern_type*& __frm_nxt,
intern_type* __to,
intern_type* __to_end,
intern_type*& __to_nxt) const;
virtual result do_unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const;
virtual int do_encoding() const _NOEXCEPT;
virtual bool do_always_noconv() const _NOEXCEPT;
virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const;
virtual int do_max_length() const _NOEXCEPT;
};
#endif
// template <class _InternT, class _ExternT, class _StateT> class codecvt_byname
template <class _InternT, class _ExternT, class _StateT>
class _LIBCPP_TEMPLATE_VIS codecvt_byname : public codecvt<_InternT, _ExternT, _StateT> {
public:
_LIBCPP_HIDE_FROM_ABI explicit codecvt_byname(const char* __nm, size_t __refs = 0)
: codecvt<_InternT, _ExternT, _StateT>(__nm, __refs) {}
_LIBCPP_HIDE_FROM_ABI explicit codecvt_byname(const string& __nm, size_t __refs = 0)
: codecvt<_InternT, _ExternT, _StateT>(__nm.c_str(), __refs) {}
protected:
~codecvt_byname() override;
};
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _InternT, class _ExternT, class _StateT>
codecvt_byname<_InternT, _ExternT, _StateT>::~codecvt_byname() {}
_LIBCPP_SUPPRESS_DEPRECATED_POP
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char, char, mbstate_t>;
#if _LIBCPP_HAS_WIDE_CHARACTERS
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<wchar_t, char, mbstate_t>;
#endif
extern template class _LIBCPP_DEPRECATED_IN_CXX20
_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char, mbstate_t>; // deprecated in C++20
extern template class _LIBCPP_DEPRECATED_IN_CXX20
_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char, mbstate_t>; // deprecated in C++20
#if _LIBCPP_HAS_CHAR8_T
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char8_t, mbstate_t>; // C++20
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char8_t, mbstate_t>; // C++20
#endif
template <size_t _Np>
struct __narrow_to_utf8 {
template <class _OutputIterator, class _CharT>
_OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const;
};
template <>
struct __narrow_to_utf8<8> {
template <class _OutputIterator, class _CharT>
_LIBCPP_HIDE_FROM_ABI _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const {
for (; __wb < __we; ++__wb, ++__s)
*__s = *__wb;
return __s;
}
};
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <>
struct _LIBCPP_EXPORTED_FROM_ABI __narrow_to_utf8<16> : public codecvt<char16_t, char, mbstate_t> {
_LIBCPP_HIDE_FROM_ABI __narrow_to_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
_LIBCPP_SUPPRESS_DEPRECATED_POP
~__narrow_to_utf8() override;
template <class _OutputIterator, class _CharT>
_LIBCPP_HIDE_FROM_ABI _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const {
result __r = ok;
mbstate_t __mb;
while (__wb < __we && __r != error) {
const int __sz = 32;
char __buf[__sz];
char* __bn;
const char16_t* __wn = (const char16_t*)__wb;
__r = do_out(__mb, (const char16_t*)__wb, (const char16_t*)__we, __wn, __buf, __buf + __sz, __bn);
if (__r == codecvt_base::error || __wn == (const char16_t*)__wb)
__throw_runtime_error("locale not supported");
for (const char* __p = __buf; __p < __bn; ++__p, ++__s)
*__s = *__p;
__wb = (const _CharT*)__wn;
}
return __s;
}
};
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <>
struct _LIBCPP_EXPORTED_FROM_ABI __narrow_to_utf8<32> : public codecvt<char32_t, char, mbstate_t> {
_LIBCPP_HIDE_FROM_ABI __narrow_to_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
_LIBCPP_SUPPRESS_DEPRECATED_POP
~__narrow_to_utf8() override;
template <class _OutputIterator, class _CharT>
_LIBCPP_HIDE_FROM_ABI _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const {
result __r = ok;
mbstate_t __mb;
while (__wb < __we && __r != error) {
const int __sz = 32;
char __buf[__sz];
char* __bn;
const char32_t* __wn = (const char32_t*)__wb;
__r = do_out(__mb, (const char32_t*)__wb, (const char32_t*)__we, __wn, __buf, __buf + __sz, __bn);
if (__r == codecvt_base::error || __wn == (const char32_t*)__wb)
__throw_runtime_error("locale not supported");
for (const char* __p = __buf; __p < __bn; ++__p, ++__s)
*__s = *__p;
__wb = (const _CharT*)__wn;
}
return __s;
}
};
template <size_t _Np>
struct __widen_from_utf8 {
template <class _OutputIterator>
_OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const;
};
template <>
struct __widen_from_utf8<8> {
template <class _OutputIterator>
_LIBCPP_HIDE_FROM_ABI _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const {
for (; __nb < __ne; ++__nb, ++__s)
*__s = *__nb;
return __s;
}
};
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <>
struct _LIBCPP_EXPORTED_FROM_ABI __widen_from_utf8<16> : public codecvt<char16_t, char, mbstate_t> {
_LIBCPP_HIDE_FROM_ABI __widen_from_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
_LIBCPP_SUPPRESS_DEPRECATED_POP
~__widen_from_utf8() override;
template <class _OutputIterator>
_LIBCPP_HIDE_FROM_ABI _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const {
result __r = ok;
mbstate_t __mb;
while (__nb < __ne && __r != error) {
const int __sz = 32;
char16_t __buf[__sz];
char16_t* __bn;
const char* __nn = __nb;
__r = do_in(__mb, __nb, __ne - __nb > __sz ? __nb + __sz : __ne, __nn, __buf, __buf + __sz, __bn);
if (__r == codecvt_base::error || __nn == __nb)
__throw_runtime_error("locale not supported");
for (const char16_t* __p = __buf; __p < __bn; ++__p, ++__s)
*__s = *__p;
__nb = __nn;
}
return __s;
}
};
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <>
struct _LIBCPP_EXPORTED_FROM_ABI __widen_from_utf8<32> : public codecvt<char32_t, char, mbstate_t> {
_LIBCPP_HIDE_FROM_ABI __widen_from_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
_LIBCPP_SUPPRESS_DEPRECATED_POP
~__widen_from_utf8() override;
template <class _OutputIterator>
_LIBCPP_HIDE_FROM_ABI _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const {
result __r = ok;
mbstate_t __mb;
while (__nb < __ne && __r != error) {
const int __sz = 32;
char32_t __buf[__sz];
char32_t* __bn;
const char* __nn = __nb;
__r = do_in(__mb, __nb, __ne - __nb > __sz ? __nb + __sz : __ne, __nn, __buf, __buf + __sz, __bn);
if (__r == codecvt_base::error || __nn == __nb)
__throw_runtime_error("locale not supported");
for (const char32_t* __p = __buf; __p < __bn; ++__p, ++__s)
*__s = *__p;
__nb = __nn;
}
return __s;
}
};
// template <class charT> class numpunct
template <class _CharT>
class _LIBCPP_TEMPLATE_VIS numpunct;
template <>
class _LIBCPP_EXPORTED_FROM_ABI numpunct<char> : public locale::facet {
public:
typedef char char_type;
typedef basic_string<char_type> string_type;
explicit numpunct(size_t __refs = 0);
_LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); }
_LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); }
_LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); }
_LIBCPP_HIDE_FROM_ABI string_type truename() const { return do_truename(); }
_LIBCPP_HIDE_FROM_ABI string_type falsename() const { return do_falsename(); }
static locale::id id;
protected:
~numpunct() override;
virtual char_type do_decimal_point() const;
virtual char_type do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_truename() const;
virtual string_type do_falsename() const;
char_type __decimal_point_;
char_type __thousands_sep_;
string __grouping_;
};
#if _LIBCPP_HAS_WIDE_CHARACTERS
template <>
class _LIBCPP_EXPORTED_FROM_ABI numpunct<wchar_t> : public locale::facet {
public:
typedef wchar_t char_type;
typedef basic_string<char_type> string_type;
explicit numpunct(size_t __refs = 0);
_LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); }
_LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); }
_LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); }
_LIBCPP_HIDE_FROM_ABI string_type truename() const { return do_truename(); }
_LIBCPP_HIDE_FROM_ABI string_type falsename() const { return do_falsename(); }
static locale::id id;
protected:
~numpunct() override;
virtual char_type do_decimal_point() const;
virtual char_type do_thousands_sep() const;
virtual string do_grouping() const;
virtual string_type do_truename() const;
virtual string_type do_falsename() const;
char_type __decimal_point_;
char_type __thousands_sep_;
string __grouping_;
};
#endif // _LIBCPP_HAS_WIDE_CHARACTERS
// template <class charT> class numpunct_byname
template <class _CharT>
class _LIBCPP_TEMPLATE_VIS numpunct_byname;
template <>
class _LIBCPP_EXPORTED_FROM_ABI numpunct_byname<char> : public numpunct<char> {
public:
typedef char char_type;
typedef basic_string<char_type> string_type;
explicit numpunct_byname(const char* __nm, size_t __refs = 0);
explicit numpunct_byname(const string& __nm, size_t __refs = 0);
protected:
~numpunct_byname() override;
private:
void __init(const char*);
};
#if _LIBCPP_HAS_WIDE_CHARACTERS
template <>
class _LIBCPP_EXPORTED_FROM_ABI numpunct_byname<wchar_t> : public numpunct<wchar_t> {
public:
typedef wchar_t char_type;
typedef basic_string<char_type> string_type;
explicit numpunct_byname(const char* __nm, size_t __refs = 0);
explicit numpunct_byname(const string& __nm, size_t __refs = 0);
protected:
~numpunct_byname() override;
private:
void __init(const char*);
};
#endif // _LIBCPP_HAS_WIDE_CHARACTERS
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___LOCALE