C/C++ API Reference
Loading...
Searching...
No Matches
algorithm.h
Go to the documentation of this file.
1// Copyright 2022 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14//
15// This was forked from
16// https://cs.opensource.google/abseil/abseil-cpp/+/main:absl/algorithm/algorithm.h;drc=12bc53e0318d80569270a5b26ccbc62b52022b89
17#pragma once
18
19#include <algorithm>
20#include <utility>
21
22#include "pw_containers/internal/algorithm_internal.h"
23
45
46namespace pw {
48
51namespace containers {
52
55template <typename C, typename Pred>
56bool AllOf(const C& c, Pred&& pred) {
57 return std::all_of(std::begin(c), std::end(c), std::forward<Pred>(pred));
58}
59
62template <typename C, typename Pred>
63bool AnyOf(const C& c, Pred&& pred) {
64 return std::any_of(std::begin(c), std::end(c), std::forward<Pred>(pred));
65}
66
69template <typename C, typename Pred>
70bool NoneOf(const C& c, Pred&& pred) {
71 return std::none_of(std::begin(c), std::end(c), std::forward<Pred>(pred));
72}
73
76template <typename C, typename Function>
77std::decay_t<Function> ForEach(C&& c, Function&& f) {
78 return std::for_each(std::begin(c), std::end(c), std::forward<Function>(f));
79}
80
83template <typename C, typename T>
84internal_algorithm::ContainerIter<C> Find(C& c, T&& value) {
85 return std::find(std::begin(c), std::end(c), std::forward<T>(value));
86}
87
88// Container-based version of the <algorithm> `std::ranges::contains()` C++23
89// function to search a container for a value.
90template <typename C, typename T>
91bool Contains(const C& c, T&& value) {
92 return Find(c, std::forward<T>(value)) != std::end(c);
93}
94
97template <typename C, typename Pred>
98internal_algorithm::ContainerIter<C> FindIf(C& c, Pred&& pred) {
99 return std::find_if(std::begin(c), std::end(c), std::forward<Pred>(pred));
100}
101
104template <typename C, typename Pred>
105internal_algorithm::ContainerIter<C> FindIfNot(C& c, Pred&& pred) {
106 return std::find_if_not(std::begin(c), std::end(c), std::forward<Pred>(pred));
107}
108
111template <typename Sequence1, typename Sequence2>
112internal_algorithm::ContainerIter<Sequence1> FindEnd(Sequence1& sequence,
113 Sequence2& subsequence) {
114 return std::find_end(std::begin(sequence),
115 std::end(sequence),
116 std::begin(subsequence),
117 std::end(subsequence));
118}
119
122template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
123internal_algorithm::ContainerIter<Sequence1> FindEnd(Sequence1& sequence,
124 Sequence2& subsequence,
125 BinaryPredicate&& pred) {
126 return std::find_end(std::begin(sequence),
127 std::end(sequence),
128 std::begin(subsequence),
129 std::end(subsequence),
130 std::forward<BinaryPredicate>(pred));
131}
132
136template <typename C1, typename C2>
137internal_algorithm::ContainerIter<C1> FindFirstOf(C1& container, C2& options) {
138 return std::find_first_of(std::begin(container),
139 std::end(container),
140 std::begin(options),
141 std::end(options));
142}
143
146template <typename C1, typename C2, typename BinaryPredicate>
147internal_algorithm::ContainerIter<C1> FindFirstOf(C1& container,
148 C2& options,
149 BinaryPredicate&& pred) {
150 return std::find_first_of(std::begin(container),
151 std::end(container),
152 std::begin(options),
153 std::end(options),
154 std::forward<BinaryPredicate>(pred));
155}
156
159template <typename Sequence>
160internal_algorithm::ContainerIter<Sequence> AdjacentFind(Sequence& sequence) {
161 return std::adjacent_find(std::begin(sequence), std::end(sequence));
162}
163
166template <typename Sequence, typename BinaryPredicate>
167internal_algorithm::ContainerIter<Sequence> AdjacentFind(
168 Sequence& sequence, BinaryPredicate&& pred) {
169 return std::adjacent_find(std::begin(sequence),
170 std::end(sequence),
171 std::forward<BinaryPredicate>(pred));
172}
173
176template <typename C, typename T>
177internal_algorithm::ContainerDifferenceType<const C> Count(const C& c,
178 T&& value) {
179 return std::count(std::begin(c), std::end(c), std::forward<T>(value));
180}
181
184template <typename C, typename Pred>
185internal_algorithm::ContainerDifferenceType<const C> CountIf(const C& c,
186 Pred&& pred) {
187 return std::count_if(std::begin(c), std::end(c), std::forward<Pred>(pred));
188}
189
193template <typename C1, typename C2>
194internal_algorithm::ContainerIterPairType<C1, C2> Mismatch(C1& c1, C2& c2) {
195 auto first1 = std::begin(c1);
196 auto last1 = std::end(c1);
197 auto first2 = std::begin(c2);
198 auto last2 = std::end(c2);
199
200 for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
201 // Negates equality because Cpp17EqualityComparable doesn't require clients
202 // to overload both `operator==` and `operator!=`.
203 if (!(*first1 == *first2)) {
204 break;
205 }
206 }
207
208 return std::make_pair(first1, first2);
209}
210
214template <typename C1, typename C2, typename BinaryPredicate>
215internal_algorithm::ContainerIterPairType<C1, C2> Mismatch(
216 C1& c1, C2& c2, BinaryPredicate pred) {
217 auto first1 = std::begin(c1);
218 auto last1 = std::end(c1);
219 auto first2 = std::begin(c2);
220 auto last2 = std::end(c2);
221
222 for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
223 if (!pred(*first1, *first2)) {
224 break;
225 }
226 }
227
228 return std::make_pair(first1, first2);
229}
230
246
247template <typename C1, typename C2>
248bool Equal(const C1& c1, const C2& c2) {
249 return ((std::size(c1) == std::size(c2)) &&
250 std::equal(std::begin(c1), std::end(c1), std::begin(c2)));
251}
252
255template <typename C1, typename C2, typename BinaryPredicate>
256bool Equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
257 return ((std::size(c1) == std::size(c2)) &&
258 std::equal(std::begin(c1),
259 std::end(c1),
260 std::begin(c2),
261 std::forward<BinaryPredicate>(pred)));
262}
263
266template <typename C1, typename C2>
267bool IsPermutation(const C1& c1, const C2& c2) {
268 using std::begin;
269 using std::end;
270 return c1.size() == c2.size() &&
271 std::is_permutation(begin(c1), end(c1), begin(c2));
272}
273
276template <typename C1, typename C2, typename BinaryPredicate>
277bool IsPermutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
278 using std::begin;
279 using std::end;
280 return c1.size() == c2.size() &&
281 std::is_permutation(begin(c1),
282 end(c1),
283 begin(c2),
284 std::forward<BinaryPredicate>(pred));
285}
286
289template <typename Sequence1, typename Sequence2>
290internal_algorithm::ContainerIter<Sequence1> Search(Sequence1& sequence,
291 Sequence2& subsequence) {
292 return std::search(std::begin(sequence),
293 std::end(sequence),
294 std::begin(subsequence),
295 std::end(subsequence));
296}
297
300template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
301internal_algorithm::ContainerIter<Sequence1> Search(Sequence1& sequence,
302 Sequence2& subsequence,
303 BinaryPredicate&& pred) {
304 return std::search(std::begin(sequence),
305 std::end(sequence),
306 std::begin(subsequence),
307 std::end(subsequence),
308 std::forward<BinaryPredicate>(pred));
309}
310
313template <typename Sequence, typename Size, typename T>
314internal_algorithm::ContainerIter<Sequence> SearchN(Sequence& sequence,
315 Size count,
316 T&& value) {
317 return std::search_n(
318 std::begin(sequence), std::end(sequence), count, std::forward<T>(value));
319}
320
323template <typename Sequence,
324 typename Size,
325 typename T,
326 typename BinaryPredicate>
327internal_algorithm::ContainerIter<Sequence> SearchN(Sequence& sequence,
328 Size count,
329 T&& value,
330 BinaryPredicate&& pred) {
331 return std::search_n(std::begin(sequence),
332 std::end(sequence),
333 count,
334 std::forward<T>(value),
335 std::forward<BinaryPredicate>(pred));
336}
337
338} // namespace containers
339
340#if defined(__cpp_lib_constexpr_algorithms)
341
342// Use the standard library versions if they are constexpr.
343using std::all_of;
344using std::any_of;
345using std::copy;
346using std::copy_if;
347using std::fill;
348using std::fill_n;
349using std::find_if;
350
351#else
352
354template <typename InputIt, typename OutputIt>
355constexpr OutputIt copy(InputIt first, InputIt last, OutputIt d_first) {
356 while (first != last) {
357 *d_first++ = *first++;
358 }
359 return d_first;
360}
361
363template <typename InputIt, typename OutputIt, typename UnaryPredicate>
364constexpr OutputIt copy_if(InputIt first,
365 InputIt last,
366 OutputIt d_first,
367 UnaryPredicate pred) {
368 while (first != last) {
369 if (pred(*first)) {
370 *d_first++ = *first;
371 }
372 ++first;
373 }
374 return d_first;
375}
376
378template <typename InputIt, typename Predicate>
379constexpr bool all_of(InputIt first, InputIt last, Predicate pred) {
380 for (; first != last; ++first) {
381 if (!pred(*first)) {
382 return false;
383 }
384 }
385 return true;
386}
387
389template <typename InputIt, typename Predicate>
390constexpr bool any_of(InputIt first, InputIt last, Predicate pred) {
391 for (; first != last; ++first) {
392 if (pred(*first)) {
393 return true;
394 }
395 }
396 return false;
397}
398
400template <typename InputIt, typename Predicate>
401constexpr InputIt find_if(InputIt first, InputIt last, Predicate pred) {
402 for (; first != last; ++first) {
403 if (pred(*first)) {
404 return first;
405 }
406 }
407 return last;
408}
409
411template <typename ForwardIt, typename T>
412constexpr void fill(ForwardIt begin, ForwardIt end, const T& value) {
413 for (; begin != end; ++begin) {
414 *begin = value;
415 }
416}
417
419template <typename It, typename Size, typename T>
420constexpr It fill_n(It begin, Size count, const T& value) {
421 for (Size i = 0; i < count; ++i) {
422 *begin++ = value;
423 }
424 return begin;
425}
426
427#endif
428} // namespace pw
std::decay_t< Function > ForEach(C &&c, Function &&f)
Definition: algorithm.h:77
internal_algorithm::ContainerIter< C > FindIfNot(C &c, Pred &&pred)
Definition: algorithm.h:105
internal_algorithm::ContainerIter< Sequence > SearchN(Sequence &sequence, Size count, T &&value)
Definition: algorithm.h:314
internal_algorithm::ContainerIter< C > Find(C &c, T &&value)
Definition: algorithm.h:84
bool Equal(const C1 &c1, const C2 &c2)
Definition: algorithm.h:248
internal_algorithm::ContainerIter< Sequence1 > Search(Sequence1 &sequence, Sequence2 &subsequence)
Definition: algorithm.h:290
internal_algorithm::ContainerIter< Sequence > AdjacentFind(Sequence &sequence)
Definition: algorithm.h:160
internal_algorithm::ContainerIter< Sequence1 > FindEnd(Sequence1 &sequence, Sequence2 &subsequence)
Definition: algorithm.h:112
constexpr InputIt find_if(InputIt first, InputIt last, Predicate pred)
constexpr backport of <algorithm>'s std::find_if for C++17.
Definition: algorithm.h:401
constexpr It fill_n(It begin, Size count, const T &value)
constexpr backport of <algorithm>'s std::fill_n for C++17.
Definition: algorithm.h:420
constexpr OutputIt copy(InputIt first, InputIt last, OutputIt d_first)
constexpr backport of <algorithm>'s std::copy for C++17.
Definition: algorithm.h:355
constexpr bool all_of(InputIt first, InputIt last, Predicate pred)
constexpr backport of <algorithm>'s std::all_of for C++17.
Definition: algorithm.h:379
internal_algorithm::ContainerDifferenceType< const C > CountIf(const C &c, Pred &&pred)
Definition: algorithm.h:185
bool AllOf(const C &c, Pred &&pred)
Definition: algorithm.h:56
bool AnyOf(const C &c, Pred &&pred)
Definition: algorithm.h:63
bool IsPermutation(const C1 &c1, const C2 &c2)
Definition: algorithm.h:267
internal_algorithm::ContainerIter< C > FindIf(C &c, Pred &&pred)
Definition: algorithm.h:98
internal_algorithm::ContainerIterPairType< C1, C2 > Mismatch(C1 &c1, C2 &c2)
Definition: algorithm.h:194
constexpr void fill(ForwardIt begin, ForwardIt end, const T &value)
constexpr backport of <algorithm>'s std::fill for C++17.
Definition: algorithm.h:412
bool NoneOf(const C &c, Pred &&pred)
Definition: algorithm.h:70
internal_algorithm::ContainerIter< C1 > FindFirstOf(C1 &container, C2 &options)
Definition: algorithm.h:137
constexpr bool any_of(InputIt first, InputIt last, Predicate pred)
constexpr backport of <algorithm>'s std::any_of for C++17.
Definition: algorithm.h:390
constexpr OutputIt copy_if(InputIt first, InputIt last, OutputIt d_first, UnaryPredicate pred)
constexpr backport of <algorithm>'s std::copy_if for C++17.
Definition: algorithm.h:364
internal_algorithm::ContainerDifferenceType< const C > Count(const C &c, T &&value)
Definition: algorithm.h:177
fit::function_impl< function_internal::config::kInlineCallableSize, !function_internal::config::kEnableDynamicAllocation, FunctionType, PW_FUNCTION_DEFAULT_ALLOCATOR_TYPE > Function
Definition: function.h:73
The Pigweed namespace.
Definition: alignment.h:27