blob: a23e7c95fe44eb803e0d7e245d99db66d35116f2 [file] [log] [blame]
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001// -*- C++ -*-
2//===-------------------------- __string ----------------------------------===//
3//
Chandler Carruth7642bb12019-01-19 08:50:56 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Marshall Clowdf63a6d2016-07-21 05:31:24 +00007//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP___STRING
11#define _LIBCPP___STRING
12
Marshall Clowdf63a6d2016-07-21 05:31:24 +000013#include <__config>
Christopher Di Bella55d7a822021-07-01 09:25:35 -040014#include <__algorithm/copy.h>
15#include <__algorithm/copy_backward.h>
16#include <__algorithm/copy_n.h>
17#include <__algorithm/fill_n.h>
18#include <__algorithm/find_first_of.h>
19#include <__algorithm/find_end.h>
20#include <__algorithm/min.h>
21#include <__functional/hash.h> // for __murmur2_or_cityhash
22#include <__iterator/iterator_traits.h>
23#include <cstdio> // for EOF
24#include <cstdint> // for uint_least16_t
25#include <cstring> // for memcpy
26#include <cwchar> // for wmemcpy
27#include <type_traits> // for __libcpp_is_constant_evaluated
Marshall Clowdf63a6d2016-07-21 05:31:24 +000028
Marshall Clowdf63a6d2016-07-21 05:31:24 +000029#include <__debug>
30
31#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
32#pragma GCC system_header
33#endif
34
Eric Fiselierf4433a32017-05-31 22:07:49 +000035_LIBCPP_PUSH_MACROS
36#include <__undef_macros>
37
38
Marshall Clowdf63a6d2016-07-21 05:31:24 +000039_LIBCPP_BEGIN_NAMESPACE_STD
40
Eric Fiselier5dcce5c2020-01-15 17:12:09 -050041// The the extern template ABI lists are kept outside of <string> to improve the
42// readability of that header.
Martijn Vels1e63ba02020-02-19 16:27:50 -050043
44// The extern template ABI lists are kept outside of <string> to improve the
45// readability of that header. We maintain 2 ABI lists:
46// - _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST
47// - _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST
48// As the name implies, the ABI lists define the V1 (Stable) and unstable ABI.
49//
50// For unstable, we may explicitly remove function that are external in V1,
51// and add (new) external functions to better control inlining and compiler
52// optimization opportunities.
53//
54// For stable, the ABI list should rarely change, except for adding new
55// functions supporting new c++ version / API changes. Typically entries
56// must never be removed from the stable list.
57#define _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_Func, _CharType) \
58 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \
59 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \
60 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \
61 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&)) \
62 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \
Arthur O'Dwyer07b22492020-11-27 11:02:06 -050063 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, allocator<_CharType> const&)) \
Martijn Vels1e63ba02020-02-19 16:27:50 -050064 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \
65 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \
66 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \
67 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \
68 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \
69 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type)) \
70 _Func(_LIBCPP_FUNC_VIS const _CharType& basic_string<_CharType>::at(size_type) const) \
71 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \
72 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \
73 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \
74 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*, size_type)) \
75 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \
76 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \
77 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \
78 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \
Arthur O'Dwyer07b22492020-11-27 11:02:06 -050079 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, size_type, size_type, allocator<_CharType> const&)) \
Martijn Vels1e63ba02020-02-19 16:27:50 -050080 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \
81 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(size_type, value_type)) \
82 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \
83 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \
84 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \
85 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \
86 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \
87 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \
88 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \
89 _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \
90 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \
91 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::erase(size_type, size_type)) \
92 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \
93 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \
94 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \
95 _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \
96 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*)) \
97 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \
98 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \
99 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \
100 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \
101 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \
102 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \
103 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \
104 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \
105 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type))
106
107#define _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_Func, _CharType) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500108 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \
109 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \
110 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500111 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500112 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \
113 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \
114 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \
115 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \
116 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \
117 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type)) \
Martijn Vels5e7c9752020-03-04 17:52:46 -0500118 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init_copy_ctor_external(value_type const*, size_type)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500119 _Func(_LIBCPP_FUNC_VIS const _CharType& basic_string<_CharType>::at(size_type) const) \
120 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \
121 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \
122 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \
Martijn Velsda7d94f2020-06-19 14:24:03 -0400123 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*, size_type)) \
124 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500125 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \
126 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \
127 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \
128 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \
Arthur O'Dwyer07b22492020-11-27 11:02:06 -0500129 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, size_type, size_type, allocator<_CharType> const&)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500130 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \
131 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(size_type, value_type)) \
132 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \
133 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \
134 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \
135 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \
Martijn Velsb6a08b62020-04-10 18:36:31 -0400136 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<false>(value_type const*, size_type)) \
137 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<true>(value_type const*, size_type)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500138 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \
139 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \
140 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \
141 _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \
142 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \
Martijn Velsa81fc792020-02-26 13:25:43 -0500143 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__erase_external_with_move(size_type, size_type)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500144 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \
145 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \
146 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \
147 _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500148 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \
149 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \
150 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500151 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \
152 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \
153 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \
154 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \
155 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type))
156
157
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000158// char_traits
159
160template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000161struct _LIBCPP_TEMPLATE_VIS char_traits
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000162{
163 typedef _CharT char_type;
164 typedef int int_type;
165 typedef streamoff off_type;
166 typedef streampos pos_type;
167 typedef mbstate_t state_type;
168
Marshall Clow951035b2017-01-12 04:37:14 +0000169 static inline void _LIBCPP_CONSTEXPR_AFTER_CXX14
170 assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000171 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
172 {return __c1 == __c2;}
173 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
174 {return __c1 < __c2;}
175
Marshall Clow951035b2017-01-12 04:37:14 +0000176 static _LIBCPP_CONSTEXPR_AFTER_CXX14
177 int compare(const char_type* __s1, const char_type* __s2, size_t __n);
178 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
179 size_t length(const char_type* __s);
180 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
181 const char_type* find(const char_type* __s, size_t __n, const char_type& __a);
Michael Parkb5f44472019-11-08 13:42:26 +0000182 static _LIBCPP_CONSTEXPR_AFTER_CXX17
183 char_type* move(char_type* __s1, const char_type* __s2, size_t __n);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000184 _LIBCPP_INLINE_VISIBILITY
Michael Parkb5f44472019-11-08 13:42:26 +0000185 static _LIBCPP_CONSTEXPR_AFTER_CXX17
186 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000187 _LIBCPP_INLINE_VISIBILITY
Michael Parkb5f44472019-11-08 13:42:26 +0000188 static _LIBCPP_CONSTEXPR_AFTER_CXX17
189 char_type* assign(char_type* __s, size_t __n, char_type __a);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000190
191 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
192 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
193 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
194 {return char_type(__c);}
195 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
196 {return int_type(__c);}
197 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
198 {return __c1 == __c2;}
199 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
200 {return int_type(EOF);}
201};
202
203template <class _CharT>
Marshall Clow951035b2017-01-12 04:37:14 +0000204_LIBCPP_CONSTEXPR_AFTER_CXX14 int
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000205char_traits<_CharT>::compare(const char_type* __s1, const char_type* __s2, size_t __n)
206{
207 for (; __n; --__n, ++__s1, ++__s2)
208 {
209 if (lt(*__s1, *__s2))
210 return -1;
211 if (lt(*__s2, *__s1))
212 return 1;
213 }
214 return 0;
215}
216
217template <class _CharT>
218inline
Marshall Clow951035b2017-01-12 04:37:14 +0000219_LIBCPP_CONSTEXPR_AFTER_CXX14 size_t
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000220char_traits<_CharT>::length(const char_type* __s)
221{
222 size_t __len = 0;
223 for (; !eq(*__s, char_type(0)); ++__s)
224 ++__len;
225 return __len;
226}
227
228template <class _CharT>
229inline
Marshall Clow951035b2017-01-12 04:37:14 +0000230_LIBCPP_CONSTEXPR_AFTER_CXX14 const _CharT*
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000231char_traits<_CharT>::find(const char_type* __s, size_t __n, const char_type& __a)
232{
233 for (; __n; --__n)
234 {
235 if (eq(*__s, __a))
236 return __s;
237 ++__s;
238 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500239 return nullptr;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000240}
241
242template <class _CharT>
Michael Parkb5f44472019-11-08 13:42:26 +0000243_LIBCPP_CONSTEXPR_AFTER_CXX17 _CharT*
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000244char_traits<_CharT>::move(char_type* __s1, const char_type* __s2, size_t __n)
245{
Michael Parkb5f44472019-11-08 13:42:26 +0000246 if (__n == 0) return __s1;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000247 char_type* __r = __s1;
248 if (__s1 < __s2)
249 {
250 for (; __n; --__n, ++__s1, ++__s2)
251 assign(*__s1, *__s2);
252 }
253 else if (__s2 < __s1)
254 {
255 __s1 += __n;
256 __s2 += __n;
257 for (; __n; --__n)
258 assign(*--__s1, *--__s2);
259 }
260 return __r;
261}
262
263template <class _CharT>
Michael Parkb5f44472019-11-08 13:42:26 +0000264inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000265_CharT*
266char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n)
267{
268 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
269 char_type* __r = __s1;
270 for (; __n; --__n, ++__s1, ++__s2)
271 assign(*__s1, *__s2);
272 return __r;
273}
274
275template <class _CharT>
Michael Parkb5f44472019-11-08 13:42:26 +0000276inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000277_CharT*
278char_traits<_CharT>::assign(char_type* __s, size_t __n, char_type __a)
279{
280 char_type* __r = __s;
281 for (; __n; --__n, ++__s)
282 assign(*__s, __a);
283 return __r;
284}
285
Michael Parkb5f44472019-11-08 13:42:26 +0000286// constexpr versions of move/copy/assign.
287
288template <class _CharT>
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500289static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000290_CharT* __move_constexpr(_CharT* __s1, const _CharT* __s2, size_t __n) _NOEXCEPT
291{
292 if (__n == 0) return __s1;
293 if (__s1 < __s2) {
294 _VSTD::copy(__s2, __s2 + __n, __s1);
295 } else if (__s2 < __s1) {
296 _VSTD::copy_backward(__s2, __s2 + __n, __s1 + __n);
297 }
298 return __s1;
299}
300
301template <class _CharT>
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500302static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000303_CharT* __copy_constexpr(_CharT* __s1, const _CharT* __s2, size_t __n) _NOEXCEPT
304{
305 _VSTD::copy_n(__s2, __n, __s1);
306 return __s1;
307}
308
309template <class _CharT>
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500310static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000311_CharT* __assign_constexpr(_CharT* __s, size_t __n, _CharT __a) _NOEXCEPT
312{
313 _VSTD::fill_n(__s, __n, __a);
314 return __s;
315}
316
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000317// char_traits<char>
318
319template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000320struct _LIBCPP_TEMPLATE_VIS char_traits<char>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000321{
322 typedef char char_type;
323 typedef int int_type;
324 typedef streamoff off_type;
325 typedef streampos pos_type;
326 typedef mbstate_t state_type;
327
Marshall Clow951035b2017-01-12 04:37:14 +0000328 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
329 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000330 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
331 {return __c1 == __c2;}
332 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
333 {return (unsigned char)__c1 < (unsigned char)__c2;}
334
Marshall Clowaa32f162017-01-12 05:40:58 +0000335 static _LIBCPP_CONSTEXPR_AFTER_CXX14
336 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Marshall Clow951035b2017-01-12 04:37:14 +0000337 static inline size_t _LIBCPP_CONSTEXPR_AFTER_CXX14
338 length(const char_type* __s) _NOEXCEPT {return __builtin_strlen(__s);}
339 static _LIBCPP_CONSTEXPR_AFTER_CXX14
340 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500341 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000342 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
343 {
344 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500345 ? _VSTD::__move_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500346 : __n == 0 ? __s1 : (char_type*)_VSTD::memmove(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000347 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500348 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000349 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000350 {
351 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
Michael Parkb5f44472019-11-08 13:42:26 +0000352 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500353 ? _VSTD::__copy_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500354 : __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000355 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500356 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000357 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
358 {
359 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500360 ? _VSTD::__assign_constexpr(__s, __n, __a)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500361 : __n == 0 ? __s : (char_type*)_VSTD::memset(__s, to_int_type(__a), __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000362 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000363
364 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
365 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
366 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
367 {return char_type(__c);}
368 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
369 {return int_type((unsigned char)__c);}
370 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
371 {return __c1 == __c2;}
372 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
373 {return int_type(EOF);}
374};
375
Marshall Clow951035b2017-01-12 04:37:14 +0000376inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowaa32f162017-01-12 05:40:58 +0000377int
378char_traits<char>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
379{
380 if (__n == 0)
381 return 0;
Marshall Clowb344c362017-01-26 06:58:29 +0000382#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clowaa32f162017-01-12 05:40:58 +0000383 return __builtin_memcmp(__s1, __s2, __n);
384#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500385 return _VSTD::memcmp(__s1, __s2, __n);
Marshall Clowaa32f162017-01-12 05:40:58 +0000386#else
387 for (; __n; --__n, ++__s1, ++__s2)
388 {
389 if (lt(*__s1, *__s2))
390 return -1;
391 if (lt(*__s2, *__s1))
392 return 1;
393 }
394 return 0;
395#endif
396}
397
398inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clow951035b2017-01-12 04:37:14 +0000399const char*
400char_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
401{
402 if (__n == 0)
Marshall Clow32043ac2018-02-06 18:58:05 +0000403 return nullptr;
Marshall Clowb344c362017-01-26 06:58:29 +0000404#if __has_feature(cxx_constexpr_string_builtins)
405 return __builtin_char_memchr(__s, to_int_type(__a), __n);
406#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500407 return (const char_type*) _VSTD::memchr(__s, to_int_type(__a), __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000408#else
409 for (; __n; --__n)
410 {
411 if (eq(*__s, __a))
412 return __s;
413 ++__s;
414 }
Marshall Clow32043ac2018-02-06 18:58:05 +0000415 return nullptr;
Marshall Clow951035b2017-01-12 04:37:14 +0000416#endif
417}
418
419
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000420// char_traits<wchar_t>
421
422template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000423struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000424{
425 typedef wchar_t char_type;
426 typedef wint_t int_type;
427 typedef streamoff off_type;
428 typedef streampos pos_type;
429 typedef mbstate_t state_type;
430
Marshall Clow951035b2017-01-12 04:37:14 +0000431 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
432 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000433 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
434 {return __c1 == __c2;}
435 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
436 {return __c1 < __c2;}
437
Marshall Clow951035b2017-01-12 04:37:14 +0000438 static _LIBCPP_CONSTEXPR_AFTER_CXX14
439 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
440 static _LIBCPP_CONSTEXPR_AFTER_CXX14
441 size_t length(const char_type* __s) _NOEXCEPT;
442 static _LIBCPP_CONSTEXPR_AFTER_CXX14
443 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500444 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000445 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
446 {
447 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500448 ? _VSTD::__move_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500449 : __n == 0 ? __s1 : _VSTD::wmemmove(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000450 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500451 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000452 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000453 {
454 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
Michael Parkb5f44472019-11-08 13:42:26 +0000455 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500456 ? _VSTD::__copy_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500457 : __n == 0 ? __s1 : _VSTD::wmemcpy(__s1, __s2, __n);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000458 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500459 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000460 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
461 {
462 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500463 ? _VSTD::__assign_constexpr(__s, __n, __a)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500464 : __n == 0 ? __s : _VSTD::wmemset(__s, __a, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000465 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000466 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
467 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
468 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
469 {return char_type(__c);}
470 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
471 {return int_type(__c);}
472 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
473 {return __c1 == __c2;}
474 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
475 {return int_type(WEOF);}
476};
477
Marshall Clow951035b2017-01-12 04:37:14 +0000478inline _LIBCPP_CONSTEXPR_AFTER_CXX14
479int
480char_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
481{
482 if (__n == 0)
483 return 0;
Marshall Clowb344c362017-01-26 06:58:29 +0000484#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clow951035b2017-01-12 04:37:14 +0000485 return __builtin_wmemcmp(__s1, __s2, __n);
486#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500487 return _VSTD::wmemcmp(__s1, __s2, __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000488#else
489 for (; __n; --__n, ++__s1, ++__s2)
490 {
491 if (lt(*__s1, *__s2))
492 return -1;
493 if (lt(*__s2, *__s1))
494 return 1;
495 }
496 return 0;
497#endif
498}
499
500inline _LIBCPP_CONSTEXPR_AFTER_CXX14
501size_t
502char_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT
503{
Marshall Clowb344c362017-01-26 06:58:29 +0000504#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clow951035b2017-01-12 04:37:14 +0000505 return __builtin_wcslen(__s);
506#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500507 return _VSTD::wcslen(__s);
Marshall Clow951035b2017-01-12 04:37:14 +0000508#else
509 size_t __len = 0;
510 for (; !eq(*__s, char_type(0)); ++__s)
511 ++__len;
512 return __len;
513#endif
514}
515
516inline _LIBCPP_CONSTEXPR_AFTER_CXX14
517const wchar_t*
518char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
519{
520 if (__n == 0)
Marshall Clow32043ac2018-02-06 18:58:05 +0000521 return nullptr;
Marshall Clowb344c362017-01-26 06:58:29 +0000522#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clow32043ac2018-02-06 18:58:05 +0000523 return __builtin_wmemchr(__s, __a, __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000524#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500525 return _VSTD::wmemchr(__s, __a, __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000526#else
527 for (; __n; --__n)
528 {
529 if (eq(*__s, __a))
530 return __s;
531 ++__s;
532 }
Marshall Clow32043ac2018-02-06 18:58:05 +0000533 return nullptr;
Marshall Clow951035b2017-01-12 04:37:14 +0000534#endif
535}
536
Louis Dionne76f4e0b2021-09-09 13:23:26 -0400537template <class _Traits>
538_LIBCPP_INLINE_VISIBILITY
539_LIBCPP_CONSTEXPR
540inline size_t __char_traits_length_checked(const typename _Traits::char_type* __s) _NOEXCEPT {
541#if _LIBCPP_DEBUG_LEVEL >= 1
542 return __s ? _Traits::length(__s) : (_VSTD::__libcpp_debug_function(_VSTD::__libcpp_debug_info(__FILE__, __LINE__, "p == nullptr", "null pointer pass to non-null argument of char_traits<...>::length")), 0);
543#else
544 return _Traits::length(__s);
545#endif
546}
Marshall Clow951035b2017-01-12 04:37:14 +0000547
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400548#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marshall Clow8732fed2018-12-11 04:35:44 +0000549
550template <>
551struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
552{
553 typedef char8_t char_type;
554 typedef unsigned int int_type;
555 typedef streamoff off_type;
556 typedef u8streampos pos_type;
557 typedef mbstate_t state_type;
558
559 static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
560 {__c1 = __c2;}
561 static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept
562 {return __c1 == __c2;}
563 static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept
564 {return __c1 < __c2;}
565
566 static constexpr
567 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
568
569 static constexpr
570 size_t length(const char_type* __s) _NOEXCEPT;
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700571
Marshall Clow8732fed2018-12-11 04:35:44 +0000572 _LIBCPP_INLINE_VISIBILITY static constexpr
573 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700574
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500575 static _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000576 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
577 {
578 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500579 ? _VSTD::__move_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500580 : __n == 0 ? __s1 : (char_type*)_VSTD::memmove(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000581 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700582
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500583 static _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000584 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clow8732fed2018-12-11 04:35:44 +0000585 {
586 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
Michael Parkb5f44472019-11-08 13:42:26 +0000587 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500588 ? _VSTD::__copy_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500589 : __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000590 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700591
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500592 static _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000593 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
594 {
595 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500596 ? _VSTD::__assign_constexpr(__s, __n, __a)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500597 : __n == 0 ? __s : (char_type*)_VSTD::memset(__s, to_int_type(__a), __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000598 }
Marshall Clow8732fed2018-12-11 04:35:44 +0000599
600 static inline constexpr int_type not_eof(int_type __c) noexcept
601 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
602 static inline constexpr char_type to_char_type(int_type __c) noexcept
603 {return char_type(__c);}
604 static inline constexpr int_type to_int_type(char_type __c) noexcept
605 {return int_type(__c);}
606 static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept
607 {return __c1 == __c2;}
608 static inline constexpr int_type eof() noexcept
609 {return int_type(EOF);}
610};
611
612// TODO use '__builtin_strlen' if it ever supports char8_t ??
613inline constexpr
614size_t
615char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
616{
617 size_t __len = 0;
618 for (; !eq(*__s, char_type(0)); ++__s)
619 ++__len;
620 return __len;
621}
622
623inline constexpr
624int
625char_traits<char8_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
626{
627#if __has_feature(cxx_constexpr_string_builtins)
628 return __builtin_memcmp(__s1, __s2, __n);
629#else
630 for (; __n; --__n, ++__s1, ++__s2)
631 {
632 if (lt(*__s1, *__s2))
633 return -1;
634 if (lt(*__s2, *__s1))
635 return 1;
636 }
637 return 0;
638#endif
639}
640
641// TODO use '__builtin_char_memchr' if it ever supports char8_t ??
642inline constexpr
643const char8_t*
644char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
645{
646 for (; __n; --__n)
647 {
648 if (eq(*__s, __a))
649 return __s;
650 ++__s;
651 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500652 return nullptr;
Marshall Clow8732fed2018-12-11 04:35:44 +0000653}
654
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400655#endif // #_LIBCPP_HAS_NO_CHAR8_T
Marshall Clow8732fed2018-12-11 04:35:44 +0000656
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000657#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
658
659template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000660struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000661{
662 typedef char16_t char_type;
663 typedef uint_least16_t int_type;
664 typedef streamoff off_type;
665 typedef u16streampos pos_type;
666 typedef mbstate_t state_type;
667
Marshall Clow951035b2017-01-12 04:37:14 +0000668 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
669 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000670 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
671 {return __c1 == __c2;}
672 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
673 {return __c1 < __c2;}
674
Marshall Clow951035b2017-01-12 04:37:14 +0000675 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
676 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
677 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
678 size_t length(const char_type* __s) _NOEXCEPT;
679 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
680 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000681 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000682 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000683 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000684 static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000685 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000686 static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000687
688 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
689 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
690 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
691 {return char_type(__c);}
692 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
693 {return int_type(__c);}
694 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
695 {return __c1 == __c2;}
696 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
697 {return int_type(0xFFFF);}
698};
699
Marshall Clow951035b2017-01-12 04:37:14 +0000700inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000701int
Marshall Clow36097db2016-07-28 04:52:02 +0000702char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000703{
704 for (; __n; --__n, ++__s1, ++__s2)
705 {
706 if (lt(*__s1, *__s2))
707 return -1;
708 if (lt(*__s2, *__s1))
709 return 1;
710 }
711 return 0;
712}
713
Marshall Clow951035b2017-01-12 04:37:14 +0000714inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000715size_t
Marshall Clow36097db2016-07-28 04:52:02 +0000716char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000717{
718 size_t __len = 0;
719 for (; !eq(*__s, char_type(0)); ++__s)
720 ++__len;
721 return __len;
722}
723
Marshall Clow951035b2017-01-12 04:37:14 +0000724inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000725const char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000726char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000727{
728 for (; __n; --__n)
729 {
730 if (eq(*__s, __a))
731 return __s;
732 ++__s;
733 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500734 return nullptr;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000735}
736
Michael Parkb5f44472019-11-08 13:42:26 +0000737inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000738char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000739char_traits<char16_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000740{
Michael Parkb5f44472019-11-08 13:42:26 +0000741 if (__n == 0) return __s1;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000742 char_type* __r = __s1;
743 if (__s1 < __s2)
744 {
745 for (; __n; --__n, ++__s1, ++__s2)
746 assign(*__s1, *__s2);
747 }
748 else if (__s2 < __s1)
749 {
750 __s1 += __n;
751 __s2 += __n;
752 for (; __n; --__n)
753 assign(*--__s1, *--__s2);
754 }
755 return __r;
756}
757
Michael Parkb5f44472019-11-08 13:42:26 +0000758inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000759char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000760char_traits<char16_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000761{
762 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
763 char_type* __r = __s1;
764 for (; __n; --__n, ++__s1, ++__s2)
765 assign(*__s1, *__s2);
766 return __r;
767}
768
Michael Parkb5f44472019-11-08 13:42:26 +0000769inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000770char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000771char_traits<char16_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000772{
773 char_type* __r = __s;
774 for (; __n; --__n, ++__s)
775 assign(*__s, __a);
776 return __r;
777}
778
779template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000780struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000781{
782 typedef char32_t char_type;
783 typedef uint_least32_t int_type;
784 typedef streamoff off_type;
785 typedef u32streampos pos_type;
786 typedef mbstate_t state_type;
787
Marshall Clow951035b2017-01-12 04:37:14 +0000788 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
789 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000790 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
791 {return __c1 == __c2;}
792 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
793 {return __c1 < __c2;}
794
Marshall Clow951035b2017-01-12 04:37:14 +0000795 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
796 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
797 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
798 size_t length(const char_type* __s) _NOEXCEPT;
799 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
800 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000801 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000802 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000803 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000804 static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000805 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000806 static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000807
808 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
809 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
810 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
811 {return char_type(__c);}
812 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
813 {return int_type(__c);}
814 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
815 {return __c1 == __c2;}
816 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
817 {return int_type(0xFFFFFFFF);}
818};
819
Marshall Clow951035b2017-01-12 04:37:14 +0000820inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000821int
Marshall Clow36097db2016-07-28 04:52:02 +0000822char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000823{
824 for (; __n; --__n, ++__s1, ++__s2)
825 {
826 if (lt(*__s1, *__s2))
827 return -1;
828 if (lt(*__s2, *__s1))
829 return 1;
830 }
831 return 0;
832}
833
Marshall Clow951035b2017-01-12 04:37:14 +0000834inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000835size_t
Marshall Clow36097db2016-07-28 04:52:02 +0000836char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000837{
838 size_t __len = 0;
839 for (; !eq(*__s, char_type(0)); ++__s)
840 ++__len;
841 return __len;
842}
843
Marshall Clow951035b2017-01-12 04:37:14 +0000844inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000845const char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000846char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000847{
848 for (; __n; --__n)
849 {
850 if (eq(*__s, __a))
851 return __s;
852 ++__s;
853 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500854 return nullptr;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000855}
856
Michael Parkb5f44472019-11-08 13:42:26 +0000857inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000858char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000859char_traits<char32_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000860{
Michael Parkb5f44472019-11-08 13:42:26 +0000861 if (__n == 0) return __s1;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000862 char_type* __r = __s1;
863 if (__s1 < __s2)
864 {
865 for (; __n; --__n, ++__s1, ++__s2)
866 assign(*__s1, *__s2);
867 }
868 else if (__s2 < __s1)
869 {
870 __s1 += __n;
871 __s2 += __n;
872 for (; __n; --__n)
873 assign(*--__s1, *--__s2);
874 }
875 return __r;
876}
877
Michael Parkb5f44472019-11-08 13:42:26 +0000878inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000879char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000880char_traits<char32_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000881{
882 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
883 char_type* __r = __s1;
884 for (; __n; --__n, ++__s1, ++__s2)
885 assign(*__s1, *__s2);
886 return __r;
887}
888
Michael Parkb5f44472019-11-08 13:42:26 +0000889inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000890char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000891char_traits<char32_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000892{
893 char_type* __r = __s;
894 for (; __n; --__n, ++__s)
895 assign(*__s, __a);
896 return __r;
897}
898
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400899#endif // _LIBCPP_HAS_NO_UNICODE_CHARS
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000900
901// helper fns for basic_string and string_view
902
903// __str_find
904template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
905inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700906__str_find(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000907 _CharT __c, _SizeT __pos) _NOEXCEPT
908{
909 if (__pos >= __sz)
910 return __npos;
911 const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
Bruce Mitchener170d8972020-11-24 12:53:53 -0500912 if (__r == nullptr)
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000913 return __npos;
914 return static_cast<_SizeT>(__r - __p);
915}
916
Sebastian Pop65115202016-12-30 18:01:36 +0000917template <class _CharT, class _Traits>
918inline _LIBCPP_CONSTEXPR_AFTER_CXX11 const _CharT *
919__search_substring(const _CharT *__first1, const _CharT *__last1,
zoecarver1997e0a2021-02-05 11:54:47 -0800920 const _CharT *__first2, const _CharT *__last2) _NOEXCEPT {
Sebastian Pop65115202016-12-30 18:01:36 +0000921 // Take advantage of knowing source and pattern lengths.
922 // Stop short when source is smaller than pattern.
923 const ptrdiff_t __len2 = __last2 - __first2;
924 if (__len2 == 0)
925 return __first1;
926
927 ptrdiff_t __len1 = __last1 - __first1;
928 if (__len1 < __len2)
929 return __last1;
930
931 // First element of __first2 is loop invariant.
932 _CharT __f2 = *__first2;
933 while (true) {
934 __len1 = __last1 - __first1;
935 // Check whether __first1 still has at least __len2 bytes.
936 if (__len1 < __len2)
937 return __last1;
938
939 // Find __f2 the first byte matching in __first1.
940 __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
Bruce Mitchener170d8972020-11-24 12:53:53 -0500941 if (__first1 == nullptr)
Sebastian Pop65115202016-12-30 18:01:36 +0000942 return __last1;
943
944 // It is faster to compare from the first byte of __first1 even if we
945 // already know that it matches the first byte of __first2: this is because
946 // __first2 is most likely aligned, as it is user's "pattern" string, and
947 // __first1 + 1 is most likely not aligned, as the match is in the middle of
948 // the string.
949 if (_Traits::compare(__first1, __first2, __len2) == 0)
950 return __first1;
951
952 ++__first1;
953 }
954}
955
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000956template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
957inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700958__str_find(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000959 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
960{
Sebastian Pop65115202016-12-30 18:01:36 +0000961 if (__pos > __sz)
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000962 return __npos;
Sebastian Pop65115202016-12-30 18:01:36 +0000963
964 if (__n == 0) // There is nothing to search, just return __pos.
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000965 return __pos;
Sebastian Pop65115202016-12-30 18:01:36 +0000966
967 const _CharT *__r = __search_substring<_CharT, _Traits>(
968 __p + __pos, __p + __sz, __s, __s + __n);
969
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000970 if (__r == __p + __sz)
971 return __npos;
972 return static_cast<_SizeT>(__r - __p);
973}
974
975
976// __str_rfind
977
978template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
979inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700980__str_rfind(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000981 _CharT __c, _SizeT __pos) _NOEXCEPT
982{
983 if (__sz < 1)
984 return __npos;
985 if (__pos < __sz)
986 ++__pos;
987 else
988 __pos = __sz;
989 for (const _CharT* __ps = __p + __pos; __ps != __p;)
990 {
991 if (_Traits::eq(*--__ps, __c))
992 return static_cast<_SizeT>(__ps - __p);
993 }
994 return __npos;
995}
996
997template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
998inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700999__str_rfind(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001000 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1001{
1002 __pos = _VSTD::min(__pos, __sz);
1003 if (__n < __sz - __pos)
1004 __pos += __n;
1005 else
1006 __pos = __sz;
1007 const _CharT* __r = _VSTD::__find_end(
Louis Dionnefd77e4f2019-10-23 10:40:15 -07001008 __p, __p + __pos, __s, __s + __n, _Traits::eq,
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001009 random_access_iterator_tag(), random_access_iterator_tag());
1010 if (__n > 0 && __r == __p + __pos)
1011 return __npos;
1012 return static_cast<_SizeT>(__r - __p);
1013}
1014
1015// __str_find_first_of
1016template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1017inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1018__str_find_first_of(const _CharT *__p, _SizeT __sz,
1019 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1020{
1021 if (__pos >= __sz || __n == 0)
1022 return __npos;
1023 const _CharT* __r = _VSTD::__find_first_of_ce
1024 (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq );
1025 if (__r == __p + __sz)
1026 return __npos;
1027 return static_cast<_SizeT>(__r - __p);
1028}
1029
1030
1031// __str_find_last_of
1032template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1033inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1034__str_find_last_of(const _CharT *__p, _SizeT __sz,
1035 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1036 {
1037 if (__n != 0)
1038 {
1039 if (__pos < __sz)
1040 ++__pos;
1041 else
1042 __pos = __sz;
1043 for (const _CharT* __ps = __p + __pos; __ps != __p;)
1044 {
1045 const _CharT* __r = _Traits::find(__s, __n, *--__ps);
1046 if (__r)
1047 return static_cast<_SizeT>(__ps - __p);
1048 }
1049 }
1050 return __npos;
1051}
1052
1053
1054// __str_find_first_not_of
1055template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1056inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1057__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
1058 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1059{
1060 if (__pos < __sz)
1061 {
1062 const _CharT* __pe = __p + __sz;
1063 for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
Bruce Mitchener170d8972020-11-24 12:53:53 -05001064 if (_Traits::find(__s, __n, *__ps) == nullptr)
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001065 return static_cast<_SizeT>(__ps - __p);
1066 }
1067 return __npos;
1068}
1069
1070
1071template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1072inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1073__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
1074 _CharT __c, _SizeT __pos) _NOEXCEPT
1075{
1076 if (__pos < __sz)
1077 {
1078 const _CharT* __pe = __p + __sz;
1079 for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
1080 if (!_Traits::eq(*__ps, __c))
1081 return static_cast<_SizeT>(__ps - __p);
1082 }
1083 return __npos;
1084}
1085
1086
1087// __str_find_last_not_of
1088template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1089inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1090__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
1091 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1092{
1093 if (__pos < __sz)
1094 ++__pos;
1095 else
1096 __pos = __sz;
1097 for (const _CharT* __ps = __p + __pos; __ps != __p;)
Bruce Mitchener170d8972020-11-24 12:53:53 -05001098 if (_Traits::find(__s, __n, *--__ps) == nullptr)
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001099 return static_cast<_SizeT>(__ps - __p);
1100 return __npos;
1101}
1102
1103
1104template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1105inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1106__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
1107 _CharT __c, _SizeT __pos) _NOEXCEPT
1108{
1109 if (__pos < __sz)
1110 ++__pos;
1111 else
1112 __pos = __sz;
1113 for (const _CharT* __ps = __p + __pos; __ps != __p;)
1114 if (!_Traits::eq(*--__ps, __c))
1115 return static_cast<_SizeT>(__ps - __p);
1116 return __npos;
1117}
1118
1119template<class _Ptr>
Eric Fiselier1b57fa82016-09-15 22:27:07 +00001120inline _LIBCPP_INLINE_VISIBILITY
1121size_t __do_string_hash(_Ptr __p, _Ptr __e)
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001122{
1123 typedef typename iterator_traits<_Ptr>::value_type value_type;
1124 return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));
1125}
1126
1127template <class _CharT, class _Iter, class _Traits=char_traits<_CharT> >
1128struct __quoted_output_proxy
1129{
1130 _Iter __first;
1131 _Iter __last;
1132 _CharT __delim;
1133 _CharT __escape;
1134
1135 __quoted_output_proxy(_Iter __f, _Iter __l, _CharT __d, _CharT __e)
1136 : __first(__f), __last(__l), __delim(__d), __escape(__e) {}
Louis Dionnefd77e4f2019-10-23 10:40:15 -07001137 // This would be a nice place for a string_ref
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001138};
1139
1140_LIBCPP_END_NAMESPACE_STD
1141
Eric Fiselierf4433a32017-05-31 22:07:49 +00001142_LIBCPP_POP_MACROS
1143
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001144#endif // _LIBCPP___STRING