Skip to content

Commit 19f796d

Browse files
committed
[WIP] Specialize std::search for char
Bug: #130432
1 parent 8f05f25 commit 19f796d

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

libcxx/include/__algorithm/search.h

Lines changed: 34 additions & 1 deletion
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,29 @@ _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 <class _ForwardIterator1, class _ForwardIterator2, class _CharT, class _Traits>
165+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 search_str(
166+
_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
167+
auto __size2 = __last2 - __first2;
168+
if (__size2 == 0)
169+
return __first1;
170+
171+
auto __size1 = __last1 - __first1;
172+
if (__size1 < __size2) {
173+
return __last1;
174+
}
175+
using value_type = remove_const_t<typename iterator_traits<_ForwardIterator1>::value_type>;
176+
177+
const value_type* __r = std::__search_substring<_CharT, _Traits>(__first1, __last1, __first2, __last2);
178+
if (__r == __first1)
179+
return __first1;
180+
181+
if (__r == __last1)
182+
return __last1;
183+
184+
return __r;
185+
}
186+
162187
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
163188
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1
164189
search(_ForwardIterator1 __first1,
@@ -175,7 +200,15 @@ search(_ForwardIterator1 __first1,
175200
template <class _ForwardIterator1, class _ForwardIterator2>
176201
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1
177202
search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
178-
return std::search(__first1, __last1, __first2, __last2, __equal_to());
203+
using value_type = __remove_const_t<typename iterator_traits<_ForwardIterator1>::value_type>;
204+
if constexpr (is_same<value_type, char>::value || is_same<value_type, wchar_t>::value ||
205+
is_same<value_type, char8_t>::value || is_same<value_type, char16_t>::value ||
206+
is_same<value_type, char32_t>::value) {
207+
using _CharT = value_type;
208+
using _Traits = char_traits<_CharT>;
209+
return std::search_str<_ForwardIterator1, _ForwardIterator2, _CharT, _Traits>(__first1, __last1, __first2, __last2);
210+
} else
211+
return std::search(__first1, __last1, __first2, __last2, __equal_to());
179212
}
180213

181214
#if _LIBCPP_STD_VER >= 17

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

Lines changed: 11 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*> >();

0 commit comments

Comments
 (0)