181ad6265SDimitry Andric //===----------------------------------------------------------------------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #ifndef _LIBCPP___STRING_CHAR_TRAITS_H 1081ad6265SDimitry Andric #define _LIBCPP___STRING_CHAR_TRAITS_H 1181ad6265SDimitry Andric 1281ad6265SDimitry Andric #include <__algorithm/copy_n.h> 1381ad6265SDimitry Andric #include <__algorithm/fill_n.h> 1481ad6265SDimitry Andric #include <__algorithm/find_end.h> 1581ad6265SDimitry Andric #include <__algorithm/find_first_of.h> 1681ad6265SDimitry Andric #include <__algorithm/min.h> 1781ad6265SDimitry Andric #include <__config> 1881ad6265SDimitry Andric #include <__functional/hash.h> 1981ad6265SDimitry Andric #include <__iterator/iterator_traits.h> 2081ad6265SDimitry Andric #include <cstdint> 2181ad6265SDimitry Andric #include <cstdio> 2281ad6265SDimitry Andric #include <cstring> 2381ad6265SDimitry Andric #include <iosfwd> 2481ad6265SDimitry Andric #include <type_traits> 2581ad6265SDimitry Andric 2681ad6265SDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2781ad6265SDimitry Andric # include <cwchar> // for wmemcpy 2881ad6265SDimitry Andric #endif 2981ad6265SDimitry Andric 3081ad6265SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 3181ad6265SDimitry Andric # pragma GCC system_header 3281ad6265SDimitry Andric #endif 3381ad6265SDimitry Andric 3481ad6265SDimitry Andric _LIBCPP_PUSH_MACROS 3581ad6265SDimitry Andric #include <__undef_macros> 3681ad6265SDimitry Andric 3781ad6265SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 3881ad6265SDimitry Andric 3981ad6265SDimitry Andric template <class _CharT> 4081ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits 4181ad6265SDimitry Andric { 4281ad6265SDimitry Andric typedef _CharT char_type; 4381ad6265SDimitry Andric typedef int int_type; 4481ad6265SDimitry Andric typedef streamoff off_type; 4581ad6265SDimitry Andric typedef streampos pos_type; 4681ad6265SDimitry Andric typedef mbstate_t state_type; 4781ad6265SDimitry Andric 4881ad6265SDimitry Andric static inline void _LIBCPP_CONSTEXPR_AFTER_CXX14 4981ad6265SDimitry Andric assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} 5081ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 5181ad6265SDimitry Andric {return __c1 == __c2;} 5281ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 5381ad6265SDimitry Andric {return __c1 < __c2;} 5481ad6265SDimitry Andric 5581ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX14 5681ad6265SDimitry Andric int compare(const char_type* __s1, const char_type* __s2, size_t __n); 5781ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 5881ad6265SDimitry Andric size_t length(const char_type* __s); 5981ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 6081ad6265SDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a); 6181ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX17 6281ad6265SDimitry Andric char_type* move(char_type* __s1, const char_type* __s2, size_t __n); 6381ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY 6481ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX17 6581ad6265SDimitry Andric char_type* copy(char_type* __s1, const char_type* __s2, size_t __n); 6681ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY 6781ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX17 6881ad6265SDimitry Andric char_type* assign(char_type* __s, size_t __n, char_type __a); 6981ad6265SDimitry Andric 7081ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 7181ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 7281ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 7381ad6265SDimitry Andric {return char_type(__c);} 7481ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 7581ad6265SDimitry Andric {return int_type(__c);} 7681ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 7781ad6265SDimitry Andric {return __c1 == __c2;} 7881ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 7981ad6265SDimitry Andric {return int_type(EOF);} 8081ad6265SDimitry Andric }; 8181ad6265SDimitry Andric 8281ad6265SDimitry Andric template <class _CharT> 8381ad6265SDimitry Andric _LIBCPP_CONSTEXPR_AFTER_CXX14 int 8481ad6265SDimitry Andric char_traits<_CharT>::compare(const char_type* __s1, const char_type* __s2, size_t __n) 8581ad6265SDimitry Andric { 8681ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 8781ad6265SDimitry Andric { 8881ad6265SDimitry Andric if (lt(*__s1, *__s2)) 8981ad6265SDimitry Andric return -1; 9081ad6265SDimitry Andric if (lt(*__s2, *__s1)) 9181ad6265SDimitry Andric return 1; 9281ad6265SDimitry Andric } 9381ad6265SDimitry Andric return 0; 9481ad6265SDimitry Andric } 9581ad6265SDimitry Andric 9681ad6265SDimitry Andric template <class _CharT> 9781ad6265SDimitry Andric inline 9881ad6265SDimitry Andric _LIBCPP_CONSTEXPR_AFTER_CXX14 size_t 9981ad6265SDimitry Andric char_traits<_CharT>::length(const char_type* __s) 10081ad6265SDimitry Andric { 10181ad6265SDimitry Andric size_t __len = 0; 10281ad6265SDimitry Andric for (; !eq(*__s, char_type(0)); ++__s) 10381ad6265SDimitry Andric ++__len; 10481ad6265SDimitry Andric return __len; 10581ad6265SDimitry Andric } 10681ad6265SDimitry Andric 10781ad6265SDimitry Andric template <class _CharT> 10881ad6265SDimitry Andric inline 10981ad6265SDimitry Andric _LIBCPP_CONSTEXPR_AFTER_CXX14 const _CharT* 11081ad6265SDimitry Andric char_traits<_CharT>::find(const char_type* __s, size_t __n, const char_type& __a) 11181ad6265SDimitry Andric { 11281ad6265SDimitry Andric for (; __n; --__n) 11381ad6265SDimitry Andric { 11481ad6265SDimitry Andric if (eq(*__s, __a)) 11581ad6265SDimitry Andric return __s; 11681ad6265SDimitry Andric ++__s; 11781ad6265SDimitry Andric } 11881ad6265SDimitry Andric return nullptr; 11981ad6265SDimitry Andric } 12081ad6265SDimitry Andric 12181ad6265SDimitry Andric template <class _CharT> 12281ad6265SDimitry Andric _LIBCPP_CONSTEXPR_AFTER_CXX17 _CharT* 12381ad6265SDimitry Andric char_traits<_CharT>::move(char_type* __s1, const char_type* __s2, size_t __n) 12481ad6265SDimitry Andric { 12581ad6265SDimitry Andric if (__n == 0) return __s1; 12681ad6265SDimitry Andric char_type* __r = __s1; 12781ad6265SDimitry Andric if (__s1 < __s2) 12881ad6265SDimitry Andric { 12981ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 13081ad6265SDimitry Andric assign(*__s1, *__s2); 13181ad6265SDimitry Andric } 13281ad6265SDimitry Andric else if (__s2 < __s1) 13381ad6265SDimitry Andric { 13481ad6265SDimitry Andric __s1 += __n; 13581ad6265SDimitry Andric __s2 += __n; 13681ad6265SDimitry Andric for (; __n; --__n) 13781ad6265SDimitry Andric assign(*--__s1, *--__s2); 13881ad6265SDimitry Andric } 13981ad6265SDimitry Andric return __r; 14081ad6265SDimitry Andric } 14181ad6265SDimitry Andric 14281ad6265SDimitry Andric template <class _CharT> 14381ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX17 14481ad6265SDimitry Andric _CharT* 14581ad6265SDimitry Andric char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n) 14681ad6265SDimitry Andric { 14781ad6265SDimitry Andric if (!__libcpp_is_constant_evaluated()) { 14881ad6265SDimitry Andric _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); 14981ad6265SDimitry Andric } 15081ad6265SDimitry Andric char_type* __r = __s1; 15181ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 15281ad6265SDimitry Andric assign(*__s1, *__s2); 15381ad6265SDimitry Andric return __r; 15481ad6265SDimitry Andric } 15581ad6265SDimitry Andric 15681ad6265SDimitry Andric template <class _CharT> 15781ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX17 15881ad6265SDimitry Andric _CharT* 15981ad6265SDimitry Andric char_traits<_CharT>::assign(char_type* __s, size_t __n, char_type __a) 16081ad6265SDimitry Andric { 16181ad6265SDimitry Andric char_type* __r = __s; 16281ad6265SDimitry Andric for (; __n; --__n, ++__s) 16381ad6265SDimitry Andric assign(*__s, __a); 16481ad6265SDimitry Andric return __r; 16581ad6265SDimitry Andric } 16681ad6265SDimitry Andric 16781ad6265SDimitry Andric template <class _CharT> 16881ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 16981ad6265SDimitry Andric _CharT* __char_traits_move(_CharT* __dest, const _CharT* __source, size_t __n) _NOEXCEPT 17081ad6265SDimitry Andric { 17181ad6265SDimitry Andric #ifdef _LIBCPP_COMPILER_GCC 17281ad6265SDimitry Andric if (__libcpp_is_constant_evaluated()) { 17381ad6265SDimitry Andric if (__n == 0) 17481ad6265SDimitry Andric return __dest; 17581ad6265SDimitry Andric _CharT* __allocation = new _CharT[__n]; 17681ad6265SDimitry Andric std::copy_n(__source, __n, __allocation); 17781ad6265SDimitry Andric std::copy_n(static_cast<const _CharT*>(__allocation), __n, __dest); 17881ad6265SDimitry Andric delete[] __allocation; 17981ad6265SDimitry Andric return __dest; 18081ad6265SDimitry Andric } 18181ad6265SDimitry Andric #endif 18281ad6265SDimitry Andric ::__builtin_memmove(__dest, __source, __n * sizeof(_CharT)); 18381ad6265SDimitry Andric return __dest; 18481ad6265SDimitry Andric } 18581ad6265SDimitry Andric 18681ad6265SDimitry Andric // char_traits<char> 18781ad6265SDimitry Andric 18881ad6265SDimitry Andric template <> 18981ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char> 19081ad6265SDimitry Andric { 19181ad6265SDimitry Andric typedef char char_type; 19281ad6265SDimitry Andric typedef int int_type; 19381ad6265SDimitry Andric typedef streamoff off_type; 19481ad6265SDimitry Andric typedef streampos pos_type; 19581ad6265SDimitry Andric typedef mbstate_t state_type; 19681ad6265SDimitry Andric 19781ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 19881ad6265SDimitry Andric void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} 19981ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 20081ad6265SDimitry Andric {return __c1 == __c2;} 20181ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 20281ad6265SDimitry Andric {return (unsigned char)__c1 < (unsigned char)__c2;} 20381ad6265SDimitry Andric 20481ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX14 20581ad6265SDimitry Andric int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; 20681ad6265SDimitry Andric 20781ad6265SDimitry Andric static inline size_t _LIBCPP_CONSTEXPR_AFTER_CXX14 length(const char_type* __s) _NOEXCEPT { 20881ad6265SDimitry Andric // GCC currently does not support __builtin_strlen during constant evaluation. 20981ad6265SDimitry Andric // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70816 21081ad6265SDimitry Andric #ifdef _LIBCPP_COMPILER_GCC 21181ad6265SDimitry Andric if (__libcpp_is_constant_evaluated()) { 21281ad6265SDimitry Andric size_t __i = 0; 21381ad6265SDimitry Andric for (; __s[__i] != char_type('\0'); ++__i) 21481ad6265SDimitry Andric ; 21581ad6265SDimitry Andric return __i; 21681ad6265SDimitry Andric } 21781ad6265SDimitry Andric #endif 21881ad6265SDimitry Andric return __builtin_strlen(__s); 21981ad6265SDimitry Andric } 22081ad6265SDimitry Andric 22181ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX14 22281ad6265SDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; 22381ad6265SDimitry Andric 22481ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 22581ad6265SDimitry Andric char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 22681ad6265SDimitry Andric return std::__char_traits_move(__s1, __s2, __n); 22781ad6265SDimitry Andric } 22881ad6265SDimitry Andric 22981ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 23081ad6265SDimitry Andric char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 23181ad6265SDimitry Andric if (!__libcpp_is_constant_evaluated()) 23281ad6265SDimitry Andric _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); 23381ad6265SDimitry Andric std::copy_n(__s2, __n, __s1); 23481ad6265SDimitry Andric return __s1; 23581ad6265SDimitry Andric } 23681ad6265SDimitry Andric 23781ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 23881ad6265SDimitry Andric char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { 23981ad6265SDimitry Andric std::fill_n(__s, __n, __a); 24081ad6265SDimitry Andric return __s; 24181ad6265SDimitry Andric } 24281ad6265SDimitry Andric 24381ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 24481ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 24581ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 24681ad6265SDimitry Andric {return char_type(__c);} 24781ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 24881ad6265SDimitry Andric {return int_type((unsigned char)__c);} 24981ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 25081ad6265SDimitry Andric {return __c1 == __c2;} 25181ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 25281ad6265SDimitry Andric {return int_type(EOF);} 25381ad6265SDimitry Andric }; 25481ad6265SDimitry Andric 25581ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 25681ad6265SDimitry Andric int 25781ad6265SDimitry Andric char_traits<char>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT 25881ad6265SDimitry Andric { 25981ad6265SDimitry Andric if (__n == 0) 26081ad6265SDimitry Andric return 0; 26181ad6265SDimitry Andric #if __has_feature(cxx_constexpr_string_builtins) 26281ad6265SDimitry Andric return __builtin_memcmp(__s1, __s2, __n); 26381ad6265SDimitry Andric #elif _LIBCPP_STD_VER <= 14 26481ad6265SDimitry Andric return _VSTD::memcmp(__s1, __s2, __n); 26581ad6265SDimitry Andric #else 26681ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 26781ad6265SDimitry Andric { 26881ad6265SDimitry Andric if (lt(*__s1, *__s2)) 26981ad6265SDimitry Andric return -1; 27081ad6265SDimitry Andric if (lt(*__s2, *__s1)) 27181ad6265SDimitry Andric return 1; 27281ad6265SDimitry Andric } 27381ad6265SDimitry Andric return 0; 27481ad6265SDimitry Andric #endif 27581ad6265SDimitry Andric } 27681ad6265SDimitry Andric 27781ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 27881ad6265SDimitry Andric const char* 27981ad6265SDimitry Andric char_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT 28081ad6265SDimitry Andric { 28181ad6265SDimitry Andric if (__n == 0) 28281ad6265SDimitry Andric return nullptr; 28381ad6265SDimitry Andric #if __has_feature(cxx_constexpr_string_builtins) 28481ad6265SDimitry Andric return __builtin_char_memchr(__s, to_int_type(__a), __n); 28581ad6265SDimitry Andric #elif _LIBCPP_STD_VER <= 14 28681ad6265SDimitry Andric return (const char_type*) _VSTD::memchr(__s, to_int_type(__a), __n); 28781ad6265SDimitry Andric #else 28881ad6265SDimitry Andric for (; __n; --__n) 28981ad6265SDimitry Andric { 29081ad6265SDimitry Andric if (eq(*__s, __a)) 29181ad6265SDimitry Andric return __s; 29281ad6265SDimitry Andric ++__s; 29381ad6265SDimitry Andric } 29481ad6265SDimitry Andric return nullptr; 29581ad6265SDimitry Andric #endif 29681ad6265SDimitry Andric } 29781ad6265SDimitry Andric 29881ad6265SDimitry Andric 29981ad6265SDimitry Andric // char_traits<wchar_t> 30081ad6265SDimitry Andric 30181ad6265SDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 30281ad6265SDimitry Andric template <> 30381ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t> 30481ad6265SDimitry Andric { 30581ad6265SDimitry Andric typedef wchar_t char_type; 30681ad6265SDimitry Andric typedef wint_t int_type; 30781ad6265SDimitry Andric typedef streamoff off_type; 30881ad6265SDimitry Andric typedef streampos pos_type; 30981ad6265SDimitry Andric typedef mbstate_t state_type; 31081ad6265SDimitry Andric 31181ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 31281ad6265SDimitry Andric void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} 31381ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 31481ad6265SDimitry Andric {return __c1 == __c2;} 31581ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 31681ad6265SDimitry Andric {return __c1 < __c2;} 31781ad6265SDimitry Andric 31881ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX14 31981ad6265SDimitry Andric int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; 32081ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX14 32181ad6265SDimitry Andric size_t length(const char_type* __s) _NOEXCEPT; 32281ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX14 32381ad6265SDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; 32481ad6265SDimitry Andric 32581ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 32681ad6265SDimitry Andric char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 32781ad6265SDimitry Andric return std::__char_traits_move(__s1, __s2, __n); 32881ad6265SDimitry Andric } 32981ad6265SDimitry Andric 33081ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 33181ad6265SDimitry Andric char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 33281ad6265SDimitry Andric if (!__libcpp_is_constant_evaluated()) 33381ad6265SDimitry Andric _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); 33481ad6265SDimitry Andric std::copy_n(__s2, __n, __s1); 33581ad6265SDimitry Andric return __s1; 33681ad6265SDimitry Andric } 33781ad6265SDimitry Andric 33881ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX17 33981ad6265SDimitry Andric char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { 34081ad6265SDimitry Andric std::fill_n(__s, __n, __a); 34181ad6265SDimitry Andric return __s; 34281ad6265SDimitry Andric } 34381ad6265SDimitry Andric 34481ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 34581ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 34681ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 34781ad6265SDimitry Andric {return char_type(__c);} 34881ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 34981ad6265SDimitry Andric {return int_type(__c);} 35081ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 35181ad6265SDimitry Andric {return __c1 == __c2;} 35281ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 35381ad6265SDimitry Andric {return int_type(WEOF);} 35481ad6265SDimitry Andric }; 35581ad6265SDimitry Andric 35681ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 35781ad6265SDimitry Andric int 35881ad6265SDimitry Andric char_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT 35981ad6265SDimitry Andric { 36081ad6265SDimitry Andric if (__n == 0) 36181ad6265SDimitry Andric return 0; 36281ad6265SDimitry Andric #if __has_feature(cxx_constexpr_string_builtins) 36381ad6265SDimitry Andric return __builtin_wmemcmp(__s1, __s2, __n); 36481ad6265SDimitry Andric #elif _LIBCPP_STD_VER <= 14 36581ad6265SDimitry Andric return _VSTD::wmemcmp(__s1, __s2, __n); 36681ad6265SDimitry Andric #else 36781ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 36881ad6265SDimitry Andric { 36981ad6265SDimitry Andric if (lt(*__s1, *__s2)) 37081ad6265SDimitry Andric return -1; 37181ad6265SDimitry Andric if (lt(*__s2, *__s1)) 37281ad6265SDimitry Andric return 1; 37381ad6265SDimitry Andric } 37481ad6265SDimitry Andric return 0; 37581ad6265SDimitry Andric #endif 37681ad6265SDimitry Andric } 37781ad6265SDimitry Andric 37881ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 37981ad6265SDimitry Andric size_t 38081ad6265SDimitry Andric char_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT 38181ad6265SDimitry Andric { 38281ad6265SDimitry Andric #if __has_feature(cxx_constexpr_string_builtins) 38381ad6265SDimitry Andric return __builtin_wcslen(__s); 38481ad6265SDimitry Andric #elif _LIBCPP_STD_VER <= 14 38581ad6265SDimitry Andric return _VSTD::wcslen(__s); 38681ad6265SDimitry Andric #else 38781ad6265SDimitry Andric size_t __len = 0; 38881ad6265SDimitry Andric for (; !eq(*__s, char_type(0)); ++__s) 38981ad6265SDimitry Andric ++__len; 39081ad6265SDimitry Andric return __len; 39181ad6265SDimitry Andric #endif 39281ad6265SDimitry Andric } 39381ad6265SDimitry Andric 39481ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 39581ad6265SDimitry Andric const wchar_t* 39681ad6265SDimitry Andric char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT 39781ad6265SDimitry Andric { 39881ad6265SDimitry Andric if (__n == 0) 39981ad6265SDimitry Andric return nullptr; 40081ad6265SDimitry Andric #if __has_feature(cxx_constexpr_string_builtins) 40181ad6265SDimitry Andric return __builtin_wmemchr(__s, __a, __n); 40281ad6265SDimitry Andric #elif _LIBCPP_STD_VER <= 14 40381ad6265SDimitry Andric return _VSTD::wmemchr(__s, __a, __n); 40481ad6265SDimitry Andric #else 40581ad6265SDimitry Andric for (; __n; --__n) 40681ad6265SDimitry Andric { 40781ad6265SDimitry Andric if (eq(*__s, __a)) 40881ad6265SDimitry Andric return __s; 40981ad6265SDimitry Andric ++__s; 41081ad6265SDimitry Andric } 41181ad6265SDimitry Andric return nullptr; 41281ad6265SDimitry Andric #endif 41381ad6265SDimitry Andric } 41481ad6265SDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 41581ad6265SDimitry Andric 41681ad6265SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T 41781ad6265SDimitry Andric 41881ad6265SDimitry Andric template <> 41981ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t> 42081ad6265SDimitry Andric { 42181ad6265SDimitry Andric typedef char8_t char_type; 42281ad6265SDimitry Andric typedef unsigned int int_type; 42381ad6265SDimitry Andric typedef streamoff off_type; 42481ad6265SDimitry Andric typedef u8streampos pos_type; 42581ad6265SDimitry Andric typedef mbstate_t state_type; 42681ad6265SDimitry Andric 42781ad6265SDimitry Andric static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept 42881ad6265SDimitry Andric {__c1 = __c2;} 42981ad6265SDimitry Andric static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept 43081ad6265SDimitry Andric {return __c1 == __c2;} 43181ad6265SDimitry Andric static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept 43281ad6265SDimitry Andric {return __c1 < __c2;} 43381ad6265SDimitry Andric 43481ad6265SDimitry Andric static constexpr 43581ad6265SDimitry Andric int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; 43681ad6265SDimitry Andric 43781ad6265SDimitry Andric static constexpr 43881ad6265SDimitry Andric size_t length(const char_type* __s) _NOEXCEPT; 43981ad6265SDimitry Andric 44081ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY static constexpr 44181ad6265SDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; 44281ad6265SDimitry Andric 44381ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX17 44481ad6265SDimitry Andric char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 44581ad6265SDimitry Andric return std::__char_traits_move(__s1, __s2, __n); 44681ad6265SDimitry Andric } 44781ad6265SDimitry Andric 44881ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX17 44981ad6265SDimitry Andric char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 45081ad6265SDimitry Andric if (!__libcpp_is_constant_evaluated()) 45181ad6265SDimitry Andric _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); 45281ad6265SDimitry Andric std::copy_n(__s2, __n, __s1); 45381ad6265SDimitry Andric return __s1; 45481ad6265SDimitry Andric } 45581ad6265SDimitry Andric 45681ad6265SDimitry Andric static _LIBCPP_CONSTEXPR_AFTER_CXX17 45781ad6265SDimitry Andric char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { 45881ad6265SDimitry Andric std::fill_n(__s, __n, __a); 45981ad6265SDimitry Andric return __s; 46081ad6265SDimitry Andric } 46181ad6265SDimitry Andric 46281ad6265SDimitry Andric static inline constexpr int_type not_eof(int_type __c) noexcept 46381ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 46481ad6265SDimitry Andric static inline constexpr char_type to_char_type(int_type __c) noexcept 46581ad6265SDimitry Andric {return char_type(__c);} 46681ad6265SDimitry Andric static inline constexpr int_type to_int_type(char_type __c) noexcept 46781ad6265SDimitry Andric {return int_type(__c);} 46881ad6265SDimitry Andric static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept 46981ad6265SDimitry Andric {return __c1 == __c2;} 47081ad6265SDimitry Andric static inline constexpr int_type eof() noexcept 47181ad6265SDimitry Andric {return int_type(EOF);} 47281ad6265SDimitry Andric }; 47381ad6265SDimitry Andric 47481ad6265SDimitry Andric // TODO use '__builtin_strlen' if it ever supports char8_t ?? 47581ad6265SDimitry Andric inline constexpr 47681ad6265SDimitry Andric size_t 47781ad6265SDimitry Andric char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT 47881ad6265SDimitry Andric { 47981ad6265SDimitry Andric size_t __len = 0; 48081ad6265SDimitry Andric for (; !eq(*__s, char_type(0)); ++__s) 48181ad6265SDimitry Andric ++__len; 48281ad6265SDimitry Andric return __len; 48381ad6265SDimitry Andric } 48481ad6265SDimitry Andric 48581ad6265SDimitry Andric inline constexpr 48681ad6265SDimitry Andric int 48781ad6265SDimitry Andric char_traits<char8_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT 48881ad6265SDimitry Andric { 48981ad6265SDimitry Andric #if __has_feature(cxx_constexpr_string_builtins) 49081ad6265SDimitry Andric return __builtin_memcmp(__s1, __s2, __n); 49181ad6265SDimitry Andric #else 49281ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 49381ad6265SDimitry Andric { 49481ad6265SDimitry Andric if (lt(*__s1, *__s2)) 49581ad6265SDimitry Andric return -1; 49681ad6265SDimitry Andric if (lt(*__s2, *__s1)) 49781ad6265SDimitry Andric return 1; 49881ad6265SDimitry Andric } 49981ad6265SDimitry Andric return 0; 50081ad6265SDimitry Andric #endif 50181ad6265SDimitry Andric } 50281ad6265SDimitry Andric 50381ad6265SDimitry Andric // TODO use '__builtin_char_memchr' if it ever supports char8_t ?? 50481ad6265SDimitry Andric inline constexpr 50581ad6265SDimitry Andric const char8_t* 50681ad6265SDimitry Andric char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT 50781ad6265SDimitry Andric { 50881ad6265SDimitry Andric for (; __n; --__n) 50981ad6265SDimitry Andric { 51081ad6265SDimitry Andric if (eq(*__s, __a)) 51181ad6265SDimitry Andric return __s; 51281ad6265SDimitry Andric ++__s; 51381ad6265SDimitry Andric } 51481ad6265SDimitry Andric return nullptr; 51581ad6265SDimitry Andric } 51681ad6265SDimitry Andric 51781ad6265SDimitry Andric #endif // _LIBCPP_HAS_NO_CHAR8_T 51881ad6265SDimitry Andric 51981ad6265SDimitry Andric template <> 52081ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> 52181ad6265SDimitry Andric { 52281ad6265SDimitry Andric typedef char16_t char_type; 52381ad6265SDimitry Andric typedef uint_least16_t int_type; 52481ad6265SDimitry Andric typedef streamoff off_type; 52581ad6265SDimitry Andric typedef u16streampos pos_type; 52681ad6265SDimitry Andric typedef mbstate_t state_type; 52781ad6265SDimitry Andric 52881ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 52981ad6265SDimitry Andric void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} 53081ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 53181ad6265SDimitry Andric {return __c1 == __c2;} 53281ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 53381ad6265SDimitry Andric {return __c1 < __c2;} 53481ad6265SDimitry Andric 53581ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 53681ad6265SDimitry Andric int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; 53781ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 53881ad6265SDimitry Andric size_t length(const char_type* __s) _NOEXCEPT; 53981ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 54081ad6265SDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; 54181ad6265SDimitry Andric 54281ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 54381ad6265SDimitry Andric static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 54481ad6265SDimitry Andric return std::__char_traits_move(__s1, __s2, __n); 54581ad6265SDimitry Andric } 54681ad6265SDimitry Andric 54781ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 54881ad6265SDimitry Andric static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 54981ad6265SDimitry Andric if (!__libcpp_is_constant_evaluated()) 55081ad6265SDimitry Andric _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); 55181ad6265SDimitry Andric std::copy_n(__s2, __n, __s1); 55281ad6265SDimitry Andric return __s1; 55381ad6265SDimitry Andric } 55481ad6265SDimitry Andric 55581ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 55681ad6265SDimitry Andric static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { 55781ad6265SDimitry Andric std::fill_n(__s, __n, __a); 55881ad6265SDimitry Andric return __s; 55981ad6265SDimitry Andric } 56081ad6265SDimitry Andric 56181ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 56281ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 56381ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 56481ad6265SDimitry Andric {return char_type(__c);} 56581ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 56681ad6265SDimitry Andric {return int_type(__c);} 56781ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 56881ad6265SDimitry Andric {return __c1 == __c2;} 56981ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 57081ad6265SDimitry Andric {return int_type(0xFFFF);} 57181ad6265SDimitry Andric }; 57281ad6265SDimitry Andric 57381ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 57481ad6265SDimitry Andric int 57581ad6265SDimitry Andric char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT 57681ad6265SDimitry Andric { 57781ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 57881ad6265SDimitry Andric { 57981ad6265SDimitry Andric if (lt(*__s1, *__s2)) 58081ad6265SDimitry Andric return -1; 58181ad6265SDimitry Andric if (lt(*__s2, *__s1)) 58281ad6265SDimitry Andric return 1; 58381ad6265SDimitry Andric } 58481ad6265SDimitry Andric return 0; 58581ad6265SDimitry Andric } 58681ad6265SDimitry Andric 58781ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 58881ad6265SDimitry Andric size_t 58981ad6265SDimitry Andric char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT 59081ad6265SDimitry Andric { 59181ad6265SDimitry Andric size_t __len = 0; 59281ad6265SDimitry Andric for (; !eq(*__s, char_type(0)); ++__s) 59381ad6265SDimitry Andric ++__len; 59481ad6265SDimitry Andric return __len; 59581ad6265SDimitry Andric } 59681ad6265SDimitry Andric 59781ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 59881ad6265SDimitry Andric const char16_t* 59981ad6265SDimitry Andric char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT 60081ad6265SDimitry Andric { 60181ad6265SDimitry Andric for (; __n; --__n) 60281ad6265SDimitry Andric { 60381ad6265SDimitry Andric if (eq(*__s, __a)) 60481ad6265SDimitry Andric return __s; 60581ad6265SDimitry Andric ++__s; 60681ad6265SDimitry Andric } 60781ad6265SDimitry Andric return nullptr; 60881ad6265SDimitry Andric } 60981ad6265SDimitry Andric 61081ad6265SDimitry Andric template <> 61181ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t> 61281ad6265SDimitry Andric { 61381ad6265SDimitry Andric typedef char32_t char_type; 61481ad6265SDimitry Andric typedef uint_least32_t int_type; 61581ad6265SDimitry Andric typedef streamoff off_type; 61681ad6265SDimitry Andric typedef u32streampos pos_type; 61781ad6265SDimitry Andric typedef mbstate_t state_type; 61881ad6265SDimitry Andric 61981ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR_AFTER_CXX14 62081ad6265SDimitry Andric void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} 62181ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 62281ad6265SDimitry Andric {return __c1 == __c2;} 62381ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 62481ad6265SDimitry Andric {return __c1 < __c2;} 62581ad6265SDimitry Andric 62681ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 62781ad6265SDimitry Andric int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; 62881ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 62981ad6265SDimitry Andric size_t length(const char_type* __s) _NOEXCEPT; 63081ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14 63181ad6265SDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; 63281ad6265SDimitry Andric 63381ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 63481ad6265SDimitry Andric static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 63581ad6265SDimitry Andric return std::__char_traits_move(__s1, __s2, __n); 63681ad6265SDimitry Andric } 63781ad6265SDimitry Andric 63881ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 63981ad6265SDimitry Andric static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 64081ad6265SDimitry Andric std::copy_n(__s2, __n, __s1); 64181ad6265SDimitry Andric return __s1; 64281ad6265SDimitry Andric } 64381ad6265SDimitry Andric 64481ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 64581ad6265SDimitry Andric static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { 64681ad6265SDimitry Andric std::fill_n(__s, __n, __a); 64781ad6265SDimitry Andric return __s; 64881ad6265SDimitry Andric } 64981ad6265SDimitry Andric 65081ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 65181ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 65281ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 65381ad6265SDimitry Andric {return char_type(__c);} 65481ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 65581ad6265SDimitry Andric {return int_type(__c);} 65681ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 65781ad6265SDimitry Andric {return __c1 == __c2;} 65881ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 65981ad6265SDimitry Andric {return int_type(0xFFFFFFFF);} 66081ad6265SDimitry Andric }; 66181ad6265SDimitry Andric 66281ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 66381ad6265SDimitry Andric int 66481ad6265SDimitry Andric char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT 66581ad6265SDimitry Andric { 66681ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 66781ad6265SDimitry Andric { 66881ad6265SDimitry Andric if (lt(*__s1, *__s2)) 66981ad6265SDimitry Andric return -1; 67081ad6265SDimitry Andric if (lt(*__s2, *__s1)) 67181ad6265SDimitry Andric return 1; 67281ad6265SDimitry Andric } 67381ad6265SDimitry Andric return 0; 67481ad6265SDimitry Andric } 67581ad6265SDimitry Andric 67681ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 67781ad6265SDimitry Andric size_t 67881ad6265SDimitry Andric char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT 67981ad6265SDimitry Andric { 68081ad6265SDimitry Andric size_t __len = 0; 68181ad6265SDimitry Andric for (; !eq(*__s, char_type(0)); ++__s) 68281ad6265SDimitry Andric ++__len; 68381ad6265SDimitry Andric return __len; 68481ad6265SDimitry Andric } 68581ad6265SDimitry Andric 68681ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX14 68781ad6265SDimitry Andric const char32_t* 68881ad6265SDimitry Andric char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT 68981ad6265SDimitry Andric { 69081ad6265SDimitry Andric for (; __n; --__n) 69181ad6265SDimitry Andric { 69281ad6265SDimitry Andric if (eq(*__s, __a)) 69381ad6265SDimitry Andric return __s; 69481ad6265SDimitry Andric ++__s; 69581ad6265SDimitry Andric } 69681ad6265SDimitry Andric return nullptr; 69781ad6265SDimitry Andric } 69881ad6265SDimitry Andric 69981ad6265SDimitry Andric // helper fns for basic_string and string_view 70081ad6265SDimitry Andric 70181ad6265SDimitry Andric // __str_find 70281ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 70381ad6265SDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 70481ad6265SDimitry Andric __str_find(const _CharT *__p, _SizeT __sz, 70581ad6265SDimitry Andric _CharT __c, _SizeT __pos) _NOEXCEPT 70681ad6265SDimitry Andric { 70781ad6265SDimitry Andric if (__pos >= __sz) 70881ad6265SDimitry Andric return __npos; 70981ad6265SDimitry Andric const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c); 71081ad6265SDimitry Andric if (__r == nullptr) 71181ad6265SDimitry Andric return __npos; 71281ad6265SDimitry Andric return static_cast<_SizeT>(__r - __p); 71381ad6265SDimitry Andric } 71481ad6265SDimitry Andric 71581ad6265SDimitry Andric template <class _CharT, class _Traits> 71681ad6265SDimitry Andric inline _LIBCPP_CONSTEXPR_AFTER_CXX11 const _CharT * 71781ad6265SDimitry Andric __search_substring(const _CharT *__first1, const _CharT *__last1, 71881ad6265SDimitry Andric const _CharT *__first2, const _CharT *__last2) _NOEXCEPT { 71981ad6265SDimitry Andric // Take advantage of knowing source and pattern lengths. 72081ad6265SDimitry Andric // Stop short when source is smaller than pattern. 72181ad6265SDimitry Andric const ptrdiff_t __len2 = __last2 - __first2; 72281ad6265SDimitry Andric if (__len2 == 0) 72381ad6265SDimitry Andric return __first1; 72481ad6265SDimitry Andric 72581ad6265SDimitry Andric ptrdiff_t __len1 = __last1 - __first1; 72681ad6265SDimitry Andric if (__len1 < __len2) 72781ad6265SDimitry Andric return __last1; 72881ad6265SDimitry Andric 72981ad6265SDimitry Andric // First element of __first2 is loop invariant. 73081ad6265SDimitry Andric _CharT __f2 = *__first2; 73181ad6265SDimitry Andric while (true) { 73281ad6265SDimitry Andric __len1 = __last1 - __first1; 73381ad6265SDimitry Andric // Check whether __first1 still has at least __len2 bytes. 73481ad6265SDimitry Andric if (__len1 < __len2) 73581ad6265SDimitry Andric return __last1; 73681ad6265SDimitry Andric 73781ad6265SDimitry Andric // Find __f2 the first byte matching in __first1. 73881ad6265SDimitry Andric __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2); 73981ad6265SDimitry Andric if (__first1 == nullptr) 74081ad6265SDimitry Andric return __last1; 74181ad6265SDimitry Andric 74281ad6265SDimitry Andric // It is faster to compare from the first byte of __first1 even if we 74381ad6265SDimitry Andric // already know that it matches the first byte of __first2: this is because 74481ad6265SDimitry Andric // __first2 is most likely aligned, as it is user's "pattern" string, and 74581ad6265SDimitry Andric // __first1 + 1 is most likely not aligned, as the match is in the middle of 74681ad6265SDimitry Andric // the string. 74781ad6265SDimitry Andric if (_Traits::compare(__first1, __first2, __len2) == 0) 74881ad6265SDimitry Andric return __first1; 74981ad6265SDimitry Andric 75081ad6265SDimitry Andric ++__first1; 75181ad6265SDimitry Andric } 75281ad6265SDimitry Andric } 75381ad6265SDimitry Andric 75481ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 75581ad6265SDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 75681ad6265SDimitry Andric __str_find(const _CharT *__p, _SizeT __sz, 75781ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 75881ad6265SDimitry Andric { 75981ad6265SDimitry Andric if (__pos > __sz) 76081ad6265SDimitry Andric return __npos; 76181ad6265SDimitry Andric 76281ad6265SDimitry Andric if (__n == 0) // There is nothing to search, just return __pos. 76381ad6265SDimitry Andric return __pos; 76481ad6265SDimitry Andric 76581ad6265SDimitry Andric const _CharT *__r = __search_substring<_CharT, _Traits>( 76681ad6265SDimitry Andric __p + __pos, __p + __sz, __s, __s + __n); 76781ad6265SDimitry Andric 76881ad6265SDimitry Andric if (__r == __p + __sz) 76981ad6265SDimitry Andric return __npos; 77081ad6265SDimitry Andric return static_cast<_SizeT>(__r - __p); 77181ad6265SDimitry Andric } 77281ad6265SDimitry Andric 77381ad6265SDimitry Andric 77481ad6265SDimitry Andric // __str_rfind 77581ad6265SDimitry Andric 77681ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 77781ad6265SDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 77881ad6265SDimitry Andric __str_rfind(const _CharT *__p, _SizeT __sz, 77981ad6265SDimitry Andric _CharT __c, _SizeT __pos) _NOEXCEPT 78081ad6265SDimitry Andric { 78181ad6265SDimitry Andric if (__sz < 1) 78281ad6265SDimitry Andric return __npos; 78381ad6265SDimitry Andric if (__pos < __sz) 78481ad6265SDimitry Andric ++__pos; 78581ad6265SDimitry Andric else 78681ad6265SDimitry Andric __pos = __sz; 78781ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __p;) 78881ad6265SDimitry Andric { 78981ad6265SDimitry Andric if (_Traits::eq(*--__ps, __c)) 79081ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 79181ad6265SDimitry Andric } 79281ad6265SDimitry Andric return __npos; 79381ad6265SDimitry Andric } 79481ad6265SDimitry Andric 79581ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 79681ad6265SDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 79781ad6265SDimitry Andric __str_rfind(const _CharT *__p, _SizeT __sz, 79881ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 79981ad6265SDimitry Andric { 80081ad6265SDimitry Andric __pos = _VSTD::min(__pos, __sz); 80181ad6265SDimitry Andric if (__n < __sz - __pos) 80281ad6265SDimitry Andric __pos += __n; 80381ad6265SDimitry Andric else 80481ad6265SDimitry Andric __pos = __sz; 805*753f127fSDimitry Andric const _CharT* __r = std::__find_end_classic(__p, __p + __pos, __s, __s + __n, _Traits::eq); 80681ad6265SDimitry Andric if (__n > 0 && __r == __p + __pos) 80781ad6265SDimitry Andric return __npos; 80881ad6265SDimitry Andric return static_cast<_SizeT>(__r - __p); 80981ad6265SDimitry Andric } 81081ad6265SDimitry Andric 81181ad6265SDimitry Andric // __str_find_first_of 81281ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 81381ad6265SDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 81481ad6265SDimitry Andric __str_find_first_of(const _CharT *__p, _SizeT __sz, 81581ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 81681ad6265SDimitry Andric { 81781ad6265SDimitry Andric if (__pos >= __sz || __n == 0) 81881ad6265SDimitry Andric return __npos; 81981ad6265SDimitry Andric const _CharT* __r = _VSTD::__find_first_of_ce 82081ad6265SDimitry Andric (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq ); 82181ad6265SDimitry Andric if (__r == __p + __sz) 82281ad6265SDimitry Andric return __npos; 82381ad6265SDimitry Andric return static_cast<_SizeT>(__r - __p); 82481ad6265SDimitry Andric } 82581ad6265SDimitry Andric 82681ad6265SDimitry Andric 82781ad6265SDimitry Andric // __str_find_last_of 82881ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 82981ad6265SDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 83081ad6265SDimitry Andric __str_find_last_of(const _CharT *__p, _SizeT __sz, 83181ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 83281ad6265SDimitry Andric { 83381ad6265SDimitry Andric if (__n != 0) 83481ad6265SDimitry Andric { 83581ad6265SDimitry Andric if (__pos < __sz) 83681ad6265SDimitry Andric ++__pos; 83781ad6265SDimitry Andric else 83881ad6265SDimitry Andric __pos = __sz; 83981ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __p;) 84081ad6265SDimitry Andric { 84181ad6265SDimitry Andric const _CharT* __r = _Traits::find(__s, __n, *--__ps); 84281ad6265SDimitry Andric if (__r) 84381ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 84481ad6265SDimitry Andric } 84581ad6265SDimitry Andric } 84681ad6265SDimitry Andric return __npos; 84781ad6265SDimitry Andric } 84881ad6265SDimitry Andric 84981ad6265SDimitry Andric 85081ad6265SDimitry Andric // __str_find_first_not_of 85181ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 85281ad6265SDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 85381ad6265SDimitry Andric __str_find_first_not_of(const _CharT *__p, _SizeT __sz, 85481ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 85581ad6265SDimitry Andric { 85681ad6265SDimitry Andric if (__pos < __sz) 85781ad6265SDimitry Andric { 85881ad6265SDimitry Andric const _CharT* __pe = __p + __sz; 85981ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps) 86081ad6265SDimitry Andric if (_Traits::find(__s, __n, *__ps) == nullptr) 86181ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 86281ad6265SDimitry Andric } 86381ad6265SDimitry Andric return __npos; 86481ad6265SDimitry Andric } 86581ad6265SDimitry Andric 86681ad6265SDimitry Andric 86781ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 86881ad6265SDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 86981ad6265SDimitry Andric __str_find_first_not_of(const _CharT *__p, _SizeT __sz, 87081ad6265SDimitry Andric _CharT __c, _SizeT __pos) _NOEXCEPT 87181ad6265SDimitry Andric { 87281ad6265SDimitry Andric if (__pos < __sz) 87381ad6265SDimitry Andric { 87481ad6265SDimitry Andric const _CharT* __pe = __p + __sz; 87581ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps) 87681ad6265SDimitry Andric if (!_Traits::eq(*__ps, __c)) 87781ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 87881ad6265SDimitry Andric } 87981ad6265SDimitry Andric return __npos; 88081ad6265SDimitry Andric } 88181ad6265SDimitry Andric 88281ad6265SDimitry Andric 88381ad6265SDimitry Andric // __str_find_last_not_of 88481ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 88581ad6265SDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 88681ad6265SDimitry Andric __str_find_last_not_of(const _CharT *__p, _SizeT __sz, 88781ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 88881ad6265SDimitry Andric { 88981ad6265SDimitry Andric if (__pos < __sz) 89081ad6265SDimitry Andric ++__pos; 89181ad6265SDimitry Andric else 89281ad6265SDimitry Andric __pos = __sz; 89381ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __p;) 89481ad6265SDimitry Andric if (_Traits::find(__s, __n, *--__ps) == nullptr) 89581ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 89681ad6265SDimitry Andric return __npos; 89781ad6265SDimitry Andric } 89881ad6265SDimitry Andric 89981ad6265SDimitry Andric 90081ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 90181ad6265SDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY 90281ad6265SDimitry Andric __str_find_last_not_of(const _CharT *__p, _SizeT __sz, 90381ad6265SDimitry Andric _CharT __c, _SizeT __pos) _NOEXCEPT 90481ad6265SDimitry Andric { 90581ad6265SDimitry Andric if (__pos < __sz) 90681ad6265SDimitry Andric ++__pos; 90781ad6265SDimitry Andric else 90881ad6265SDimitry Andric __pos = __sz; 90981ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __p;) 91081ad6265SDimitry Andric if (!_Traits::eq(*--__ps, __c)) 91181ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 91281ad6265SDimitry Andric return __npos; 91381ad6265SDimitry Andric } 91481ad6265SDimitry Andric 91581ad6265SDimitry Andric template<class _Ptr> 91681ad6265SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 91781ad6265SDimitry Andric size_t __do_string_hash(_Ptr __p, _Ptr __e) 91881ad6265SDimitry Andric { 91981ad6265SDimitry Andric typedef typename iterator_traits<_Ptr>::value_type value_type; 92081ad6265SDimitry Andric return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type)); 92181ad6265SDimitry Andric } 92281ad6265SDimitry Andric 92381ad6265SDimitry Andric _LIBCPP_END_NAMESPACE_STD 92481ad6265SDimitry Andric 92581ad6265SDimitry Andric _LIBCPP_POP_MACROS 92681ad6265SDimitry Andric 92781ad6265SDimitry Andric #endif // _LIBCPP___STRING_CHAR_TRAITS_H 928