diff --git a/include/__string/char_traits.h b/include/__string/char_traits.h index 5880d3a..91b413a 100644 --- a/include/__string/char_traits.h +++ b/include/__string/char_traits.h @@ -73,6 +73,106 @@ exposition-only to document what members a char_traits specialization should pro }; */ +// +// Temporary extension to provide a base template for std::char_traits. +// TODO(LLVM-19): Remove this class. +// +#if !defined(_LIBCPP_CHAR_TRAITS_REMOVE_BASE_SPECIALIZATION) +template +struct _LIBCPP_DEPRECATED_( + "char_traits for T not equal to char, wchar_t, char8_t, char16_t or char32_t is non-standard and is provided " + "for a temporary period. It will be removed in LLVM 19, so please migrate off of it.") char_traits { + using char_type = _CharT; + using int_type = int; + using off_type = streamoff; + using pos_type = streampos; + using state_type = mbstate_t; + + static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_HIDE_FROM_ABI + assign(char_type& __c1, const char_type& __c2) _NOEXCEPT { + __c1 = __c2; + } + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT { + return __c1 == __c2; + } + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT { + return __c1 < __c2; + } + + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int + compare(const char_type* __s1, const char_type* __s2, size_t __n) { + for (; __n; --__n, ++__s1, ++__s2) { + if (lt(*__s1, *__s2)) + return -1; + if (lt(*__s2, *__s1)) + return 1; + } + return 0; + } + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) { + size_t __len = 0; + for (; !eq(*__s, char_type(0)); ++__s) + ++__len; + return __len; + } + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) { + for (; __n; --__n) { + if (eq(*__s, __a)) + return __s; + ++__s; + } + return nullptr; + } + static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) { + if (__n == 0) + return __s1; + char_type* __r = __s1; + if (__s1 < __s2) { + for (; __n; --__n, ++__s1, ++__s2) + assign(*__s1, *__s2); + } else if (__s2 < __s1) { + __s1 += __n; + __s2 += __n; + for (; __n; --__n) + assign(*--__s1, *--__s2); + } + return __r; + } + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) { + _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2), + "char_traits::copy: source and destination ranges overlap"); + char_type* __r = __s1; + for (; __n; --__n, ++__s1, ++__s2) + assign(*__s1, *__s2); + return __r; + } + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type* + assign(char_type* __s, size_t __n, char_type __a) { + char_type* __r = __s; + for (; __n; --__n, ++__s) + assign(*__s, __a); + return __r; + } + + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT { + return eq_int_type(__c, eof()) ? ~eof() : __c; + } + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT { + return char_type(__c); + } + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT { + return int_type(__c); + } + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT { + return __c1 == __c2; + } + static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return int_type(EOF); } +}; +#endif // !defined(_LIBCPP_CHAR_TRAITS_REMOVE_BASE_SPECIALIZATION) + // char_traits template <>