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> 17*bdd1243dSDimitry Andric #include <__compare/ordering.h> 1881ad6265SDimitry Andric #include <__config> 1981ad6265SDimitry Andric #include <__functional/hash.h> 2081ad6265SDimitry Andric #include <__iterator/iterator_traits.h> 21*bdd1243dSDimitry Andric #include <__type_traits/is_constant_evaluated.h> 22*bdd1243dSDimitry Andric #include <cstddef> 2381ad6265SDimitry Andric #include <cstdint> 2481ad6265SDimitry Andric #include <cstdio> 2581ad6265SDimitry Andric #include <cstring> 2681ad6265SDimitry Andric #include <iosfwd> 2781ad6265SDimitry Andric 2881ad6265SDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 2981ad6265SDimitry Andric # include <cwchar> // for wmemcpy 3081ad6265SDimitry Andric #endif 3181ad6265SDimitry Andric 3281ad6265SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 3381ad6265SDimitry Andric # pragma GCC system_header 3481ad6265SDimitry Andric #endif 3581ad6265SDimitry Andric 3681ad6265SDimitry Andric _LIBCPP_PUSH_MACROS 3781ad6265SDimitry Andric #include <__undef_macros> 3881ad6265SDimitry Andric 3981ad6265SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 4081ad6265SDimitry Andric 4181ad6265SDimitry Andric template <class _CharT> 42*bdd1243dSDimitry Andric struct char_traits; 43*bdd1243dSDimitry Andric /* 44*bdd1243dSDimitry Andric The Standard does not define the base template for char_traits because it is impossible to provide 45*bdd1243dSDimitry Andric a correct definition for arbitrary character types. Instead, it requires implementations to provide 46*bdd1243dSDimitry Andric specializations for predefined character types like `char`, `wchar_t` and others. We provide this as 47*bdd1243dSDimitry Andric exposition-only to document what members a char_traits specialization should provide: 4881ad6265SDimitry Andric { 49*bdd1243dSDimitry Andric using char_type = _CharT; 50*bdd1243dSDimitry Andric using int_type = ...; 51*bdd1243dSDimitry Andric using off_type = ...; 52*bdd1243dSDimitry Andric using pos_type = ...; 53*bdd1243dSDimitry Andric using state_type = ...; 5481ad6265SDimitry Andric 55*bdd1243dSDimitry Andric static void assign(char_type&, const char_type&); 56*bdd1243dSDimitry Andric static bool eq(char_type, char_type); 57*bdd1243dSDimitry Andric static bool lt(char_type, char_type); 58*bdd1243dSDimitry Andric 59*bdd1243dSDimitry Andric static int compare(const char_type*, const char_type*, size_t); 60*bdd1243dSDimitry Andric static size_t length(const char_type*); 61*bdd1243dSDimitry Andric static const char_type* find(const char_type*, size_t, const char_type&); 62*bdd1243dSDimitry Andric static char_type* move(char_type*, const char_type*, size_t); 63*bdd1243dSDimitry Andric static char_type* copy(char_type*, const char_type*, size_t); 64*bdd1243dSDimitry Andric static char_type* assign(char_type*, size_t, char_type); 65*bdd1243dSDimitry Andric 66*bdd1243dSDimitry Andric static int_type not_eof(int_type); 67*bdd1243dSDimitry Andric static char_type to_char_type(int_type); 68*bdd1243dSDimitry Andric static int_type to_int_type(char_type); 69*bdd1243dSDimitry Andric static bool eq_int_type(int_type, int_type); 70*bdd1243dSDimitry Andric static int_type eof(); 71*bdd1243dSDimitry Andric }; 72*bdd1243dSDimitry Andric */ 73*bdd1243dSDimitry Andric 74*bdd1243dSDimitry Andric // 75*bdd1243dSDimitry Andric // Temporary extension to provide a base template for std::char_traits. 76*bdd1243dSDimitry Andric // TODO: Remove in LLVM 18. 77*bdd1243dSDimitry Andric // 78*bdd1243dSDimitry Andric template <class _CharT> 79*bdd1243dSDimitry Andric struct _LIBCPP_DEPRECATED_("char_traits<T> 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 18, so please migrate off of it.") 80*bdd1243dSDimitry Andric char_traits 81*bdd1243dSDimitry Andric { 82*bdd1243dSDimitry Andric using char_type = _CharT; 83*bdd1243dSDimitry Andric using int_type = int; 84*bdd1243dSDimitry Andric using off_type = streamoff; 85*bdd1243dSDimitry Andric using pos_type = streampos; 86*bdd1243dSDimitry Andric using state_type = mbstate_t; 87*bdd1243dSDimitry Andric 88*bdd1243dSDimitry Andric static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17 8981ad6265SDimitry Andric assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} 9081ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 9181ad6265SDimitry Andric {return __c1 == __c2;} 9281ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 9381ad6265SDimitry Andric {return __c1 < __c2;} 9481ad6265SDimitry Andric 95*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX17 96*bdd1243dSDimitry Andric int compare(const char_type* __s1, const char_type* __s2, size_t __n) { 9781ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 9881ad6265SDimitry Andric { 9981ad6265SDimitry Andric if (lt(*__s1, *__s2)) 10081ad6265SDimitry Andric return -1; 10181ad6265SDimitry Andric if (lt(*__s2, *__s1)) 10281ad6265SDimitry Andric return 1; 10381ad6265SDimitry Andric } 10481ad6265SDimitry Andric return 0; 10581ad6265SDimitry Andric } 106*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 107*bdd1243dSDimitry Andric size_t length(const char_type* __s) { 10881ad6265SDimitry Andric size_t __len = 0; 10981ad6265SDimitry Andric for (; !eq(*__s, char_type(0)); ++__s) 11081ad6265SDimitry Andric ++__len; 11181ad6265SDimitry Andric return __len; 11281ad6265SDimitry Andric } 113*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 114*bdd1243dSDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) { 11581ad6265SDimitry Andric for (; __n; --__n) 11681ad6265SDimitry Andric { 11781ad6265SDimitry Andric if (eq(*__s, __a)) 11881ad6265SDimitry Andric return __s; 11981ad6265SDimitry Andric ++__s; 12081ad6265SDimitry Andric } 12181ad6265SDimitry Andric return nullptr; 12281ad6265SDimitry Andric } 123*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX20 124*bdd1243dSDimitry Andric char_type* move(char_type* __s1, const char_type* __s2, size_t __n) { 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 } 141*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY 142*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX20 143*bdd1243dSDimitry Andric char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) { 14481ad6265SDimitry Andric if (!__libcpp_is_constant_evaluated()) { 14581ad6265SDimitry Andric _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); 14681ad6265SDimitry Andric } 14781ad6265SDimitry Andric char_type* __r = __s1; 14881ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 14981ad6265SDimitry Andric assign(*__s1, *__s2); 15081ad6265SDimitry Andric return __r; 15181ad6265SDimitry Andric } 152*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY 153*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX20 154*bdd1243dSDimitry Andric char_type* assign(char_type* __s, size_t __n, char_type __a) { 15581ad6265SDimitry Andric char_type* __r = __s; 15681ad6265SDimitry Andric for (; __n; --__n, ++__s) 15781ad6265SDimitry Andric assign(*__s, __a); 15881ad6265SDimitry Andric return __r; 15981ad6265SDimitry Andric } 16081ad6265SDimitry Andric 161*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 162*bdd1243dSDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 163*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 164*bdd1243dSDimitry Andric {return char_type(__c);} 165*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 166*bdd1243dSDimitry Andric {return int_type(__c);} 167*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 168*bdd1243dSDimitry Andric {return __c1 == __c2;} 169*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 170*bdd1243dSDimitry Andric {return int_type(EOF);} 171*bdd1243dSDimitry Andric }; 172*bdd1243dSDimitry Andric 17381ad6265SDimitry Andric template <class _CharT> 174*bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 17581ad6265SDimitry Andric _CharT* __char_traits_move(_CharT* __dest, const _CharT* __source, size_t __n) _NOEXCEPT 17681ad6265SDimitry Andric { 17781ad6265SDimitry Andric #ifdef _LIBCPP_COMPILER_GCC 17881ad6265SDimitry Andric if (__libcpp_is_constant_evaluated()) { 17981ad6265SDimitry Andric if (__n == 0) 18081ad6265SDimitry Andric return __dest; 18181ad6265SDimitry Andric _CharT* __allocation = new _CharT[__n]; 18281ad6265SDimitry Andric std::copy_n(__source, __n, __allocation); 18381ad6265SDimitry Andric std::copy_n(static_cast<const _CharT*>(__allocation), __n, __dest); 18481ad6265SDimitry Andric delete[] __allocation; 18581ad6265SDimitry Andric return __dest; 18681ad6265SDimitry Andric } 18781ad6265SDimitry Andric #endif 18881ad6265SDimitry Andric ::__builtin_memmove(__dest, __source, __n * sizeof(_CharT)); 18981ad6265SDimitry Andric return __dest; 19081ad6265SDimitry Andric } 19181ad6265SDimitry Andric 19281ad6265SDimitry Andric // char_traits<char> 19381ad6265SDimitry Andric 19481ad6265SDimitry Andric template <> 19581ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char> 19681ad6265SDimitry Andric { 197*bdd1243dSDimitry Andric using char_type = char; 198*bdd1243dSDimitry Andric using int_type = int; 199*bdd1243dSDimitry Andric using off_type = streamoff; 200*bdd1243dSDimitry Andric using pos_type = streampos; 201*bdd1243dSDimitry Andric using state_type = mbstate_t; 202*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17 203*bdd1243dSDimitry Andric using comparison_category = strong_ordering; 204*bdd1243dSDimitry Andric #endif 20581ad6265SDimitry Andric 206*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR_SINCE_CXX17 20781ad6265SDimitry Andric void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} 20881ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 20981ad6265SDimitry Andric {return __c1 == __c2;} 21081ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 21181ad6265SDimitry Andric {return (unsigned char)__c1 < (unsigned char)__c2;} 21281ad6265SDimitry Andric 213*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 214*bdd1243dSDimitry Andric if (__n == 0) 215*bdd1243dSDimitry Andric return 0; 216*bdd1243dSDimitry Andric return std::__constexpr_memcmp(__s1, __s2, __n); 21781ad6265SDimitry Andric } 21881ad6265SDimitry Andric 219*bdd1243dSDimitry Andric static inline size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT { 220*bdd1243dSDimitry Andric return std::__constexpr_strlen(__s); 221*bdd1243dSDimitry Andric } 22281ad6265SDimitry Andric 223*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX17 224*bdd1243dSDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { 225*bdd1243dSDimitry Andric if (__n == 0) 226*bdd1243dSDimitry Andric return nullptr; 227*bdd1243dSDimitry Andric return std::__constexpr_char_memchr(__s, static_cast<int>(__a), __n); 228*bdd1243dSDimitry Andric } 229*bdd1243dSDimitry Andric 230*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 23181ad6265SDimitry Andric char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 23281ad6265SDimitry Andric return std::__char_traits_move(__s1, __s2, __n); 23381ad6265SDimitry Andric } 23481ad6265SDimitry Andric 235*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 23681ad6265SDimitry Andric char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 23781ad6265SDimitry Andric if (!__libcpp_is_constant_evaluated()) 23881ad6265SDimitry Andric _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); 23981ad6265SDimitry Andric std::copy_n(__s2, __n, __s1); 24081ad6265SDimitry Andric return __s1; 24181ad6265SDimitry Andric } 24281ad6265SDimitry Andric 243*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 24481ad6265SDimitry Andric char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { 24581ad6265SDimitry Andric std::fill_n(__s, __n, __a); 24681ad6265SDimitry Andric return __s; 24781ad6265SDimitry Andric } 24881ad6265SDimitry Andric 24981ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 25081ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 25181ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 25281ad6265SDimitry Andric {return char_type(__c);} 25381ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 25481ad6265SDimitry Andric {return int_type((unsigned char)__c);} 25581ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 25681ad6265SDimitry Andric {return __c1 == __c2;} 25781ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 25881ad6265SDimitry Andric {return int_type(EOF);} 25981ad6265SDimitry Andric }; 26081ad6265SDimitry Andric 26181ad6265SDimitry Andric // char_traits<wchar_t> 26281ad6265SDimitry Andric 26381ad6265SDimitry Andric #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS 26481ad6265SDimitry Andric template <> 26581ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t> 26681ad6265SDimitry Andric { 267*bdd1243dSDimitry Andric using char_type = wchar_t; 268*bdd1243dSDimitry Andric using int_type = wint_t; 269*bdd1243dSDimitry Andric using off_type = streamoff; 270*bdd1243dSDimitry Andric using pos_type = streampos; 271*bdd1243dSDimitry Andric using state_type = mbstate_t; 272*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17 273*bdd1243dSDimitry Andric using comparison_category = strong_ordering; 274*bdd1243dSDimitry Andric #endif 27581ad6265SDimitry Andric 276*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR_SINCE_CXX17 27781ad6265SDimitry Andric void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} 27881ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 27981ad6265SDimitry Andric {return __c1 == __c2;} 28081ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 28181ad6265SDimitry Andric {return __c1 < __c2;} 28281ad6265SDimitry Andric 283*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX17 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 284*bdd1243dSDimitry Andric if (__n == 0) 285*bdd1243dSDimitry Andric return 0; 286*bdd1243dSDimitry Andric return std::__constexpr_wmemcmp(__s1, __s2, __n); 287*bdd1243dSDimitry Andric } 28881ad6265SDimitry Andric 289*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT { 290*bdd1243dSDimitry Andric return std::__constexpr_wcslen(__s); 291*bdd1243dSDimitry Andric } 292*bdd1243dSDimitry Andric 293*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX17 294*bdd1243dSDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT { 295*bdd1243dSDimitry Andric if (__n == 0) 296*bdd1243dSDimitry Andric return nullptr; 297*bdd1243dSDimitry Andric return std::__constexpr_wmemchr(__s, __a, __n); 298*bdd1243dSDimitry Andric } 299*bdd1243dSDimitry Andric 300*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 30181ad6265SDimitry Andric char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 30281ad6265SDimitry Andric return std::__char_traits_move(__s1, __s2, __n); 30381ad6265SDimitry Andric } 30481ad6265SDimitry Andric 305*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 30681ad6265SDimitry Andric char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 30781ad6265SDimitry Andric if (!__libcpp_is_constant_evaluated()) 30881ad6265SDimitry Andric _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); 30981ad6265SDimitry Andric std::copy_n(__s2, __n, __s1); 31081ad6265SDimitry Andric return __s1; 31181ad6265SDimitry Andric } 31281ad6265SDimitry Andric 313*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR_SINCE_CXX20 31481ad6265SDimitry Andric char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { 31581ad6265SDimitry Andric std::fill_n(__s, __n, __a); 31681ad6265SDimitry Andric return __s; 31781ad6265SDimitry Andric } 31881ad6265SDimitry Andric 31981ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 32081ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 32181ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 32281ad6265SDimitry Andric {return char_type(__c);} 32381ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 32481ad6265SDimitry Andric {return int_type(__c);} 32581ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 32681ad6265SDimitry Andric {return __c1 == __c2;} 32781ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 32881ad6265SDimitry Andric {return int_type(WEOF);} 32981ad6265SDimitry Andric }; 33081ad6265SDimitry Andric #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS 33181ad6265SDimitry Andric 33281ad6265SDimitry Andric #ifndef _LIBCPP_HAS_NO_CHAR8_T 33381ad6265SDimitry Andric 33481ad6265SDimitry Andric template <> 33581ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t> 33681ad6265SDimitry Andric { 337*bdd1243dSDimitry Andric using char_type = char8_t; 338*bdd1243dSDimitry Andric using int_type = unsigned int; 339*bdd1243dSDimitry Andric using off_type = streamoff; 340*bdd1243dSDimitry Andric using pos_type = u8streampos; 341*bdd1243dSDimitry Andric using state_type = mbstate_t; 342*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17 343*bdd1243dSDimitry Andric using comparison_category = strong_ordering; 344*bdd1243dSDimitry Andric #endif 34581ad6265SDimitry Andric 34681ad6265SDimitry Andric static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept 34781ad6265SDimitry Andric {__c1 = __c2;} 34881ad6265SDimitry Andric static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept 34981ad6265SDimitry Andric {return __c1 == __c2;} 35081ad6265SDimitry Andric static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept 35181ad6265SDimitry Andric {return __c1 < __c2;} 35281ad6265SDimitry Andric 353*bdd1243dSDimitry Andric static _LIBCPP_HIDE_FROM_ABI constexpr int 354*bdd1243dSDimitry Andric compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 355*bdd1243dSDimitry Andric return std::__constexpr_memcmp(__s1, __s2, __n); 356*bdd1243dSDimitry Andric } 35781ad6265SDimitry Andric 35881ad6265SDimitry Andric static constexpr 35981ad6265SDimitry Andric size_t length(const char_type* __s) _NOEXCEPT; 36081ad6265SDimitry Andric 36181ad6265SDimitry Andric _LIBCPP_INLINE_VISIBILITY static constexpr 36281ad6265SDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; 36381ad6265SDimitry Andric 364*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX20 36581ad6265SDimitry Andric char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 36681ad6265SDimitry Andric return std::__char_traits_move(__s1, __s2, __n); 36781ad6265SDimitry Andric } 36881ad6265SDimitry Andric 369*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX20 37081ad6265SDimitry Andric char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 37181ad6265SDimitry Andric if (!__libcpp_is_constant_evaluated()) 37281ad6265SDimitry Andric _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); 37381ad6265SDimitry Andric std::copy_n(__s2, __n, __s1); 37481ad6265SDimitry Andric return __s1; 37581ad6265SDimitry Andric } 37681ad6265SDimitry Andric 377*bdd1243dSDimitry Andric static _LIBCPP_CONSTEXPR_SINCE_CXX20 37881ad6265SDimitry Andric char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { 37981ad6265SDimitry Andric std::fill_n(__s, __n, __a); 38081ad6265SDimitry Andric return __s; 38181ad6265SDimitry Andric } 38281ad6265SDimitry Andric 38381ad6265SDimitry Andric static inline constexpr int_type not_eof(int_type __c) noexcept 38481ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 38581ad6265SDimitry Andric static inline constexpr char_type to_char_type(int_type __c) noexcept 38681ad6265SDimitry Andric {return char_type(__c);} 38781ad6265SDimitry Andric static inline constexpr int_type to_int_type(char_type __c) noexcept 38881ad6265SDimitry Andric {return int_type(__c);} 38981ad6265SDimitry Andric static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept 39081ad6265SDimitry Andric {return __c1 == __c2;} 39181ad6265SDimitry Andric static inline constexpr int_type eof() noexcept 39281ad6265SDimitry Andric {return int_type(EOF);} 39381ad6265SDimitry Andric }; 39481ad6265SDimitry Andric 39581ad6265SDimitry Andric // TODO use '__builtin_strlen' if it ever supports char8_t ?? 39681ad6265SDimitry Andric inline constexpr 39781ad6265SDimitry Andric size_t 39881ad6265SDimitry Andric char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT 39981ad6265SDimitry Andric { 40081ad6265SDimitry Andric size_t __len = 0; 40181ad6265SDimitry Andric for (; !eq(*__s, char_type(0)); ++__s) 40281ad6265SDimitry Andric ++__len; 40381ad6265SDimitry Andric return __len; 40481ad6265SDimitry Andric } 40581ad6265SDimitry Andric 40681ad6265SDimitry Andric // TODO use '__builtin_char_memchr' if it ever supports char8_t ?? 40781ad6265SDimitry Andric inline constexpr 40881ad6265SDimitry Andric const char8_t* 40981ad6265SDimitry Andric char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT 41081ad6265SDimitry Andric { 41181ad6265SDimitry Andric for (; __n; --__n) 41281ad6265SDimitry Andric { 41381ad6265SDimitry Andric if (eq(*__s, __a)) 41481ad6265SDimitry Andric return __s; 41581ad6265SDimitry Andric ++__s; 41681ad6265SDimitry Andric } 41781ad6265SDimitry Andric return nullptr; 41881ad6265SDimitry Andric } 41981ad6265SDimitry Andric 42081ad6265SDimitry Andric #endif // _LIBCPP_HAS_NO_CHAR8_T 42181ad6265SDimitry Andric 42281ad6265SDimitry Andric template <> 42381ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t> 42481ad6265SDimitry Andric { 425*bdd1243dSDimitry Andric using char_type = char16_t; 426*bdd1243dSDimitry Andric using int_type = uint_least16_t; 427*bdd1243dSDimitry Andric using off_type = streamoff; 428*bdd1243dSDimitry Andric using pos_type = u16streampos; 429*bdd1243dSDimitry Andric using state_type = mbstate_t; 430*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17 431*bdd1243dSDimitry Andric using comparison_category = strong_ordering; 432*bdd1243dSDimitry Andric #endif 43381ad6265SDimitry Andric 434*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR_SINCE_CXX17 43581ad6265SDimitry Andric void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;} 43681ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT 43781ad6265SDimitry Andric {return __c1 == __c2;} 43881ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT 43981ad6265SDimitry Andric {return __c1 < __c2;} 44081ad6265SDimitry Andric 441*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 44281ad6265SDimitry Andric int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; 443*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 44481ad6265SDimitry Andric size_t length(const char_type* __s) _NOEXCEPT; 445*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 44681ad6265SDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; 44781ad6265SDimitry Andric 448*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 44981ad6265SDimitry Andric static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 45081ad6265SDimitry Andric return std::__char_traits_move(__s1, __s2, __n); 45181ad6265SDimitry Andric } 45281ad6265SDimitry Andric 453*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 45481ad6265SDimitry Andric static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 45581ad6265SDimitry Andric if (!__libcpp_is_constant_evaluated()) 45681ad6265SDimitry Andric _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); 45781ad6265SDimitry Andric std::copy_n(__s2, __n, __s1); 45881ad6265SDimitry Andric return __s1; 45981ad6265SDimitry Andric } 46081ad6265SDimitry Andric 461*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 46281ad6265SDimitry Andric static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { 46381ad6265SDimitry Andric std::fill_n(__s, __n, __a); 46481ad6265SDimitry Andric return __s; 46581ad6265SDimitry Andric } 46681ad6265SDimitry Andric 46781ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 46881ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 46981ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 47081ad6265SDimitry Andric {return char_type(__c);} 47181ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 47281ad6265SDimitry Andric {return int_type(__c);} 47381ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 47481ad6265SDimitry Andric {return __c1 == __c2;} 47581ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 47681ad6265SDimitry Andric {return int_type(0xFFFF);} 47781ad6265SDimitry Andric }; 47881ad6265SDimitry Andric 479*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17 48081ad6265SDimitry Andric int 48181ad6265SDimitry Andric char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT 48281ad6265SDimitry Andric { 48381ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 48481ad6265SDimitry Andric { 48581ad6265SDimitry Andric if (lt(*__s1, *__s2)) 48681ad6265SDimitry Andric return -1; 48781ad6265SDimitry Andric if (lt(*__s2, *__s1)) 48881ad6265SDimitry Andric return 1; 48981ad6265SDimitry Andric } 49081ad6265SDimitry Andric return 0; 49181ad6265SDimitry Andric } 49281ad6265SDimitry Andric 493*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17 49481ad6265SDimitry Andric size_t 49581ad6265SDimitry Andric char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT 49681ad6265SDimitry Andric { 49781ad6265SDimitry Andric size_t __len = 0; 49881ad6265SDimitry Andric for (; !eq(*__s, char_type(0)); ++__s) 49981ad6265SDimitry Andric ++__len; 50081ad6265SDimitry Andric return __len; 50181ad6265SDimitry Andric } 50281ad6265SDimitry Andric 503*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17 50481ad6265SDimitry Andric const char16_t* 50581ad6265SDimitry Andric char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT 50681ad6265SDimitry Andric { 50781ad6265SDimitry Andric for (; __n; --__n) 50881ad6265SDimitry Andric { 50981ad6265SDimitry Andric if (eq(*__s, __a)) 51081ad6265SDimitry Andric return __s; 51181ad6265SDimitry Andric ++__s; 51281ad6265SDimitry Andric } 51381ad6265SDimitry Andric return nullptr; 51481ad6265SDimitry Andric } 51581ad6265SDimitry Andric 51681ad6265SDimitry Andric template <> 51781ad6265SDimitry Andric struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t> 51881ad6265SDimitry Andric { 519*bdd1243dSDimitry Andric using char_type = char32_t; 520*bdd1243dSDimitry Andric using int_type = uint_least32_t; 521*bdd1243dSDimitry Andric using off_type = streamoff; 522*bdd1243dSDimitry Andric using pos_type = u32streampos; 523*bdd1243dSDimitry Andric using state_type = mbstate_t; 524*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17 525*bdd1243dSDimitry Andric using comparison_category = strong_ordering; 526*bdd1243dSDimitry Andric #endif 52781ad6265SDimitry Andric 528*bdd1243dSDimitry Andric static inline _LIBCPP_CONSTEXPR_SINCE_CXX17 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 535*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 53681ad6265SDimitry Andric int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT; 537*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 53881ad6265SDimitry Andric size_t length(const char_type* __s) _NOEXCEPT; 539*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17 54081ad6265SDimitry Andric const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT; 54181ad6265SDimitry Andric 542*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 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 547*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 54881ad6265SDimitry Andric static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT { 54981ad6265SDimitry Andric std::copy_n(__s2, __n, __s1); 55081ad6265SDimitry Andric return __s1; 55181ad6265SDimitry Andric } 55281ad6265SDimitry Andric 553*bdd1243dSDimitry Andric _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 55481ad6265SDimitry Andric static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT { 55581ad6265SDimitry Andric std::fill_n(__s, __n, __a); 55681ad6265SDimitry Andric return __s; 55781ad6265SDimitry Andric } 55881ad6265SDimitry Andric 55981ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT 56081ad6265SDimitry Andric {return eq_int_type(__c, eof()) ? ~eof() : __c;} 56181ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT 56281ad6265SDimitry Andric {return char_type(__c);} 56381ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT 56481ad6265SDimitry Andric {return int_type(__c);} 56581ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT 56681ad6265SDimitry Andric {return __c1 == __c2;} 56781ad6265SDimitry Andric static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT 56881ad6265SDimitry Andric {return int_type(0xFFFFFFFF);} 56981ad6265SDimitry Andric }; 57081ad6265SDimitry Andric 571*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17 57281ad6265SDimitry Andric int 57381ad6265SDimitry Andric char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT 57481ad6265SDimitry Andric { 57581ad6265SDimitry Andric for (; __n; --__n, ++__s1, ++__s2) 57681ad6265SDimitry Andric { 57781ad6265SDimitry Andric if (lt(*__s1, *__s2)) 57881ad6265SDimitry Andric return -1; 57981ad6265SDimitry Andric if (lt(*__s2, *__s1)) 58081ad6265SDimitry Andric return 1; 58181ad6265SDimitry Andric } 58281ad6265SDimitry Andric return 0; 58381ad6265SDimitry Andric } 58481ad6265SDimitry Andric 585*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17 58681ad6265SDimitry Andric size_t 58781ad6265SDimitry Andric char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT 58881ad6265SDimitry Andric { 58981ad6265SDimitry Andric size_t __len = 0; 59081ad6265SDimitry Andric for (; !eq(*__s, char_type(0)); ++__s) 59181ad6265SDimitry Andric ++__len; 59281ad6265SDimitry Andric return __len; 59381ad6265SDimitry Andric } 59481ad6265SDimitry Andric 595*bdd1243dSDimitry Andric inline _LIBCPP_CONSTEXPR_SINCE_CXX17 59681ad6265SDimitry Andric const char32_t* 59781ad6265SDimitry Andric char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT 59881ad6265SDimitry Andric { 59981ad6265SDimitry Andric for (; __n; --__n) 60081ad6265SDimitry Andric { 60181ad6265SDimitry Andric if (eq(*__s, __a)) 60281ad6265SDimitry Andric return __s; 60381ad6265SDimitry Andric ++__s; 60481ad6265SDimitry Andric } 60581ad6265SDimitry Andric return nullptr; 60681ad6265SDimitry Andric } 60781ad6265SDimitry Andric 60881ad6265SDimitry Andric // helper fns for basic_string and string_view 60981ad6265SDimitry Andric 61081ad6265SDimitry Andric // __str_find 61181ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 612*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY 61381ad6265SDimitry Andric __str_find(const _CharT *__p, _SizeT __sz, 61481ad6265SDimitry Andric _CharT __c, _SizeT __pos) _NOEXCEPT 61581ad6265SDimitry Andric { 61681ad6265SDimitry Andric if (__pos >= __sz) 61781ad6265SDimitry Andric return __npos; 61881ad6265SDimitry Andric const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c); 61981ad6265SDimitry Andric if (__r == nullptr) 62081ad6265SDimitry Andric return __npos; 62181ad6265SDimitry Andric return static_cast<_SizeT>(__r - __p); 62281ad6265SDimitry Andric } 62381ad6265SDimitry Andric 62481ad6265SDimitry Andric template <class _CharT, class _Traits> 625*bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 const _CharT * 62681ad6265SDimitry Andric __search_substring(const _CharT *__first1, const _CharT *__last1, 62781ad6265SDimitry Andric const _CharT *__first2, const _CharT *__last2) _NOEXCEPT { 62881ad6265SDimitry Andric // Take advantage of knowing source and pattern lengths. 62981ad6265SDimitry Andric // Stop short when source is smaller than pattern. 63081ad6265SDimitry Andric const ptrdiff_t __len2 = __last2 - __first2; 63181ad6265SDimitry Andric if (__len2 == 0) 63281ad6265SDimitry Andric return __first1; 63381ad6265SDimitry Andric 63481ad6265SDimitry Andric ptrdiff_t __len1 = __last1 - __first1; 63581ad6265SDimitry Andric if (__len1 < __len2) 63681ad6265SDimitry Andric return __last1; 63781ad6265SDimitry Andric 63881ad6265SDimitry Andric // First element of __first2 is loop invariant. 63981ad6265SDimitry Andric _CharT __f2 = *__first2; 64081ad6265SDimitry Andric while (true) { 64181ad6265SDimitry Andric __len1 = __last1 - __first1; 64281ad6265SDimitry Andric // Check whether __first1 still has at least __len2 bytes. 64381ad6265SDimitry Andric if (__len1 < __len2) 64481ad6265SDimitry Andric return __last1; 64581ad6265SDimitry Andric 64681ad6265SDimitry Andric // Find __f2 the first byte matching in __first1. 64781ad6265SDimitry Andric __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2); 64881ad6265SDimitry Andric if (__first1 == nullptr) 64981ad6265SDimitry Andric return __last1; 65081ad6265SDimitry Andric 65181ad6265SDimitry Andric // It is faster to compare from the first byte of __first1 even if we 65281ad6265SDimitry Andric // already know that it matches the first byte of __first2: this is because 65381ad6265SDimitry Andric // __first2 is most likely aligned, as it is user's "pattern" string, and 65481ad6265SDimitry Andric // __first1 + 1 is most likely not aligned, as the match is in the middle of 65581ad6265SDimitry Andric // the string. 65681ad6265SDimitry Andric if (_Traits::compare(__first1, __first2, __len2) == 0) 65781ad6265SDimitry Andric return __first1; 65881ad6265SDimitry Andric 65981ad6265SDimitry Andric ++__first1; 66081ad6265SDimitry Andric } 66181ad6265SDimitry Andric } 66281ad6265SDimitry Andric 66381ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 664*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY 66581ad6265SDimitry Andric __str_find(const _CharT *__p, _SizeT __sz, 66681ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 66781ad6265SDimitry Andric { 66881ad6265SDimitry Andric if (__pos > __sz) 66981ad6265SDimitry Andric return __npos; 67081ad6265SDimitry Andric 67181ad6265SDimitry Andric if (__n == 0) // There is nothing to search, just return __pos. 67281ad6265SDimitry Andric return __pos; 67381ad6265SDimitry Andric 674*bdd1243dSDimitry Andric const _CharT *__r = std::__search_substring<_CharT, _Traits>( 67581ad6265SDimitry Andric __p + __pos, __p + __sz, __s, __s + __n); 67681ad6265SDimitry Andric 67781ad6265SDimitry Andric if (__r == __p + __sz) 67881ad6265SDimitry Andric return __npos; 67981ad6265SDimitry Andric return static_cast<_SizeT>(__r - __p); 68081ad6265SDimitry Andric } 68181ad6265SDimitry Andric 68281ad6265SDimitry Andric 68381ad6265SDimitry Andric // __str_rfind 68481ad6265SDimitry Andric 68581ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 686*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY 68781ad6265SDimitry Andric __str_rfind(const _CharT *__p, _SizeT __sz, 68881ad6265SDimitry Andric _CharT __c, _SizeT __pos) _NOEXCEPT 68981ad6265SDimitry Andric { 69081ad6265SDimitry Andric if (__sz < 1) 69181ad6265SDimitry Andric return __npos; 69281ad6265SDimitry Andric if (__pos < __sz) 69381ad6265SDimitry Andric ++__pos; 69481ad6265SDimitry Andric else 69581ad6265SDimitry Andric __pos = __sz; 69681ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __p;) 69781ad6265SDimitry Andric { 69881ad6265SDimitry Andric if (_Traits::eq(*--__ps, __c)) 69981ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 70081ad6265SDimitry Andric } 70181ad6265SDimitry Andric return __npos; 70281ad6265SDimitry Andric } 70381ad6265SDimitry Andric 70481ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 705*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY 70681ad6265SDimitry Andric __str_rfind(const _CharT *__p, _SizeT __sz, 70781ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 70881ad6265SDimitry Andric { 70981ad6265SDimitry Andric __pos = _VSTD::min(__pos, __sz); 71081ad6265SDimitry Andric if (__n < __sz - __pos) 71181ad6265SDimitry Andric __pos += __n; 71281ad6265SDimitry Andric else 71381ad6265SDimitry Andric __pos = __sz; 714753f127fSDimitry Andric const _CharT* __r = std::__find_end_classic(__p, __p + __pos, __s, __s + __n, _Traits::eq); 71581ad6265SDimitry Andric if (__n > 0 && __r == __p + __pos) 71681ad6265SDimitry Andric return __npos; 71781ad6265SDimitry Andric return static_cast<_SizeT>(__r - __p); 71881ad6265SDimitry Andric } 71981ad6265SDimitry Andric 72081ad6265SDimitry Andric // __str_find_first_of 72181ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 722*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY 72381ad6265SDimitry Andric __str_find_first_of(const _CharT *__p, _SizeT __sz, 72481ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 72581ad6265SDimitry Andric { 72681ad6265SDimitry Andric if (__pos >= __sz || __n == 0) 72781ad6265SDimitry Andric return __npos; 72881ad6265SDimitry Andric const _CharT* __r = _VSTD::__find_first_of_ce 72981ad6265SDimitry Andric (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq ); 73081ad6265SDimitry Andric if (__r == __p + __sz) 73181ad6265SDimitry Andric return __npos; 73281ad6265SDimitry Andric return static_cast<_SizeT>(__r - __p); 73381ad6265SDimitry Andric } 73481ad6265SDimitry Andric 73581ad6265SDimitry Andric 73681ad6265SDimitry Andric // __str_find_last_of 73781ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 738*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY 73981ad6265SDimitry Andric __str_find_last_of(const _CharT *__p, _SizeT __sz, 74081ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 74181ad6265SDimitry Andric { 74281ad6265SDimitry Andric if (__n != 0) 74381ad6265SDimitry Andric { 74481ad6265SDimitry Andric if (__pos < __sz) 74581ad6265SDimitry Andric ++__pos; 74681ad6265SDimitry Andric else 74781ad6265SDimitry Andric __pos = __sz; 74881ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __p;) 74981ad6265SDimitry Andric { 75081ad6265SDimitry Andric const _CharT* __r = _Traits::find(__s, __n, *--__ps); 75181ad6265SDimitry Andric if (__r) 75281ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 75381ad6265SDimitry Andric } 75481ad6265SDimitry Andric } 75581ad6265SDimitry Andric return __npos; 75681ad6265SDimitry Andric } 75781ad6265SDimitry Andric 75881ad6265SDimitry Andric 75981ad6265SDimitry Andric // __str_find_first_not_of 76081ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 761*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY 76281ad6265SDimitry Andric __str_find_first_not_of(const _CharT *__p, _SizeT __sz, 76381ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 76481ad6265SDimitry Andric { 76581ad6265SDimitry Andric if (__pos < __sz) 76681ad6265SDimitry Andric { 76781ad6265SDimitry Andric const _CharT* __pe = __p + __sz; 76881ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps) 76981ad6265SDimitry Andric if (_Traits::find(__s, __n, *__ps) == nullptr) 77081ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 77181ad6265SDimitry Andric } 77281ad6265SDimitry Andric return __npos; 77381ad6265SDimitry Andric } 77481ad6265SDimitry Andric 77581ad6265SDimitry Andric 77681ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 777*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY 77881ad6265SDimitry Andric __str_find_first_not_of(const _CharT *__p, _SizeT __sz, 77981ad6265SDimitry Andric _CharT __c, _SizeT __pos) _NOEXCEPT 78081ad6265SDimitry Andric { 78181ad6265SDimitry Andric if (__pos < __sz) 78281ad6265SDimitry Andric { 78381ad6265SDimitry Andric const _CharT* __pe = __p + __sz; 78481ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps) 78581ad6265SDimitry Andric if (!_Traits::eq(*__ps, __c)) 78681ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 78781ad6265SDimitry Andric } 78881ad6265SDimitry Andric return __npos; 78981ad6265SDimitry Andric } 79081ad6265SDimitry Andric 79181ad6265SDimitry Andric 79281ad6265SDimitry Andric // __str_find_last_not_of 79381ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 794*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY 79581ad6265SDimitry Andric __str_find_last_not_of(const _CharT *__p, _SizeT __sz, 79681ad6265SDimitry Andric const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT 79781ad6265SDimitry Andric { 79881ad6265SDimitry Andric if (__pos < __sz) 79981ad6265SDimitry Andric ++__pos; 80081ad6265SDimitry Andric else 80181ad6265SDimitry Andric __pos = __sz; 80281ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __p;) 80381ad6265SDimitry Andric if (_Traits::find(__s, __n, *--__ps) == nullptr) 80481ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 80581ad6265SDimitry Andric return __npos; 80681ad6265SDimitry Andric } 80781ad6265SDimitry Andric 80881ad6265SDimitry Andric 80981ad6265SDimitry Andric template<class _CharT, class _SizeT, class _Traits, _SizeT __npos> 810*bdd1243dSDimitry Andric inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_INLINE_VISIBILITY 81181ad6265SDimitry Andric __str_find_last_not_of(const _CharT *__p, _SizeT __sz, 81281ad6265SDimitry Andric _CharT __c, _SizeT __pos) _NOEXCEPT 81381ad6265SDimitry Andric { 81481ad6265SDimitry Andric if (__pos < __sz) 81581ad6265SDimitry Andric ++__pos; 81681ad6265SDimitry Andric else 81781ad6265SDimitry Andric __pos = __sz; 81881ad6265SDimitry Andric for (const _CharT* __ps = __p + __pos; __ps != __p;) 81981ad6265SDimitry Andric if (!_Traits::eq(*--__ps, __c)) 82081ad6265SDimitry Andric return static_cast<_SizeT>(__ps - __p); 82181ad6265SDimitry Andric return __npos; 82281ad6265SDimitry Andric } 82381ad6265SDimitry Andric 82481ad6265SDimitry Andric template<class _Ptr> 82581ad6265SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 82681ad6265SDimitry Andric size_t __do_string_hash(_Ptr __p, _Ptr __e) 82781ad6265SDimitry Andric { 82881ad6265SDimitry Andric typedef typename iterator_traits<_Ptr>::value_type value_type; 82981ad6265SDimitry Andric return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type)); 83081ad6265SDimitry Andric } 83181ad6265SDimitry Andric 83281ad6265SDimitry Andric _LIBCPP_END_NAMESPACE_STD 83381ad6265SDimitry Andric 83481ad6265SDimitry Andric _LIBCPP_POP_MACROS 83581ad6265SDimitry Andric 83681ad6265SDimitry Andric #endif // _LIBCPP___STRING_CHAR_TRAITS_H 837