Skip to content

Commit bee78ce

Browse files
committed
[WIP] Specialize std::search for char
Bug: #130432
1 parent 58fc4b1 commit bee78ce

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

libcxx/include/__algorithm/search.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
#include <__iterator/advance.h>
1818
#include <__iterator/concepts.h>
1919
#include <__iterator/iterator_traits.h>
20+
#include <__string/char_traits.h>
2021
#include <__type_traits/enable_if.h>
2122
#include <__type_traits/invoke.h>
2223
#include <__type_traits/is_callable.h>
24+
#include <__type_traits/is_same.h>
2325
#include <__utility/pair.h>
2426

2527
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -159,6 +161,38 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1> __searc
159161
return std::__search_forward_impl<_ClassicAlgPolicy>(__first1, __last1, __first2, __last2, __pred, __proj1, __proj2);
160162
}
161163

164+
template <
165+
class _Iter1,
166+
class _Sent1,
167+
class _Iter2,
168+
class _Sent2,
169+
__enable_if_t<
170+
__has_random_access_iterator_category<_Iter1>::value && __has_random_access_iterator_category<_Iter2>::value &&
171+
is_same<typename iterator_traits<_Iter1>::value_type, char>::value &&
172+
is_same<typename iterator_traits<_Iter2>::value_type, typename iterator_traits<_Iter2>::value_type>::value,
173+
int> = 0>
174+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_Iter1, _Iter1>
175+
search(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2) {
176+
auto __size2 = __last2 - __first2;
177+
if (__size2 == 0)
178+
return __first1;
179+
180+
auto __size1 = __last1 - __first1;
181+
if (__size1 < __size2) {
182+
return __last1;
183+
}
184+
using value_type = typename iterator_traits<_Iter1>::value_type;
185+
186+
const value_type* __r = std::__search_substring(__first1, __last1, __first2, __last2);
187+
if (__r == __first1)
188+
return __first1;
189+
190+
if (__r == __last1)
191+
return __last1;
192+
193+
return __first1 + __r;
194+
}
195+
162196
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
163197
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1
164198
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
@@ -116,6 +116,17 @@ adl_test()
116116
assert(std::search(Iter(ua), Iter(ua), Iter(ua), Iter(ua)) == Iter(ua));
117117
}
118118

119+
void test_str() {
120+
const char* s = "abcde";
121+
const char* f = "abc";
122+
const char* l = "cde";
123+
assert(std::search(s, s + 5, f, f + 3) == s);
124+
assert(std::search(s, s + 5, l, l + 3) == s + 2);
125+
assert(std::search(s, s + 5, s, s + 1) == s);
126+
assert(std::search(s, s + 5, s, s + 5) == s);
127+
assert(std::search(s, s + 5, s + 5, s + 5) == s);
128+
}
129+
119130
int main(int, char**)
120131
{
121132
test<forward_iterator<const int*>, forward_iterator<const int*> >();
@@ -130,6 +141,7 @@ int main(int, char**)
130141

131142
adl_test<forward_iterator<User::S*> >();
132143
adl_test<random_access_iterator<User::S*> >();
144+
test_str();
133145

134146
#if TEST_STD_VER > 14
135147
{

0 commit comments

Comments
 (0)