blob: a968fc0ac5b83d01fd175a4fc4a0b47496fb0eb7 [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{
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400268 if (!__libcpp_is_constant_evaluated()) {
269 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
270 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000271 char_type* __r = __s1;
272 for (; __n; --__n, ++__s1, ++__s2)
273 assign(*__s1, *__s2);
274 return __r;
275}
276
277template <class _CharT>
Michael Parkb5f44472019-11-08 13:42:26 +0000278inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000279_CharT*
280char_traits<_CharT>::assign(char_type* __s, size_t __n, char_type __a)
281{
282 char_type* __r = __s;
283 for (; __n; --__n, ++__s)
284 assign(*__s, __a);
285 return __r;
286}
287
Michael Parkb5f44472019-11-08 13:42:26 +0000288// constexpr versions of move/copy/assign.
289
290template <class _CharT>
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500291static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000292_CharT* __move_constexpr(_CharT* __s1, const _CharT* __s2, size_t __n) _NOEXCEPT
293{
294 if (__n == 0) return __s1;
295 if (__s1 < __s2) {
296 _VSTD::copy(__s2, __s2 + __n, __s1);
297 } else if (__s2 < __s1) {
298 _VSTD::copy_backward(__s2, __s2 + __n, __s1 + __n);
299 }
300 return __s1;
301}
302
303template <class _CharT>
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500304static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000305_CharT* __copy_constexpr(_CharT* __s1, const _CharT* __s2, size_t __n) _NOEXCEPT
306{
307 _VSTD::copy_n(__s2, __n, __s1);
308 return __s1;
309}
310
311template <class _CharT>
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500312static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000313_CharT* __assign_constexpr(_CharT* __s, size_t __n, _CharT __a) _NOEXCEPT
314{
315 _VSTD::fill_n(__s, __n, __a);
316 return __s;
317}
318
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000319// char_traits<char>
320
321template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000322struct _LIBCPP_TEMPLATE_VIS char_traits<char>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000323{
324 typedef char char_type;
325 typedef int int_type;
326 typedef streamoff off_type;
327 typedef streampos pos_type;
328 typedef mbstate_t state_type;
329
Marshall Clow951035b2017-01-12 04:37:14 +0000330 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
331 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000332 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
333 {return __c1 == __c2;}
334 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
335 {return (unsigned char)__c1 < (unsigned char)__c2;}
336
Marshall Clowaa32f162017-01-12 05:40:58 +0000337 static _LIBCPP_CONSTEXPR_AFTER_CXX14
338 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Marshall Clow951035b2017-01-12 04:37:14 +0000339 static inline size_t _LIBCPP_CONSTEXPR_AFTER_CXX14
340 length(const char_type* __s) _NOEXCEPT {return __builtin_strlen(__s);}
341 static _LIBCPP_CONSTEXPR_AFTER_CXX14
342 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500343 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000344 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
345 {
346 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500347 ? _VSTD::__move_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500348 : __n == 0 ? __s1 : (char_type*)_VSTD::memmove(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000349 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500350 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000351 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000352 {
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400353 if (!__libcpp_is_constant_evaluated()) {
354 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
355 }
Michael Parkb5f44472019-11-08 13:42:26 +0000356 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500357 ? _VSTD::__copy_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500358 : __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000359 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500360 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000361 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
362 {
363 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500364 ? _VSTD::__assign_constexpr(__s, __n, __a)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500365 : __n == 0 ? __s : (char_type*)_VSTD::memset(__s, to_int_type(__a), __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000366 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000367
368 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
369 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
370 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
371 {return char_type(__c);}
372 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
373 {return int_type((unsigned char)__c);}
374 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
375 {return __c1 == __c2;}
376 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
377 {return int_type(EOF);}
378};
379
Marshall Clow951035b2017-01-12 04:37:14 +0000380inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowaa32f162017-01-12 05:40:58 +0000381int
382char_traits<char>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
383{
384 if (__n == 0)
385 return 0;
Marshall Clowb344c362017-01-26 06:58:29 +0000386#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clowaa32f162017-01-12 05:40:58 +0000387 return __builtin_memcmp(__s1, __s2, __n);
388#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500389 return _VSTD::memcmp(__s1, __s2, __n);
Marshall Clowaa32f162017-01-12 05:40:58 +0000390#else
391 for (; __n; --__n, ++__s1, ++__s2)
392 {
393 if (lt(*__s1, *__s2))
394 return -1;
395 if (lt(*__s2, *__s1))
396 return 1;
397 }
398 return 0;
399#endif
400}
401
402inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clow951035b2017-01-12 04:37:14 +0000403const char*
404char_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
405{
406 if (__n == 0)
Marshall Clow32043ac2018-02-06 18:58:05 +0000407 return nullptr;
Marshall Clowb344c362017-01-26 06:58:29 +0000408#if __has_feature(cxx_constexpr_string_builtins)
409 return __builtin_char_memchr(__s, to_int_type(__a), __n);
410#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500411 return (const char_type*) _VSTD::memchr(__s, to_int_type(__a), __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000412#else
413 for (; __n; --__n)
414 {
415 if (eq(*__s, __a))
416 return __s;
417 ++__s;
418 }
Marshall Clow32043ac2018-02-06 18:58:05 +0000419 return nullptr;
Marshall Clow951035b2017-01-12 04:37:14 +0000420#endif
421}
422
423
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000424// char_traits<wchar_t>
425
426template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000427struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000428{
429 typedef wchar_t char_type;
430 typedef wint_t int_type;
431 typedef streamoff off_type;
432 typedef streampos pos_type;
433 typedef mbstate_t state_type;
434
Marshall Clow951035b2017-01-12 04:37:14 +0000435 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
436 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000437 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
438 {return __c1 == __c2;}
439 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
440 {return __c1 < __c2;}
441
Marshall Clow951035b2017-01-12 04:37:14 +0000442 static _LIBCPP_CONSTEXPR_AFTER_CXX14
443 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
444 static _LIBCPP_CONSTEXPR_AFTER_CXX14
445 size_t length(const char_type* __s) _NOEXCEPT;
446 static _LIBCPP_CONSTEXPR_AFTER_CXX14
447 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500448 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000449 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
450 {
451 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500452 ? _VSTD::__move_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500453 : __n == 0 ? __s1 : _VSTD::wmemmove(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000454 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500455 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000456 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000457 {
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400458 if (!__libcpp_is_constant_evaluated()) {
459 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
460 }
Michael Parkb5f44472019-11-08 13:42:26 +0000461 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500462 ? _VSTD::__copy_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500463 : __n == 0 ? __s1 : _VSTD::wmemcpy(__s1, __s2, __n);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000464 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500465 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000466 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
467 {
468 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500469 ? _VSTD::__assign_constexpr(__s, __n, __a)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500470 : __n == 0 ? __s : _VSTD::wmemset(__s, __a, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000471 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000472 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
473 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
474 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
475 {return char_type(__c);}
476 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
477 {return int_type(__c);}
478 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
479 {return __c1 == __c2;}
480 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
481 {return int_type(WEOF);}
482};
483
Marshall Clow951035b2017-01-12 04:37:14 +0000484inline _LIBCPP_CONSTEXPR_AFTER_CXX14
485int
486char_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
487{
488 if (__n == 0)
489 return 0;
Marshall Clowb344c362017-01-26 06:58:29 +0000490#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clow951035b2017-01-12 04:37:14 +0000491 return __builtin_wmemcmp(__s1, __s2, __n);
492#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500493 return _VSTD::wmemcmp(__s1, __s2, __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000494#else
495 for (; __n; --__n, ++__s1, ++__s2)
496 {
497 if (lt(*__s1, *__s2))
498 return -1;
499 if (lt(*__s2, *__s1))
500 return 1;
501 }
502 return 0;
503#endif
504}
505
506inline _LIBCPP_CONSTEXPR_AFTER_CXX14
507size_t
508char_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT
509{
Marshall Clowb344c362017-01-26 06:58:29 +0000510#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clow951035b2017-01-12 04:37:14 +0000511 return __builtin_wcslen(__s);
512#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500513 return _VSTD::wcslen(__s);
Marshall Clow951035b2017-01-12 04:37:14 +0000514#else
515 size_t __len = 0;
516 for (; !eq(*__s, char_type(0)); ++__s)
517 ++__len;
518 return __len;
519#endif
520}
521
522inline _LIBCPP_CONSTEXPR_AFTER_CXX14
523const wchar_t*
524char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
525{
526 if (__n == 0)
Marshall Clow32043ac2018-02-06 18:58:05 +0000527 return nullptr;
Marshall Clowb344c362017-01-26 06:58:29 +0000528#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clow32043ac2018-02-06 18:58:05 +0000529 return __builtin_wmemchr(__s, __a, __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000530#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500531 return _VSTD::wmemchr(__s, __a, __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000532#else
533 for (; __n; --__n)
534 {
535 if (eq(*__s, __a))
536 return __s;
537 ++__s;
538 }
Marshall Clow32043ac2018-02-06 18:58:05 +0000539 return nullptr;
Marshall Clow951035b2017-01-12 04:37:14 +0000540#endif
541}
542
Louis Dionne76f4e0b2021-09-09 13:23:26 -0400543template <class _Traits>
544_LIBCPP_INLINE_VISIBILITY
545_LIBCPP_CONSTEXPR
546inline size_t __char_traits_length_checked(const typename _Traits::char_type* __s) _NOEXCEPT {
547#if _LIBCPP_DEBUG_LEVEL >= 1
548 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);
549#else
550 return _Traits::length(__s);
551#endif
552}
Marshall Clow951035b2017-01-12 04:37:14 +0000553
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400554#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marshall Clow8732fed2018-12-11 04:35:44 +0000555
556template <>
557struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
558{
559 typedef char8_t char_type;
560 typedef unsigned int int_type;
561 typedef streamoff off_type;
562 typedef u8streampos pos_type;
563 typedef mbstate_t state_type;
564
565 static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
566 {__c1 = __c2;}
567 static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept
568 {return __c1 == __c2;}
569 static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept
570 {return __c1 < __c2;}
571
572 static constexpr
573 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
574
575 static constexpr
576 size_t length(const char_type* __s) _NOEXCEPT;
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700577
Marshall Clow8732fed2018-12-11 04:35:44 +0000578 _LIBCPP_INLINE_VISIBILITY static constexpr
579 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700580
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500581 static _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000582 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
583 {
584 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500585 ? _VSTD::__move_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500586 : __n == 0 ? __s1 : (char_type*)_VSTD::memmove(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000587 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700588
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500589 static _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000590 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400591 {
592 if (!__libcpp_is_constant_evaluated()) {
593 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
594 }
Michael Parkb5f44472019-11-08 13:42:26 +0000595 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500596 ? _VSTD::__copy_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500597 : __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000598 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700599
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500600 static _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000601 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
602 {
603 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500604 ? _VSTD::__assign_constexpr(__s, __n, __a)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500605 : __n == 0 ? __s : (char_type*)_VSTD::memset(__s, to_int_type(__a), __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000606 }
Marshall Clow8732fed2018-12-11 04:35:44 +0000607
608 static inline constexpr int_type not_eof(int_type __c) noexcept
609 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
610 static inline constexpr char_type to_char_type(int_type __c) noexcept
611 {return char_type(__c);}
612 static inline constexpr int_type to_int_type(char_type __c) noexcept
613 {return int_type(__c);}
614 static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept
615 {return __c1 == __c2;}
616 static inline constexpr int_type eof() noexcept
617 {return int_type(EOF);}
618};
619
620// TODO use '__builtin_strlen' if it ever supports char8_t ??
621inline constexpr
622size_t
623char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
624{
625 size_t __len = 0;
626 for (; !eq(*__s, char_type(0)); ++__s)
627 ++__len;
628 return __len;
629}
630
631inline constexpr
632int
633char_traits<char8_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
634{
635#if __has_feature(cxx_constexpr_string_builtins)
636 return __builtin_memcmp(__s1, __s2, __n);
637#else
638 for (; __n; --__n, ++__s1, ++__s2)
639 {
640 if (lt(*__s1, *__s2))
641 return -1;
642 if (lt(*__s2, *__s1))
643 return 1;
644 }
645 return 0;
646#endif
647}
648
649// TODO use '__builtin_char_memchr' if it ever supports char8_t ??
650inline constexpr
651const char8_t*
652char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
653{
654 for (; __n; --__n)
655 {
656 if (eq(*__s, __a))
657 return __s;
658 ++__s;
659 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500660 return nullptr;
Marshall Clow8732fed2018-12-11 04:35:44 +0000661}
662
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400663#endif // #_LIBCPP_HAS_NO_CHAR8_T
Marshall Clow8732fed2018-12-11 04:35:44 +0000664
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000665#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
666
667template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000668struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000669{
670 typedef char16_t char_type;
671 typedef uint_least16_t int_type;
672 typedef streamoff off_type;
673 typedef u16streampos pos_type;
674 typedef mbstate_t state_type;
675
Marshall Clow951035b2017-01-12 04:37:14 +0000676 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
677 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000678 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
679 {return __c1 == __c2;}
680 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
681 {return __c1 < __c2;}
682
Marshall Clow951035b2017-01-12 04:37:14 +0000683 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
684 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
685 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
686 size_t length(const char_type* __s) _NOEXCEPT;
687 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
688 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000689 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000690 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000691 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000692 static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000693 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000694 static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000695
696 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
697 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
698 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
699 {return char_type(__c);}
700 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
701 {return int_type(__c);}
702 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
703 {return __c1 == __c2;}
704 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
705 {return int_type(0xFFFF);}
706};
707
Marshall Clow951035b2017-01-12 04:37:14 +0000708inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000709int
Marshall Clow36097db2016-07-28 04:52:02 +0000710char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000711{
712 for (; __n; --__n, ++__s1, ++__s2)
713 {
714 if (lt(*__s1, *__s2))
715 return -1;
716 if (lt(*__s2, *__s1))
717 return 1;
718 }
719 return 0;
720}
721
Marshall Clow951035b2017-01-12 04:37:14 +0000722inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000723size_t
Marshall Clow36097db2016-07-28 04:52:02 +0000724char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000725{
726 size_t __len = 0;
727 for (; !eq(*__s, char_type(0)); ++__s)
728 ++__len;
729 return __len;
730}
731
Marshall Clow951035b2017-01-12 04:37:14 +0000732inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000733const char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000734char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000735{
736 for (; __n; --__n)
737 {
738 if (eq(*__s, __a))
739 return __s;
740 ++__s;
741 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500742 return nullptr;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000743}
744
Michael Parkb5f44472019-11-08 13:42:26 +0000745inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000746char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000747char_traits<char16_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000748{
Michael Parkb5f44472019-11-08 13:42:26 +0000749 if (__n == 0) return __s1;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000750 char_type* __r = __s1;
751 if (__s1 < __s2)
752 {
753 for (; __n; --__n, ++__s1, ++__s2)
754 assign(*__s1, *__s2);
755 }
756 else if (__s2 < __s1)
757 {
758 __s1 += __n;
759 __s2 += __n;
760 for (; __n; --__n)
761 assign(*--__s1, *--__s2);
762 }
763 return __r;
764}
765
Michael Parkb5f44472019-11-08 13:42:26 +0000766inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000767char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000768char_traits<char16_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000769{
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400770 if (!__libcpp_is_constant_evaluated()) {
771 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
772 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000773 char_type* __r = __s1;
774 for (; __n; --__n, ++__s1, ++__s2)
775 assign(*__s1, *__s2);
776 return __r;
777}
778
Michael Parkb5f44472019-11-08 13:42:26 +0000779inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000780char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000781char_traits<char16_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000782{
783 char_type* __r = __s;
784 for (; __n; --__n, ++__s)
785 assign(*__s, __a);
786 return __r;
787}
788
789template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000790struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000791{
792 typedef char32_t char_type;
793 typedef uint_least32_t int_type;
794 typedef streamoff off_type;
795 typedef u32streampos pos_type;
796 typedef mbstate_t state_type;
797
Marshall Clow951035b2017-01-12 04:37:14 +0000798 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
799 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000800 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
801 {return __c1 == __c2;}
802 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
803 {return __c1 < __c2;}
804
Marshall Clow951035b2017-01-12 04:37:14 +0000805 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
806 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
807 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
808 size_t length(const char_type* __s) _NOEXCEPT;
809 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
810 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000811 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000812 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000813 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000814 static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000815 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000816 static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000817
818 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
819 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
820 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
821 {return char_type(__c);}
822 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
823 {return int_type(__c);}
824 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
825 {return __c1 == __c2;}
826 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
827 {return int_type(0xFFFFFFFF);}
828};
829
Marshall Clow951035b2017-01-12 04:37:14 +0000830inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000831int
Marshall Clow36097db2016-07-28 04:52:02 +0000832char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000833{
834 for (; __n; --__n, ++__s1, ++__s2)
835 {
836 if (lt(*__s1, *__s2))
837 return -1;
838 if (lt(*__s2, *__s1))
839 return 1;
840 }
841 return 0;
842}
843
Marshall Clow951035b2017-01-12 04:37:14 +0000844inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000845size_t
Marshall Clow36097db2016-07-28 04:52:02 +0000846char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000847{
848 size_t __len = 0;
849 for (; !eq(*__s, char_type(0)); ++__s)
850 ++__len;
851 return __len;
852}
853
Marshall Clow951035b2017-01-12 04:37:14 +0000854inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000855const char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000856char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000857{
858 for (; __n; --__n)
859 {
860 if (eq(*__s, __a))
861 return __s;
862 ++__s;
863 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500864 return nullptr;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000865}
866
Michael Parkb5f44472019-11-08 13:42:26 +0000867inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000868char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000869char_traits<char32_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000870{
Michael Parkb5f44472019-11-08 13:42:26 +0000871 if (__n == 0) return __s1;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000872 char_type* __r = __s1;
873 if (__s1 < __s2)
874 {
875 for (; __n; --__n, ++__s1, ++__s2)
876 assign(*__s1, *__s2);
877 }
878 else if (__s2 < __s1)
879 {
880 __s1 += __n;
881 __s2 += __n;
882 for (; __n; --__n)
883 assign(*--__s1, *--__s2);
884 }
885 return __r;
886}
887
Michael Parkb5f44472019-11-08 13:42:26 +0000888inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000889char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000890char_traits<char32_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000891{
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400892 if (!__libcpp_is_constant_evaluated()) {
893 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
894 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000895 char_type* __r = __s1;
896 for (; __n; --__n, ++__s1, ++__s2)
897 assign(*__s1, *__s2);
898 return __r;
899}
900
Michael Parkb5f44472019-11-08 13:42:26 +0000901inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000902char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000903char_traits<char32_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000904{
905 char_type* __r = __s;
906 for (; __n; --__n, ++__s)
907 assign(*__s, __a);
908 return __r;
909}
910
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400911#endif // _LIBCPP_HAS_NO_UNICODE_CHARS
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000912
913// helper fns for basic_string and string_view
914
915// __str_find
916template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
917inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700918__str_find(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000919 _CharT __c, _SizeT __pos) _NOEXCEPT
920{
921 if (__pos >= __sz)
922 return __npos;
923 const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
Bruce Mitchener170d8972020-11-24 12:53:53 -0500924 if (__r == nullptr)
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000925 return __npos;
926 return static_cast<_SizeT>(__r - __p);
927}
928
Sebastian Pop65115202016-12-30 18:01:36 +0000929template <class _CharT, class _Traits>
930inline _LIBCPP_CONSTEXPR_AFTER_CXX11 const _CharT *
931__search_substring(const _CharT *__first1, const _CharT *__last1,
zoecarver1997e0a2021-02-05 11:54:47 -0800932 const _CharT *__first2, const _CharT *__last2) _NOEXCEPT {
Sebastian Pop65115202016-12-30 18:01:36 +0000933 // Take advantage of knowing source and pattern lengths.
934 // Stop short when source is smaller than pattern.
935 const ptrdiff_t __len2 = __last2 - __first2;
936 if (__len2 == 0)
937 return __first1;
938
939 ptrdiff_t __len1 = __last1 - __first1;
940 if (__len1 < __len2)
941 return __last1;
942
943 // First element of __first2 is loop invariant.
944 _CharT __f2 = *__first2;
945 while (true) {
946 __len1 = __last1 - __first1;
947 // Check whether __first1 still has at least __len2 bytes.
948 if (__len1 < __len2)
949 return __last1;
950
951 // Find __f2 the first byte matching in __first1.
952 __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
Bruce Mitchener170d8972020-11-24 12:53:53 -0500953 if (__first1 == nullptr)
Sebastian Pop65115202016-12-30 18:01:36 +0000954 return __last1;
955
956 // It is faster to compare from the first byte of __first1 even if we
957 // already know that it matches the first byte of __first2: this is because
958 // __first2 is most likely aligned, as it is user's "pattern" string, and
959 // __first1 + 1 is most likely not aligned, as the match is in the middle of
960 // the string.
961 if (_Traits::compare(__first1, __first2, __len2) == 0)
962 return __first1;
963
964 ++__first1;
965 }
966}
967
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000968template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
969inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700970__str_find(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000971 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
972{
Sebastian Pop65115202016-12-30 18:01:36 +0000973 if (__pos > __sz)
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000974 return __npos;
Sebastian Pop65115202016-12-30 18:01:36 +0000975
976 if (__n == 0) // There is nothing to search, just return __pos.
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000977 return __pos;
Sebastian Pop65115202016-12-30 18:01:36 +0000978
979 const _CharT *__r = __search_substring<_CharT, _Traits>(
980 __p + __pos, __p + __sz, __s, __s + __n);
981
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000982 if (__r == __p + __sz)
983 return __npos;
984 return static_cast<_SizeT>(__r - __p);
985}
986
987
988// __str_rfind
989
990template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
991inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700992__str_rfind(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000993 _CharT __c, _SizeT __pos) _NOEXCEPT
994{
995 if (__sz < 1)
996 return __npos;
997 if (__pos < __sz)
998 ++__pos;
999 else
1000 __pos = __sz;
1001 for (const _CharT* __ps = __p + __pos; __ps != __p;)
1002 {
1003 if (_Traits::eq(*--__ps, __c))
1004 return static_cast<_SizeT>(__ps - __p);
1005 }
1006 return __npos;
1007}
1008
1009template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1010inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -07001011__str_rfind(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001012 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1013{
1014 __pos = _VSTD::min(__pos, __sz);
1015 if (__n < __sz - __pos)
1016 __pos += __n;
1017 else
1018 __pos = __sz;
1019 const _CharT* __r = _VSTD::__find_end(
Louis Dionnefd77e4f2019-10-23 10:40:15 -07001020 __p, __p + __pos, __s, __s + __n, _Traits::eq,
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001021 random_access_iterator_tag(), random_access_iterator_tag());
1022 if (__n > 0 && __r == __p + __pos)
1023 return __npos;
1024 return static_cast<_SizeT>(__r - __p);
1025}
1026
1027// __str_find_first_of
1028template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1029inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1030__str_find_first_of(const _CharT *__p, _SizeT __sz,
1031 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1032{
1033 if (__pos >= __sz || __n == 0)
1034 return __npos;
1035 const _CharT* __r = _VSTD::__find_first_of_ce
1036 (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq );
1037 if (__r == __p + __sz)
1038 return __npos;
1039 return static_cast<_SizeT>(__r - __p);
1040}
1041
1042
1043// __str_find_last_of
1044template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1045inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1046__str_find_last_of(const _CharT *__p, _SizeT __sz,
1047 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1048 {
1049 if (__n != 0)
1050 {
1051 if (__pos < __sz)
1052 ++__pos;
1053 else
1054 __pos = __sz;
1055 for (const _CharT* __ps = __p + __pos; __ps != __p;)
1056 {
1057 const _CharT* __r = _Traits::find(__s, __n, *--__ps);
1058 if (__r)
1059 return static_cast<_SizeT>(__ps - __p);
1060 }
1061 }
1062 return __npos;
1063}
1064
1065
1066// __str_find_first_not_of
1067template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1068inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1069__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
1070 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1071{
1072 if (__pos < __sz)
1073 {
1074 const _CharT* __pe = __p + __sz;
1075 for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
Bruce Mitchener170d8972020-11-24 12:53:53 -05001076 if (_Traits::find(__s, __n, *__ps) == nullptr)
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001077 return static_cast<_SizeT>(__ps - __p);
1078 }
1079 return __npos;
1080}
1081
1082
1083template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1084inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1085__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
1086 _CharT __c, _SizeT __pos) _NOEXCEPT
1087{
1088 if (__pos < __sz)
1089 {
1090 const _CharT* __pe = __p + __sz;
1091 for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
1092 if (!_Traits::eq(*__ps, __c))
1093 return static_cast<_SizeT>(__ps - __p);
1094 }
1095 return __npos;
1096}
1097
1098
1099// __str_find_last_not_of
1100template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1101inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1102__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
1103 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1104{
1105 if (__pos < __sz)
1106 ++__pos;
1107 else
1108 __pos = __sz;
1109 for (const _CharT* __ps = __p + __pos; __ps != __p;)
Bruce Mitchener170d8972020-11-24 12:53:53 -05001110 if (_Traits::find(__s, __n, *--__ps) == nullptr)
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001111 return static_cast<_SizeT>(__ps - __p);
1112 return __npos;
1113}
1114
1115
1116template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1117inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1118__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
1119 _CharT __c, _SizeT __pos) _NOEXCEPT
1120{
1121 if (__pos < __sz)
1122 ++__pos;
1123 else
1124 __pos = __sz;
1125 for (const _CharT* __ps = __p + __pos; __ps != __p;)
1126 if (!_Traits::eq(*--__ps, __c))
1127 return static_cast<_SizeT>(__ps - __p);
1128 return __npos;
1129}
1130
1131template<class _Ptr>
Eric Fiselier1b57fa82016-09-15 22:27:07 +00001132inline _LIBCPP_INLINE_VISIBILITY
1133size_t __do_string_hash(_Ptr __p, _Ptr __e)
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001134{
1135 typedef typename iterator_traits<_Ptr>::value_type value_type;
1136 return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));
1137}
1138
1139template <class _CharT, class _Iter, class _Traits=char_traits<_CharT> >
1140struct __quoted_output_proxy
1141{
1142 _Iter __first;
1143 _Iter __last;
1144 _CharT __delim;
1145 _CharT __escape;
1146
1147 __quoted_output_proxy(_Iter __f, _Iter __l, _CharT __d, _CharT __e)
1148 : __first(__f), __last(__l), __delim(__d), __escape(__e) {}
Louis Dionnefd77e4f2019-10-23 10:40:15 -07001149 // This would be a nice place for a string_ref
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001150};
1151
1152_LIBCPP_END_NAMESPACE_STD
1153
Eric Fiselierf4433a32017-05-31 22:07:49 +00001154_LIBCPP_POP_MACROS
1155
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001156#endif // _LIBCPP___STRING