xref: /freebsd-src/contrib/llvm-project/libcxx/include/__string/char_traits.h (revision 753f127f3ace09432b2baeffd71a308760641a62)
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