Skip to content

Commit 78b1c27

Browse files
committed
[WIP] Specialize std::search for char
Bug: #130432
1 parent fbf0276 commit 78b1c27

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

libcxx/include/__algorithm/search.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717
#include <__iterator/advance.h>
1818
#include <__iterator/concepts.h>
1919
#include <__iterator/iterator_traits.h>
20+
#include <__string/char_traits.h>
21+
#include <__type_traits/desugars_to.h>
2022
#include <__type_traits/enable_if.h>
2123
#include <__type_traits/invoke.h>
2224
#include <__type_traits/is_callable.h>
25+
#include <__type_traits/is_same.h>
2326
#include <__utility/pair.h>
2427

2528
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -159,6 +162,49 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __searc
159162
return std::__search_forward_impl<_ClassicAlgPolicy>(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2);
160163
}
161164

165+
template <
166+
class _Iter1,
167+
class _Sent1,
168+
class _Iter2,
169+
class _Sent2,
170+
class _Pred,
171+
class _Proj1,
172+
class _Proj2,
173+
__enable_if_t<__desugars_to_v<__equal_tag, _Pred, typename iterator_traits<_Iter1>::value_type, typename iterator_traits<_Iter1>::value_type> &&
174+
__is_identity<_Proj1>::value && __is_identity<_Proj2>::value &&
175+
__has_random_access_iterator_category<_Iter1>::value &&
176+
__has_random_access_iterator_category<_Iter2>::value &&
177+
(is_same_v<typename iterator_traits<_Iter1>::value_type, char> ||
178+
is_same_v<typename iterator_traits<_Iter1>::value_type, wchar_t> ||
179+
is_same_v<typename iterator_traits<_Iter1>::value_type, char8_t> ||
180+
is_same_v<typename iterator_traits<_Iter1>::value_type, char16_t> ||
181+
is_same_v<typename iterator_traits<_Iter1>::value_type, char32_t>),
182+
int> = 0>
183+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __search_impl(
184+
_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred& __pred, _Proj1& __proj1, _Proj2& __proj2) {
185+
using value_type = __remove_const_t<typename iterator_traits<_Iter1>::value_type>;
186+
using _CharT = value_type;
187+
using _Traits = char_traits<_CharT>;
188+
189+
auto __size2 = __last2 - __first2;
190+
if (__size2 == 0)
191+
return {__first1, __first1};
192+
193+
auto __size1 = __last1 - __first1;
194+
if (__size1 < __size2) {
195+
return {__last1, __last1};
196+
}
197+
198+
const value_type* __r = std::__search_substring<_CharT, _Traits>(__first1, __last1, __first2, __last2);
199+
if (__r == __first1)
200+
return {__first1, __first1};
201+
202+
if (__r == __last1)
203+
return {__last1, __last1};
204+
205+
return {__r, __r + __size1};
206+
}
207+
162208
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
163209
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1
164210
search(_ForwardIterator1 __first1,

libcxx/test/std/algorithms/alg.nonmodifying/alg.search/search.pass.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ void adl_test() {
104104
assert(std::search(Iter(ua), Iter(ua), Iter(ua), Iter(ua)) == Iter(ua));
105105
}
106106

107+
void test_str() {
108+
const char* s = "abcde";
109+
const char* f = "abc";
110+
const char* l = "cde";
111+
assert(std::search(s, s + 5, f, f + 3) == s);
112+
assert(std::search(s, s + 5, l, l + 3) == s + 2);
113+
assert(std::search(s, s + 5, s, s + 1) == s);
114+
assert(std::search(s, s + 5, s, s + 5) == s);
115+
assert(std::search(s, s + 5, s + 5, s + 5) == s);
116+
}
117+
107118
int main(int, char**) {
108119
test<forward_iterator<const int*>, forward_iterator<const int*> >();
109120
test<forward_iterator<const int*>, bidirectional_iterator<const int*> >();
@@ -117,6 +128,7 @@ int main(int, char**) {
117128

118129
adl_test<forward_iterator<User::S*> >();
119130
adl_test<random_access_iterator<User::S*> >();
131+
test_str();
120132

121133
#if TEST_STD_VER > 14
122134
{

0 commit comments

Comments
 (0)