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
90template <typename C, typename Pred>
91internal_algorithm::ContainerIter<C> FindIf(C& c, Pred&& pred) {
92 return std::find_if(std::begin(c), std::end(c), std::forward<Pred>(pred));
93}
94
97template <typename C, typename Pred>
98internal_algorithm::ContainerIter<C> FindIfNot(C& c, Pred&& pred) {
99 return std::find_if_not(std::begin(c), std::end(c), std::forward<Pred>(pred));
100}
101
104template <typename Sequence1, typename Sequence2>
105internal_algorithm::ContainerIter<Sequence1> FindEnd(Sequence1& sequence,
106 Sequence2& subsequence) {
107 return std::find_end(std::begin(sequence),
108 std::end(sequence),
109 std::begin(subsequence),
110 std::end(subsequence));
111}
112
115template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
116internal_algorithm::ContainerIter<Sequence1> FindEnd(Sequence1& sequence,
117 Sequence2& subsequence,
118 BinaryPredicate&& pred) {
119 return std::find_end(std::begin(sequence),
120 std::end(sequence),
121 std::begin(subsequence),
122 std::end(subsequence),
123 std::forward<BinaryPredicate>(pred));
124}
125
129template <typename C1, typename C2>
130internal_algorithm::ContainerIter<C1> FindFirstOf(C1& container, C2& options) {
131 return std::find_first_of(std::begin(container),
132 std::end(container),
133 std::begin(options),
134 std::end(options));
135}
136
139template <typename C1, typename C2, typename BinaryPredicate>
140internal_algorithm::ContainerIter<C1> FindFirstOf(C1& container,
141 C2& options,
142 BinaryPredicate&& pred) {
143 return std::find_first_of(std::begin(container),
144 std::end(container),
145 std::begin(options),
146 std::end(options),
147 std::forward<BinaryPredicate>(pred));
148}
149
152template <typename Sequence>
153internal_algorithm::ContainerIter<Sequence> AdjacentFind(Sequence& sequence) {
154 return std::adjacent_find(std::begin(sequence), std::end(sequence));
155}
156
159template <typename Sequence, typename BinaryPredicate>
160internal_algorithm::ContainerIter<Sequence> AdjacentFind(
161 Sequence& sequence, BinaryPredicate&& pred) {
162 return std::adjacent_find(std::begin(sequence),
163 std::end(sequence),
164 std::forward<BinaryPredicate>(pred));
165}
166
169template <typename C, typename T>
170internal_algorithm::ContainerDifferenceType<const C> Count(const C& c,
171 T&& value) {
172 return std::count(std::begin(c), std::end(c), std::forward<T>(value));
173}
174
177template <typename C, typename Pred>
178internal_algorithm::ContainerDifferenceType<const C> CountIf(const C& c,
179 Pred&& pred) {
180 return std::count_if(std::begin(c), std::end(c), std::forward<Pred>(pred));
181}
182
186template <typename C1, typename C2>
187internal_algorithm::ContainerIterPairType<C1, C2> Mismatch(C1& c1, C2& c2) {
188 auto first1 = std::begin(c1);
189 auto last1 = std::end(c1);
190 auto first2 = std::begin(c2);
191 auto last2 = std::end(c2);
192
193 for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
194 // Negates equality because Cpp17EqualityComparable doesn't require clients
195 // to overload both `operator==` and `operator!=`.
196 if (!(*first1 == *first2)) {
197 break;
198 }
199 }
200
201 return std::make_pair(first1, first2);
202}
203
207template <typename C1, typename C2, typename BinaryPredicate>
208internal_algorithm::ContainerIterPairType<C1, C2> Mismatch(
209 C1& c1, C2& c2, BinaryPredicate pred) {
210 auto first1 = std::begin(c1);
211 auto last1 = std::end(c1);
212 auto first2 = std::begin(c2);
213 auto last2 = std::end(c2);
214
215 for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
216 if (!pred(*first1, *first2)) {
217 break;
218 }
219 }
220
221 return std::make_pair(first1, first2);
222}
223
239
240template <typename C1, typename C2>
241bool Equal(const C1& c1, const C2& c2) {
242 return ((std::size(c1) == std::size(c2)) &&
243 std::equal(std::begin(c1), std::end(c1), std::begin(c2)));
244}
245
248template <typename C1, typename C2, typename BinaryPredicate>
249bool Equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
250 return ((std::size(c1) == std::size(c2)) &&
251 std::equal(std::begin(c1),
252 std::end(c1),
253 std::begin(c2),
254 std::forward<BinaryPredicate>(pred)));
255}
256
259template <typename C1, typename C2>
260bool IsPermutation(const C1& c1, const C2& c2) {
261 using std::begin;
262 using std::end;
263 return c1.size() == c2.size() &&
264 std::is_permutation(begin(c1), end(c1), begin(c2));
265}
266
269template <typename C1, typename C2, typename BinaryPredicate>
270bool IsPermutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
271 using std::begin;
272 using std::end;
273 return c1.size() == c2.size() &&
274 std::is_permutation(begin(c1),
275 end(c1),
276 begin(c2),
277 std::forward<BinaryPredicate>(pred));
278}
279
282template <typename Sequence1, typename Sequence2>
283internal_algorithm::ContainerIter<Sequence1> Search(Sequence1& sequence,
284 Sequence2& subsequence) {
285 return std::search(std::begin(sequence),
286 std::end(sequence),
287 std::begin(subsequence),
288 std::end(subsequence));
289}
290
293template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
294internal_algorithm::ContainerIter<Sequence1> Search(Sequence1& sequence,
295 Sequence2& subsequence,
296 BinaryPredicate&& pred) {
297 return std::search(std::begin(sequence),
298 std::end(sequence),
299 std::begin(subsequence),
300 std::end(subsequence),
301 std::forward<BinaryPredicate>(pred));
302}
303
306template <typename Sequence, typename Size, typename T>
307internal_algorithm::ContainerIter<Sequence> SearchN(Sequence& sequence,
308 Size count,
309 T&& value) {
310 return std::search_n(
311 std::begin(sequence), std::end(sequence), count, std::forward<T>(value));
312}
313
316template <typename Sequence,
317 typename Size,
318 typename T,
319 typename BinaryPredicate>
320internal_algorithm::ContainerIter<Sequence> SearchN(Sequence& sequence,
321 Size count,
322 T&& value,
323 BinaryPredicate&& pred) {
324 return std::search_n(std::begin(sequence),
325 std::end(sequence),
326 count,
327 std::forward<T>(value),
328 std::forward<BinaryPredicate>(pred));
329}
330
331} // namespace containers
332
333#if defined(__cpp_lib_constexpr_algorithms)
334
335// Use the standard library versions if they are constexpr.
336using std::all_of;
337using std::any_of;
338using std::fill;
339using std::fill_n;
340using std::find_if;
341
342#else
343
345template <typename InputIt, typename Predicate>
346constexpr bool all_of(InputIt first, InputIt last, Predicate pred) {
347 for (; first != last; ++first) {
348 if (!pred(*first)) {
349 return false;
350 }
351 }
352 return true;
353}
354
356template <typename InputIt, typename Predicate>
357constexpr bool any_of(InputIt first, InputIt last, Predicate pred) {
358 for (; first != last; ++first) {
359 if (pred(*first)) {
360 return true;
361 }
362 }
363 return false;
364}
365
367template <typename InputIt, typename Predicate>
368constexpr InputIt find_if(InputIt first, InputIt last, Predicate pred) {
369 for (; first != last; ++first) {
370 if (pred(*first)) {
371 return first;
372 }
373 }
374 return last;
375}
376
378template <typename ForwardIt, typename T>
379constexpr void fill(ForwardIt begin, ForwardIt end, const T& value) {
380 for (; begin != end; ++begin) {
381 *begin = value;
382 }
383}
384
386template <typename It, typename Size, typename T>
387constexpr It fill_n(It begin, Size count, const T& value) {
388 for (Size i = 0; i < count; ++i) {
389 *begin++ = value;
390 }
391 return begin;
392}
393
394#endif
395} // 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:98
internal_algorithm::ContainerIter< Sequence > SearchN(Sequence &sequence, Size count, T &&value)
Definition: algorithm.h:307
internal_algorithm::ContainerIter< C > Find(C &c, T &&value)
Definition: algorithm.h:84
bool Equal(const C1 &c1, const C2 &c2)
Definition: algorithm.h:241
internal_algorithm::ContainerIter< Sequence1 > Search(Sequence1 &sequence, Sequence2 &subsequence)
Definition: algorithm.h:283
internal_algorithm::ContainerIter< Sequence > AdjacentFind(Sequence &sequence)
Definition: algorithm.h:153
internal_algorithm::ContainerIter< Sequence1 > FindEnd(Sequence1 &sequence, Sequence2 &subsequence)
Definition: algorithm.h:105
constexpr InputIt find_if(InputIt first, InputIt last, Predicate pred)
constexpr backport of <algorithm>'s std::find_if for C++17.
Definition: algorithm.h:368
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:387
constexpr bool all_of(InputIt first, InputIt last, Predicate pred)
constexpr backport of <algorithm>'s std::all_of for C++17.
Definition: algorithm.h:346
internal_algorithm::ContainerDifferenceType< const C > CountIf(const C &c, Pred &&pred)
Definition: algorithm.h:178
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:260
internal_algorithm::ContainerIter< C > FindIf(C &c, Pred &&pred)
Definition: algorithm.h:91
internal_algorithm::ContainerIterPairType< C1, C2 > Mismatch(C1 &c1, C2 &c2)
Definition: algorithm.h:187
constexpr void fill(ForwardIt begin, ForwardIt end, const T &value)
constexpr backport of <algorithm>'s std::fill for C++17.
Definition: algorithm.h:379
bool NoneOf(const C &c, Pred &&pred)
Definition: algorithm.h:70
internal_algorithm::ContainerIter< C1 > FindFirstOf(C1 &container, C2 &options)
Definition: algorithm.h:130
constexpr bool any_of(InputIt first, InputIt last, Predicate pred)
constexpr backport of <algorithm>'s std::any_of for C++17.
Definition: algorithm.h:357
internal_algorithm::ContainerDifferenceType< const C > Count(const C &c, T &&value)
Definition: algorithm.h:170
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