blob: 1691b44ed5374ba103b170e6375ae516160f3332 [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
Christopher Di Bella55d7a822021-07-01 09:25:35 -040026#include <type_traits> // for __libcpp_is_constant_evaluated
Louis Dionne89258142021-08-23 15:32:36 -040027#include <iosfwd> // for streampos & friends
28
29#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
30# include <cwchar> // for wmemcpy
31#endif
Marshall Clowdf63a6d2016-07-21 05:31:24 +000032
Marshall Clowdf63a6d2016-07-21 05:31:24 +000033#include <__debug>
34
35#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
36#pragma GCC system_header
37#endif
38
Eric Fiselierf4433a32017-05-31 22:07:49 +000039_LIBCPP_PUSH_MACROS
40#include <__undef_macros>
41
42
Marshall Clowdf63a6d2016-07-21 05:31:24 +000043_LIBCPP_BEGIN_NAMESPACE_STD
44
Eric Fiselier5dcce5c2020-01-15 17:12:09 -050045// The the extern template ABI lists are kept outside of <string> to improve the
46// readability of that header.
Martijn Vels1e63ba02020-02-19 16:27:50 -050047
48// The extern template ABI lists are kept outside of <string> to improve the
49// readability of that header. We maintain 2 ABI lists:
50// - _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST
51// - _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST
52// As the name implies, the ABI lists define the V1 (Stable) and unstable ABI.
53//
54// For unstable, we may explicitly remove function that are external in V1,
55// and add (new) external functions to better control inlining and compiler
56// optimization opportunities.
57//
58// For stable, the ABI list should rarely change, except for adding new
59// functions supporting new c++ version / API changes. Typically entries
60// must never be removed from the stable list.
61#define _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_Func, _CharType) \
62 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \
63 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \
64 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \
65 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&)) \
66 _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 -050067 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, allocator<_CharType> const&)) \
Martijn Vels1e63ba02020-02-19 16:27:50 -050068 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \
69 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \
70 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \
71 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \
72 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \
73 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type)) \
74 _Func(_LIBCPP_FUNC_VIS const _CharType& basic_string<_CharType>::at(size_type) const) \
75 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \
76 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \
77 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \
78 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*, size_type)) \
79 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \
80 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \
81 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \
82 _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 -050083 _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 -050084 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \
85 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(size_type, value_type)) \
86 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \
87 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \
88 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \
89 _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*)) \
90 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \
91 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \
92 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \
93 _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \
94 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \
95 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::erase(size_type, size_type)) \
96 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \
97 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \
98 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \
99 _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \
100 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*)) \
101 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \
102 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \
103 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \
104 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \
105 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \
106 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \
107 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \
108 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \
109 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type))
110
111#define _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_Func, _CharType) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500112 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \
113 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \
114 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500115 _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 -0500116 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \
117 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \
118 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \
119 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \
120 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \
121 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type)) \
Martijn Vels5e7c9752020-03-04 17:52:46 -0500122 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init_copy_ctor_external(value_type const*, size_type)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500123 _Func(_LIBCPP_FUNC_VIS const _CharType& basic_string<_CharType>::at(size_type) const) \
124 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \
125 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \
126 _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 -0400127 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*, size_type)) \
128 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500129 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \
130 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \
131 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \
132 _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 -0500133 _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 -0500134 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \
135 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(size_type, value_type)) \
136 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \
137 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \
138 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \
139 _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 -0400140 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<false>(value_type const*, size_type)) \
141 _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 -0500142 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \
143 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \
144 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \
145 _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \
146 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \
Martijn Velsa81fc792020-02-26 13:25:43 -0500147 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__erase_external_with_move(size_type, size_type)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500148 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \
149 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \
150 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \
151 _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \
Eric Fiselier5dcce5c2020-01-15 17:12:09 -0500152 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \
153 _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \
154 _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 -0500155 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \
156 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \
157 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \
158 _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \
159 _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type))
160
161
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000162// char_traits
163
164template <class _CharT>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000165struct _LIBCPP_TEMPLATE_VIS char_traits
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000166{
167 typedef _CharT char_type;
168 typedef int int_type;
169 typedef streamoff off_type;
170 typedef streampos pos_type;
171 typedef mbstate_t state_type;
172
Marshall Clow951035b2017-01-12 04:37:14 +0000173 static inline void _LIBCPP_CONSTEXPR_AFTER_CXX14
174 assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000175 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
176 {return __c1 == __c2;}
177 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
178 {return __c1 < __c2;}
179
Marshall Clow951035b2017-01-12 04:37:14 +0000180 static _LIBCPP_CONSTEXPR_AFTER_CXX14
181 int compare(const char_type* __s1, const char_type* __s2, size_t __n);
182 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
183 size_t length(const char_type* __s);
184 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
185 const char_type* find(const char_type* __s, size_t __n, const char_type& __a);
Michael Parkb5f44472019-11-08 13:42:26 +0000186 static _LIBCPP_CONSTEXPR_AFTER_CXX17
187 char_type* move(char_type* __s1, const char_type* __s2, size_t __n);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000188 _LIBCPP_INLINE_VISIBILITY
Michael Parkb5f44472019-11-08 13:42:26 +0000189 static _LIBCPP_CONSTEXPR_AFTER_CXX17
190 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000191 _LIBCPP_INLINE_VISIBILITY
Michael Parkb5f44472019-11-08 13:42:26 +0000192 static _LIBCPP_CONSTEXPR_AFTER_CXX17
193 char_type* assign(char_type* __s, size_t __n, char_type __a);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000194
195 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
196 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
197 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
198 {return char_type(__c);}
199 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
200 {return int_type(__c);}
201 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
202 {return __c1 == __c2;}
203 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
204 {return int_type(EOF);}
205};
206
207template <class _CharT>
Marshall Clow951035b2017-01-12 04:37:14 +0000208_LIBCPP_CONSTEXPR_AFTER_CXX14 int
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000209char_traits<_CharT>::compare(const char_type* __s1, const char_type* __s2, size_t __n)
210{
211 for (; __n; --__n, ++__s1, ++__s2)
212 {
213 if (lt(*__s1, *__s2))
214 return -1;
215 if (lt(*__s2, *__s1))
216 return 1;
217 }
218 return 0;
219}
220
221template <class _CharT>
222inline
Marshall Clow951035b2017-01-12 04:37:14 +0000223_LIBCPP_CONSTEXPR_AFTER_CXX14 size_t
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000224char_traits<_CharT>::length(const char_type* __s)
225{
226 size_t __len = 0;
227 for (; !eq(*__s, char_type(0)); ++__s)
228 ++__len;
229 return __len;
230}
231
232template <class _CharT>
233inline
Marshall Clow951035b2017-01-12 04:37:14 +0000234_LIBCPP_CONSTEXPR_AFTER_CXX14 const _CharT*
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000235char_traits<_CharT>::find(const char_type* __s, size_t __n, const char_type& __a)
236{
237 for (; __n; --__n)
238 {
239 if (eq(*__s, __a))
240 return __s;
241 ++__s;
242 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500243 return nullptr;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000244}
245
246template <class _CharT>
Michael Parkb5f44472019-11-08 13:42:26 +0000247_LIBCPP_CONSTEXPR_AFTER_CXX17 _CharT*
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000248char_traits<_CharT>::move(char_type* __s1, const char_type* __s2, size_t __n)
249{
Michael Parkb5f44472019-11-08 13:42:26 +0000250 if (__n == 0) return __s1;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000251 char_type* __r = __s1;
252 if (__s1 < __s2)
253 {
254 for (; __n; --__n, ++__s1, ++__s2)
255 assign(*__s1, *__s2);
256 }
257 else if (__s2 < __s1)
258 {
259 __s1 += __n;
260 __s2 += __n;
261 for (; __n; --__n)
262 assign(*--__s1, *--__s2);
263 }
264 return __r;
265}
266
267template <class _CharT>
Michael Parkb5f44472019-11-08 13:42:26 +0000268inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000269_CharT*
270char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n)
271{
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400272 if (!__libcpp_is_constant_evaluated()) {
273 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
274 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000275 char_type* __r = __s1;
276 for (; __n; --__n, ++__s1, ++__s2)
277 assign(*__s1, *__s2);
278 return __r;
279}
280
281template <class _CharT>
Michael Parkb5f44472019-11-08 13:42:26 +0000282inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000283_CharT*
284char_traits<_CharT>::assign(char_type* __s, size_t __n, char_type __a)
285{
286 char_type* __r = __s;
287 for (; __n; --__n, ++__s)
288 assign(*__s, __a);
289 return __r;
290}
291
Michael Parkb5f44472019-11-08 13:42:26 +0000292// constexpr versions of move/copy/assign.
293
294template <class _CharT>
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500295static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000296_CharT* __move_constexpr(_CharT* __s1, const _CharT* __s2, size_t __n) _NOEXCEPT
297{
298 if (__n == 0) return __s1;
299 if (__s1 < __s2) {
300 _VSTD::copy(__s2, __s2 + __n, __s1);
301 } else if (__s2 < __s1) {
302 _VSTD::copy_backward(__s2, __s2 + __n, __s1 + __n);
303 }
304 return __s1;
305}
306
307template <class _CharT>
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500308static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000309_CharT* __copy_constexpr(_CharT* __s1, const _CharT* __s2, size_t __n) _NOEXCEPT
310{
311 _VSTD::copy_n(__s2, __n, __s1);
312 return __s1;
313}
314
315template <class _CharT>
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500316static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000317_CharT* __assign_constexpr(_CharT* __s, size_t __n, _CharT __a) _NOEXCEPT
318{
319 _VSTD::fill_n(__s, __n, __a);
320 return __s;
321}
322
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000323// char_traits<char>
324
325template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000326struct _LIBCPP_TEMPLATE_VIS char_traits<char>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000327{
328 typedef char char_type;
329 typedef int int_type;
330 typedef streamoff off_type;
331 typedef streampos pos_type;
332 typedef mbstate_t state_type;
333
Marshall Clow951035b2017-01-12 04:37:14 +0000334 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
335 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000336 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
337 {return __c1 == __c2;}
338 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
339 {return (unsigned char)__c1 < (unsigned char)__c2;}
340
Marshall Clowaa32f162017-01-12 05:40:58 +0000341 static _LIBCPP_CONSTEXPR_AFTER_CXX14
342 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Marshall Clow951035b2017-01-12 04:37:14 +0000343 static inline size_t _LIBCPP_CONSTEXPR_AFTER_CXX14
344 length(const char_type* __s) _NOEXCEPT {return __builtin_strlen(__s);}
345 static _LIBCPP_CONSTEXPR_AFTER_CXX14
346 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500347 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000348 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
349 {
350 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500351 ? _VSTD::__move_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500352 : __n == 0 ? __s1 : (char_type*)_VSTD::memmove(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000353 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500354 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000355 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000356 {
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400357 if (!__libcpp_is_constant_evaluated()) {
358 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
359 }
Michael Parkb5f44472019-11-08 13:42:26 +0000360 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500361 ? _VSTD::__copy_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500362 : __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000363 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500364 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000365 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
366 {
367 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500368 ? _VSTD::__assign_constexpr(__s, __n, __a)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500369 : __n == 0 ? __s : (char_type*)_VSTD::memset(__s, to_int_type(__a), __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000370 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000371
372 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
373 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
374 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
375 {return char_type(__c);}
376 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
377 {return int_type((unsigned char)__c);}
378 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
379 {return __c1 == __c2;}
380 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
381 {return int_type(EOF);}
382};
383
Marshall Clow951035b2017-01-12 04:37:14 +0000384inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowaa32f162017-01-12 05:40:58 +0000385int
386char_traits<char>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
387{
388 if (__n == 0)
389 return 0;
Marshall Clowb344c362017-01-26 06:58:29 +0000390#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clowaa32f162017-01-12 05:40:58 +0000391 return __builtin_memcmp(__s1, __s2, __n);
392#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500393 return _VSTD::memcmp(__s1, __s2, __n);
Marshall Clowaa32f162017-01-12 05:40:58 +0000394#else
395 for (; __n; --__n, ++__s1, ++__s2)
396 {
397 if (lt(*__s1, *__s2))
398 return -1;
399 if (lt(*__s2, *__s1))
400 return 1;
401 }
402 return 0;
403#endif
404}
405
406inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clow951035b2017-01-12 04:37:14 +0000407const char*
408char_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
409{
410 if (__n == 0)
Marshall Clow32043ac2018-02-06 18:58:05 +0000411 return nullptr;
Marshall Clowb344c362017-01-26 06:58:29 +0000412#if __has_feature(cxx_constexpr_string_builtins)
413 return __builtin_char_memchr(__s, to_int_type(__a), __n);
414#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500415 return (const char_type*) _VSTD::memchr(__s, to_int_type(__a), __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000416#else
417 for (; __n; --__n)
418 {
419 if (eq(*__s, __a))
420 return __s;
421 ++__s;
422 }
Marshall Clow32043ac2018-02-06 18:58:05 +0000423 return nullptr;
Marshall Clow951035b2017-01-12 04:37:14 +0000424#endif
425}
426
427
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000428// char_traits<wchar_t>
429
Louis Dionne89258142021-08-23 15:32:36 -0400430#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000431template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000432struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000433{
434 typedef wchar_t char_type;
435 typedef wint_t int_type;
436 typedef streamoff off_type;
437 typedef streampos pos_type;
438 typedef mbstate_t state_type;
439
Marshall Clow951035b2017-01-12 04:37:14 +0000440 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
441 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000442 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
443 {return __c1 == __c2;}
444 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
445 {return __c1 < __c2;}
446
Marshall Clow951035b2017-01-12 04:37:14 +0000447 static _LIBCPP_CONSTEXPR_AFTER_CXX14
448 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
449 static _LIBCPP_CONSTEXPR_AFTER_CXX14
450 size_t length(const char_type* __s) _NOEXCEPT;
451 static _LIBCPP_CONSTEXPR_AFTER_CXX14
452 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500453 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000454 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
455 {
456 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500457 ? _VSTD::__move_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500458 : __n == 0 ? __s1 : _VSTD::wmemmove(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000459 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500460 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000461 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000462 {
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400463 if (!__libcpp_is_constant_evaluated()) {
464 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
465 }
Michael Parkb5f44472019-11-08 13:42:26 +0000466 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500467 ? _VSTD::__copy_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500468 : __n == 0 ? __s1 : _VSTD::wmemcpy(__s1, __s2, __n);
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000469 }
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500470 static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000471 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
472 {
473 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500474 ? _VSTD::__assign_constexpr(__s, __n, __a)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500475 : __n == 0 ? __s : _VSTD::wmemset(__s, __a, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000476 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000477 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
478 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
479 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
480 {return char_type(__c);}
481 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
482 {return int_type(__c);}
483 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
484 {return __c1 == __c2;}
485 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
486 {return int_type(WEOF);}
487};
488
Marshall Clow951035b2017-01-12 04:37:14 +0000489inline _LIBCPP_CONSTEXPR_AFTER_CXX14
490int
491char_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
492{
493 if (__n == 0)
494 return 0;
Marshall Clowb344c362017-01-26 06:58:29 +0000495#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clow951035b2017-01-12 04:37:14 +0000496 return __builtin_wmemcmp(__s1, __s2, __n);
497#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500498 return _VSTD::wmemcmp(__s1, __s2, __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000499#else
500 for (; __n; --__n, ++__s1, ++__s2)
501 {
502 if (lt(*__s1, *__s2))
503 return -1;
504 if (lt(*__s2, *__s1))
505 return 1;
506 }
507 return 0;
508#endif
509}
510
511inline _LIBCPP_CONSTEXPR_AFTER_CXX14
512size_t
513char_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT
514{
Marshall Clowb344c362017-01-26 06:58:29 +0000515#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clow951035b2017-01-12 04:37:14 +0000516 return __builtin_wcslen(__s);
517#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500518 return _VSTD::wcslen(__s);
Marshall Clow951035b2017-01-12 04:37:14 +0000519#else
520 size_t __len = 0;
521 for (; !eq(*__s, char_type(0)); ++__s)
522 ++__len;
523 return __len;
524#endif
525}
526
527inline _LIBCPP_CONSTEXPR_AFTER_CXX14
528const wchar_t*
529char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
530{
531 if (__n == 0)
Marshall Clow32043ac2018-02-06 18:58:05 +0000532 return nullptr;
Marshall Clowb344c362017-01-26 06:58:29 +0000533#if __has_feature(cxx_constexpr_string_builtins)
Marshall Clow32043ac2018-02-06 18:58:05 +0000534 return __builtin_wmemchr(__s, __a, __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000535#elif _LIBCPP_STD_VER <= 14
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500536 return _VSTD::wmemchr(__s, __a, __n);
Marshall Clow951035b2017-01-12 04:37:14 +0000537#else
538 for (; __n; --__n)
539 {
540 if (eq(*__s, __a))
541 return __s;
542 ++__s;
543 }
Marshall Clow32043ac2018-02-06 18:58:05 +0000544 return nullptr;
Marshall Clow951035b2017-01-12 04:37:14 +0000545#endif
546}
Louis Dionne89258142021-08-23 15:32:36 -0400547#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
Marshall Clow951035b2017-01-12 04:37:14 +0000548
Louis Dionne76f4e0b2021-09-09 13:23:26 -0400549template <class _Traits>
550_LIBCPP_INLINE_VISIBILITY
551_LIBCPP_CONSTEXPR
552inline size_t __char_traits_length_checked(const typename _Traits::char_type* __s) _NOEXCEPT {
553#if _LIBCPP_DEBUG_LEVEL >= 1
554 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);
555#else
556 return _Traits::length(__s);
557#endif
558}
Marshall Clow951035b2017-01-12 04:37:14 +0000559
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400560#ifndef _LIBCPP_HAS_NO_CHAR8_T
Marshall Clow8732fed2018-12-11 04:35:44 +0000561
562template <>
563struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
564{
565 typedef char8_t char_type;
566 typedef unsigned int int_type;
567 typedef streamoff off_type;
568 typedef u8streampos pos_type;
569 typedef mbstate_t state_type;
570
571 static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
572 {__c1 = __c2;}
573 static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept
574 {return __c1 == __c2;}
575 static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept
576 {return __c1 < __c2;}
577
578 static constexpr
579 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
580
581 static constexpr
582 size_t length(const char_type* __s) _NOEXCEPT;
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700583
Marshall Clow8732fed2018-12-11 04:35:44 +0000584 _LIBCPP_INLINE_VISIBILITY static constexpr
585 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700586
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500587 static _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000588 char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
589 {
590 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500591 ? _VSTD::__move_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500592 : __n == 0 ? __s1 : (char_type*)_VSTD::memmove(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000593 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700594
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500595 static _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000596 char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400597 {
598 if (!__libcpp_is_constant_evaluated()) {
599 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
600 }
Michael Parkb5f44472019-11-08 13:42:26 +0000601 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500602 ? _VSTD::__copy_constexpr(__s1, __s2, __n)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500603 : __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000604 }
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700605
Arthur O'Dwyer14606d12020-11-23 12:44:41 -0500606 static _LIBCPP_CONSTEXPR_AFTER_CXX17
Michael Parkb5f44472019-11-08 13:42:26 +0000607 char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
608 {
609 return __libcpp_is_constant_evaluated()
Arthur O'Dwyere75dcfa2020-11-22 13:21:11 -0500610 ? _VSTD::__assign_constexpr(__s, __n, __a)
Arthur O'Dwyer22236632020-12-07 21:50:15 -0500611 : __n == 0 ? __s : (char_type*)_VSTD::memset(__s, to_int_type(__a), __n);
Michael Parkb5f44472019-11-08 13:42:26 +0000612 }
Marshall Clow8732fed2018-12-11 04:35:44 +0000613
614 static inline constexpr int_type not_eof(int_type __c) noexcept
615 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
616 static inline constexpr char_type to_char_type(int_type __c) noexcept
617 {return char_type(__c);}
618 static inline constexpr int_type to_int_type(char_type __c) noexcept
619 {return int_type(__c);}
620 static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept
621 {return __c1 == __c2;}
622 static inline constexpr int_type eof() noexcept
623 {return int_type(EOF);}
624};
625
626// TODO use '__builtin_strlen' if it ever supports char8_t ??
627inline constexpr
628size_t
629char_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
630{
631 size_t __len = 0;
632 for (; !eq(*__s, char_type(0)); ++__s)
633 ++__len;
634 return __len;
635}
636
637inline constexpr
638int
639char_traits<char8_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
640{
641#if __has_feature(cxx_constexpr_string_builtins)
642 return __builtin_memcmp(__s1, __s2, __n);
643#else
644 for (; __n; --__n, ++__s1, ++__s2)
645 {
646 if (lt(*__s1, *__s2))
647 return -1;
648 if (lt(*__s2, *__s1))
649 return 1;
650 }
651 return 0;
652#endif
653}
654
655// TODO use '__builtin_char_memchr' if it ever supports char8_t ??
656inline constexpr
657const char8_t*
658char_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
659{
660 for (; __n; --__n)
661 {
662 if (eq(*__s, __a))
663 return __s;
664 ++__s;
665 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500666 return nullptr;
Marshall Clow8732fed2018-12-11 04:35:44 +0000667}
668
Arthur O'Dwyerafa5d5f2021-04-18 21:47:08 -0400669#endif // #_LIBCPP_HAS_NO_CHAR8_T
Marshall Clow8732fed2018-12-11 04:35:44 +0000670
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000671#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
672
673template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000674struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000675{
676 typedef char16_t char_type;
677 typedef uint_least16_t int_type;
678 typedef streamoff off_type;
679 typedef u16streampos pos_type;
680 typedef mbstate_t state_type;
681
Marshall Clow951035b2017-01-12 04:37:14 +0000682 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
683 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000684 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
685 {return __c1 == __c2;}
686 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
687 {return __c1 < __c2;}
688
Marshall Clow951035b2017-01-12 04:37:14 +0000689 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
690 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
691 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
692 size_t length(const char_type* __s) _NOEXCEPT;
693 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
694 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000695 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000696 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000697 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000698 static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000699 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000700 static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000701
702 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
703 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
704 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
705 {return char_type(__c);}
706 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
707 {return int_type(__c);}
708 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
709 {return __c1 == __c2;}
710 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
711 {return int_type(0xFFFF);}
712};
713
Marshall Clow951035b2017-01-12 04:37:14 +0000714inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000715int
Marshall Clow36097db2016-07-28 04:52:02 +0000716char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000717{
718 for (; __n; --__n, ++__s1, ++__s2)
719 {
720 if (lt(*__s1, *__s2))
721 return -1;
722 if (lt(*__s2, *__s1))
723 return 1;
724 }
725 return 0;
726}
727
Marshall Clow951035b2017-01-12 04:37:14 +0000728inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000729size_t
Marshall Clow36097db2016-07-28 04:52:02 +0000730char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000731{
732 size_t __len = 0;
733 for (; !eq(*__s, char_type(0)); ++__s)
734 ++__len;
735 return __len;
736}
737
Marshall Clow951035b2017-01-12 04:37:14 +0000738inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000739const char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000740char_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000741{
742 for (; __n; --__n)
743 {
744 if (eq(*__s, __a))
745 return __s;
746 ++__s;
747 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500748 return nullptr;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000749}
750
Michael Parkb5f44472019-11-08 13:42:26 +0000751inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000752char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000753char_traits<char16_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000754{
Michael Parkb5f44472019-11-08 13:42:26 +0000755 if (__n == 0) return __s1;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000756 char_type* __r = __s1;
757 if (__s1 < __s2)
758 {
759 for (; __n; --__n, ++__s1, ++__s2)
760 assign(*__s1, *__s2);
761 }
762 else if (__s2 < __s1)
763 {
764 __s1 += __n;
765 __s2 += __n;
766 for (; __n; --__n)
767 assign(*--__s1, *--__s2);
768 }
769 return __r;
770}
771
Michael Parkb5f44472019-11-08 13:42:26 +0000772inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000773char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000774char_traits<char16_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000775{
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400776 if (!__libcpp_is_constant_evaluated()) {
777 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
778 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000779 char_type* __r = __s1;
780 for (; __n; --__n, ++__s1, ++__s2)
781 assign(*__s1, *__s2);
782 return __r;
783}
784
Michael Parkb5f44472019-11-08 13:42:26 +0000785inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000786char16_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000787char_traits<char16_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000788{
789 char_type* __r = __s;
790 for (; __n; --__n, ++__s)
791 assign(*__s, __a);
792 return __r;
793}
794
795template <>
Eric Fiselierb5eb1bf2017-01-04 23:56:00 +0000796struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000797{
798 typedef char32_t char_type;
799 typedef uint_least32_t int_type;
800 typedef streamoff off_type;
801 typedef u32streampos pos_type;
802 typedef mbstate_t state_type;
803
Marshall Clow951035b2017-01-12 04:37:14 +0000804 static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
805 void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000806 static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
807 {return __c1 == __c2;}
808 static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
809 {return __c1 < __c2;}
810
Marshall Clow951035b2017-01-12 04:37:14 +0000811 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
812 int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
813 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
814 size_t length(const char_type* __s) _NOEXCEPT;
815 _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
816 const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000817 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000818 static char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000819 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000820 static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
Michael Parkb5f44472019-11-08 13:42:26 +0000821 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clow36097db2016-07-28 04:52:02 +0000822 static char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000823
824 static inline _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT
825 {return eq_int_type(__c, eof()) ? ~eof() : __c;}
826 static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
827 {return char_type(__c);}
828 static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
829 {return int_type(__c);}
830 static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
831 {return __c1 == __c2;}
832 static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
833 {return int_type(0xFFFFFFFF);}
834};
835
Marshall Clow951035b2017-01-12 04:37:14 +0000836inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000837int
Marshall Clow36097db2016-07-28 04:52:02 +0000838char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000839{
840 for (; __n; --__n, ++__s1, ++__s2)
841 {
842 if (lt(*__s1, *__s2))
843 return -1;
844 if (lt(*__s2, *__s1))
845 return 1;
846 }
847 return 0;
848}
849
Marshall Clow951035b2017-01-12 04:37:14 +0000850inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000851size_t
Marshall Clow36097db2016-07-28 04:52:02 +0000852char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000853{
854 size_t __len = 0;
855 for (; !eq(*__s, char_type(0)); ++__s)
856 ++__len;
857 return __len;
858}
859
Marshall Clow951035b2017-01-12 04:37:14 +0000860inline _LIBCPP_CONSTEXPR_AFTER_CXX14
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000861const char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000862char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000863{
864 for (; __n; --__n)
865 {
866 if (eq(*__s, __a))
867 return __s;
868 ++__s;
869 }
Bruce Mitchener170d8972020-11-24 12:53:53 -0500870 return nullptr;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000871}
872
Michael Parkb5f44472019-11-08 13:42:26 +0000873inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000874char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000875char_traits<char32_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000876{
Michael Parkb5f44472019-11-08 13:42:26 +0000877 if (__n == 0) return __s1;
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000878 char_type* __r = __s1;
879 if (__s1 < __s2)
880 {
881 for (; __n; --__n, ++__s1, ++__s2)
882 assign(*__s1, *__s2);
883 }
884 else if (__s2 < __s1)
885 {
886 __s1 += __n;
887 __s2 += __n;
888 for (; __n; --__n)
889 assign(*--__s1, *--__s2);
890 }
891 return __r;
892}
893
Michael Parkb5f44472019-11-08 13:42:26 +0000894inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000895char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000896char_traits<char32_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000897{
Arthur O'Dwyere9a55122021-04-20 22:24:24 -0400898 if (!__libcpp_is_constant_evaluated()) {
899 _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
900 }
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000901 char_type* __r = __s1;
902 for (; __n; --__n, ++__s1, ++__s2)
903 assign(*__s1, *__s2);
904 return __r;
905}
906
Michael Parkb5f44472019-11-08 13:42:26 +0000907inline _LIBCPP_CONSTEXPR_AFTER_CXX17
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000908char32_t*
Marshall Clow36097db2016-07-28 04:52:02 +0000909char_traits<char32_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000910{
911 char_type* __r = __s;
912 for (; __n; --__n, ++__s)
913 assign(*__s, __a);
914 return __r;
915}
916
Louis Dionne2b1ceaa2021-04-20 12:03:32 -0400917#endif // _LIBCPP_HAS_NO_UNICODE_CHARS
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000918
919// helper fns for basic_string and string_view
920
921// __str_find
922template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
923inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700924__str_find(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000925 _CharT __c, _SizeT __pos) _NOEXCEPT
926{
927 if (__pos >= __sz)
928 return __npos;
929 const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
Bruce Mitchener170d8972020-11-24 12:53:53 -0500930 if (__r == nullptr)
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000931 return __npos;
932 return static_cast<_SizeT>(__r - __p);
933}
934
Sebastian Pop65115202016-12-30 18:01:36 +0000935template <class _CharT, class _Traits>
936inline _LIBCPP_CONSTEXPR_AFTER_CXX11 const _CharT *
937__search_substring(const _CharT *__first1, const _CharT *__last1,
zoecarver1997e0a2021-02-05 11:54:47 -0800938 const _CharT *__first2, const _CharT *__last2) _NOEXCEPT {
Sebastian Pop65115202016-12-30 18:01:36 +0000939 // Take advantage of knowing source and pattern lengths.
940 // Stop short when source is smaller than pattern.
941 const ptrdiff_t __len2 = __last2 - __first2;
942 if (__len2 == 0)
943 return __first1;
944
945 ptrdiff_t __len1 = __last1 - __first1;
946 if (__len1 < __len2)
947 return __last1;
948
949 // First element of __first2 is loop invariant.
950 _CharT __f2 = *__first2;
951 while (true) {
952 __len1 = __last1 - __first1;
953 // Check whether __first1 still has at least __len2 bytes.
954 if (__len1 < __len2)
955 return __last1;
956
957 // Find __f2 the first byte matching in __first1.
958 __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
Bruce Mitchener170d8972020-11-24 12:53:53 -0500959 if (__first1 == nullptr)
Sebastian Pop65115202016-12-30 18:01:36 +0000960 return __last1;
961
962 // It is faster to compare from the first byte of __first1 even if we
963 // already know that it matches the first byte of __first2: this is because
964 // __first2 is most likely aligned, as it is user's "pattern" string, and
965 // __first1 + 1 is most likely not aligned, as the match is in the middle of
966 // the string.
967 if (_Traits::compare(__first1, __first2, __len2) == 0)
968 return __first1;
969
970 ++__first1;
971 }
972}
973
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000974template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
975inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700976__str_find(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000977 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
978{
Sebastian Pop65115202016-12-30 18:01:36 +0000979 if (__pos > __sz)
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000980 return __npos;
Sebastian Pop65115202016-12-30 18:01:36 +0000981
982 if (__n == 0) // There is nothing to search, just return __pos.
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000983 return __pos;
Sebastian Pop65115202016-12-30 18:01:36 +0000984
985 const _CharT *__r = __search_substring<_CharT, _Traits>(
986 __p + __pos, __p + __sz, __s, __s + __n);
987
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000988 if (__r == __p + __sz)
989 return __npos;
990 return static_cast<_SizeT>(__r - __p);
991}
992
993
994// __str_rfind
995
996template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
997inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -0700998__str_rfind(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +0000999 _CharT __c, _SizeT __pos) _NOEXCEPT
1000{
1001 if (__sz < 1)
1002 return __npos;
1003 if (__pos < __sz)
1004 ++__pos;
1005 else
1006 __pos = __sz;
1007 for (const _CharT* __ps = __p + __pos; __ps != __p;)
1008 {
1009 if (_Traits::eq(*--__ps, __c))
1010 return static_cast<_SizeT>(__ps - __p);
1011 }
1012 return __npos;
1013}
1014
1015template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1016inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
Louis Dionnefd77e4f2019-10-23 10:40:15 -07001017__str_rfind(const _CharT *__p, _SizeT __sz,
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001018 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1019{
1020 __pos = _VSTD::min(__pos, __sz);
1021 if (__n < __sz - __pos)
1022 __pos += __n;
1023 else
1024 __pos = __sz;
1025 const _CharT* __r = _VSTD::__find_end(
Louis Dionnefd77e4f2019-10-23 10:40:15 -07001026 __p, __p + __pos, __s, __s + __n, _Traits::eq,
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001027 random_access_iterator_tag(), random_access_iterator_tag());
1028 if (__n > 0 && __r == __p + __pos)
1029 return __npos;
1030 return static_cast<_SizeT>(__r - __p);
1031}
1032
1033// __str_find_first_of
1034template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1035inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1036__str_find_first_of(const _CharT *__p, _SizeT __sz,
1037 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1038{
1039 if (__pos >= __sz || __n == 0)
1040 return __npos;
1041 const _CharT* __r = _VSTD::__find_first_of_ce
1042 (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq );
1043 if (__r == __p + __sz)
1044 return __npos;
1045 return static_cast<_SizeT>(__r - __p);
1046}
1047
1048
1049// __str_find_last_of
1050template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1051inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1052__str_find_last_of(const _CharT *__p, _SizeT __sz,
1053 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1054 {
1055 if (__n != 0)
1056 {
1057 if (__pos < __sz)
1058 ++__pos;
1059 else
1060 __pos = __sz;
1061 for (const _CharT* __ps = __p + __pos; __ps != __p;)
1062 {
1063 const _CharT* __r = _Traits::find(__s, __n, *--__ps);
1064 if (__r)
1065 return static_cast<_SizeT>(__ps - __p);
1066 }
1067 }
1068 return __npos;
1069}
1070
1071
1072// __str_find_first_not_of
1073template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1074inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1075__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
1076 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1077{
1078 if (__pos < __sz)
1079 {
1080 const _CharT* __pe = __p + __sz;
1081 for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
Bruce Mitchener170d8972020-11-24 12:53:53 -05001082 if (_Traits::find(__s, __n, *__ps) == nullptr)
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001083 return static_cast<_SizeT>(__ps - __p);
1084 }
1085 return __npos;
1086}
1087
1088
1089template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1090inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1091__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
1092 _CharT __c, _SizeT __pos) _NOEXCEPT
1093{
1094 if (__pos < __sz)
1095 {
1096 const _CharT* __pe = __p + __sz;
1097 for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
1098 if (!_Traits::eq(*__ps, __c))
1099 return static_cast<_SizeT>(__ps - __p);
1100 }
1101 return __npos;
1102}
1103
1104
1105// __str_find_last_not_of
1106template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1107inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1108__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
1109 const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1110{
1111 if (__pos < __sz)
1112 ++__pos;
1113 else
1114 __pos = __sz;
1115 for (const _CharT* __ps = __p + __pos; __ps != __p;)
Bruce Mitchener170d8972020-11-24 12:53:53 -05001116 if (_Traits::find(__s, __n, *--__ps) == nullptr)
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001117 return static_cast<_SizeT>(__ps - __p);
1118 return __npos;
1119}
1120
1121
1122template<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1123inline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1124__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
1125 _CharT __c, _SizeT __pos) _NOEXCEPT
1126{
1127 if (__pos < __sz)
1128 ++__pos;
1129 else
1130 __pos = __sz;
1131 for (const _CharT* __ps = __p + __pos; __ps != __p;)
1132 if (!_Traits::eq(*--__ps, __c))
1133 return static_cast<_SizeT>(__ps - __p);
1134 return __npos;
1135}
1136
1137template<class _Ptr>
Eric Fiselier1b57fa82016-09-15 22:27:07 +00001138inline _LIBCPP_INLINE_VISIBILITY
1139size_t __do_string_hash(_Ptr __p, _Ptr __e)
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001140{
1141 typedef typename iterator_traits<_Ptr>::value_type value_type;
1142 return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));
1143}
1144
1145template <class _CharT, class _Iter, class _Traits=char_traits<_CharT> >
1146struct __quoted_output_proxy
1147{
1148 _Iter __first;
1149 _Iter __last;
1150 _CharT __delim;
1151 _CharT __escape;
1152
1153 __quoted_output_proxy(_Iter __f, _Iter __l, _CharT __d, _CharT __e)
1154 : __first(__f), __last(__l), __delim(__d), __escape(__e) {}
Louis Dionnefd77e4f2019-10-23 10:40:15 -07001155 // This would be a nice place for a string_ref
Marshall Clowdf63a6d2016-07-21 05:31:24 +00001156};
1157
1158_LIBCPP_END_NAMESPACE_STD
1159
Eric Fiselierf4433a32017-05-31 22:07:49 +00001160_LIBCPP_POP_MACROS
1161
Louis Dionne2b1ceaa2021-04-20 12:03:32 -04001162#endif // _LIBCPP___STRING