summaryrefslogtreecommitdiff
path: root/src/common/polyfill_ranges.h
diff options
context:
space:
mode:
authorGravatar liamwhite2022-12-03 12:09:21 -0500
committerGravatar GitHub2022-12-03 12:09:21 -0500
commit22aff09b33941cdf907e474cb86117fef838abba (patch)
tree73a747be44fd2ba994c3d40c8f6ea18633c0f880 /src/common/polyfill_ranges.h
parentMerge pull request #9353 from vonchenplus/draw_indexed (diff)
parentgeneral: fix compile for Apple Clang (diff)
downloadyuzu-22aff09b33941cdf907e474cb86117fef838abba.tar.gz
yuzu-22aff09b33941cdf907e474cb86117fef838abba.tar.xz
yuzu-22aff09b33941cdf907e474cb86117fef838abba.zip
Merge pull request #9289 from liamwhite/fruit-company
general: fix compile for Apple Clang
Diffstat (limited to 'src/common/polyfill_ranges.h')
-rw-r--r--src/common/polyfill_ranges.h530
1 files changed, 530 insertions, 0 deletions
diff --git a/src/common/polyfill_ranges.h b/src/common/polyfill_ranges.h
new file mode 100644
index 000000000..ca44bfaef
--- /dev/null
+++ b/src/common/polyfill_ranges.h
@@ -0,0 +1,530 @@
1// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4//
5// TODO: remove this file when ranges are supported by all compilation targets
6//
7
8#pragma once
9
10#include <algorithm>
11#include <utility>
12#include <version>
13
14#ifndef __cpp_lib_ranges
15
16namespace std {
17namespace ranges {
18
19template <typename T>
20concept range = requires(T& t) {
21 begin(t);
22 end(t);
23};
24
25template <typename T>
26concept input_range = range<T>;
27
28template <typename T>
29concept output_range = range<T>;
30
31template <range R>
32using range_difference_t = ptrdiff_t;
33
34//
35// find, find_if, find_if_not
36//
37
38struct find_fn {
39 template <typename Iterator, typename T, typename Proj = std::identity>
40 constexpr Iterator operator()(Iterator first, Iterator last, const T& value,
41 Proj proj = {}) const {
42 for (; first != last; ++first) {
43 if (std::invoke(proj, *first) == value) {
44 return first;
45 }
46 }
47 return first;
48 }
49
50 template <ranges::input_range R, typename T, typename Proj = std::identity>
51 constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Proj proj = {}) const {
52 return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj));
53 }
54};
55
56struct find_if_fn {
57 template <typename Iterator, typename Proj = std::identity, typename Pred>
58 constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
59 for (; first != last; ++first) {
60 if (std::invoke(pred, std::invoke(proj, *first))) {
61 return first;
62 }
63 }
64 return first;
65 }
66
67 template <ranges::input_range R, typename Proj = std::identity, typename Pred>
68 constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const {
69 return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
70 }
71};
72
73struct find_if_not_fn {
74 template <typename Iterator, typename Proj = std::identity, typename Pred>
75 constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
76 for (; first != last; ++first) {
77 if (!std::invoke(pred, std::invoke(proj, *first))) {
78 return first;
79 }
80 }
81 return first;
82 }
83
84 template <ranges::input_range R, typename Proj = std::identity, typename Pred>
85 constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const {
86 return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
87 }
88};
89
90inline constexpr find_fn find;
91inline constexpr find_if_fn find_if;
92inline constexpr find_if_not_fn find_if_not;
93
94//
95// any_of, all_of, none_of
96//
97
98struct all_of_fn {
99 template <typename Iterator, typename Proj = std::identity, typename Pred>
100 constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
101 return ranges::find_if_not(first, last, std::ref(pred), std::ref(proj)) == last;
102 }
103
104 template <ranges::input_range R, typename Proj = std::identity, typename Pred>
105 constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
106 return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
107 }
108};
109
110struct any_of_fn {
111 template <typename Iterator, typename Proj = std::identity, typename Pred>
112 constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
113 return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) != last;
114 }
115
116 template <ranges::input_range R, typename Proj = std::identity, typename Pred>
117 constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
118 return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
119 }
120};
121
122struct none_of_fn {
123 template <typename Iterator, typename Proj = std::identity, typename Pred>
124 constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
125 return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) == last;
126 }
127
128 template <ranges::input_range R, typename Proj = std::identity, typename Pred>
129 constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
130 return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
131 }
132};
133
134inline constexpr any_of_fn any_of;
135inline constexpr all_of_fn all_of;
136inline constexpr none_of_fn none_of;
137
138//
139// count, count_if
140//
141
142struct count_fn {
143 template <typename Iterator, typename T, typename Proj = std::identity>
144 constexpr ptrdiff_t operator()(Iterator first, Iterator last, const T& value,
145 Proj proj = {}) const {
146 ptrdiff_t counter = 0;
147 for (; first != last; ++first)
148 if (std::invoke(proj, *first) == value)
149 ++counter;
150 return counter;
151 }
152
153 template <ranges::input_range R, typename T, typename Proj = std::identity>
154 constexpr ptrdiff_t operator()(R&& r, const T& value, Proj proj = {}) const {
155 return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj));
156 }
157};
158
159struct count_if_fn {
160 template <typename Iterator, typename Proj = std::identity, typename Pred>
161 constexpr ptrdiff_t operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
162 ptrdiff_t counter = 0;
163 for (; first != last; ++first)
164 if (std::invoke(pred, std::invoke(proj, *first)))
165 ++counter;
166 return counter;
167 }
168
169 template <ranges::input_range R, typename Proj = std::identity, typename Pred>
170 constexpr ptrdiff_t operator()(R&& r, Pred pred, Proj proj = {}) const {
171 return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
172 }
173};
174
175inline constexpr count_fn count;
176inline constexpr count_if_fn count_if;
177
178//
179// transform
180//
181
182struct transform_fn {
183 template <typename InputIterator, typename OutputIterator, typename F,
184 typename Proj = std::identity>
185 constexpr void operator()(InputIterator first1, InputIterator last1, OutputIterator result,
186 F op, Proj proj = {}) const {
187 for (; first1 != last1; ++first1, (void)++result) {
188 *result = std::invoke(op, std::invoke(proj, *first1));
189 }
190 }
191
192 template <ranges::input_range R, typename OutputIterator, typename F,
193 typename Proj = std::identity>
194 constexpr void operator()(R&& r, OutputIterator result, F op, Proj proj = {}) const {
195 return operator()(ranges::begin(r), ranges::end(r), result, std::ref(op), std::ref(proj));
196 }
197};
198
199inline constexpr transform_fn transform;
200
201//
202// sort
203//
204
205struct sort_fn {
206 template <typename Iterator, typename Comp = ranges::less, typename Proj = std::identity>
207 constexpr void operator()(Iterator first, Iterator last, Comp comp = {}, Proj proj = {}) const {
208 if (first == last)
209 return;
210
211 Iterator last_iter = ranges::next(first, last);
212 std::sort(first, last_iter,
213 [&](auto& lhs, auto& rhs) { return comp(proj(lhs), proj(rhs)); });
214 }
215
216 template <ranges::input_range R, typename Comp = ranges::less, typename Proj = std::identity>
217 constexpr void operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
218 return operator()(ranges::begin(r), ranges::end(r), std::move(comp), std::move(proj));
219 }
220};
221
222inline constexpr sort_fn sort;
223
224//
225// fill
226//
227
228struct fill_fn {
229 template <typename T, typename OutputIterator>
230 constexpr OutputIterator operator()(OutputIterator first, OutputIterator last,
231 const T& value) const {
232 while (first != last) {
233 *first++ = value;
234 }
235
236 return first;
237 }
238
239 template <typename T, ranges::output_range R>
240 constexpr ranges::iterator_t<R> operator()(R&& r, const T& value) const {
241 return operator()(ranges::begin(r), ranges::end(r), value);
242 }
243};
244
245inline constexpr fill_fn fill;
246
247//
248// for_each
249//
250
251struct for_each_fn {
252 template <typename Iterator, typename Proj = std::identity, typename Fun>
253 constexpr void operator()(Iterator first, Iterator last, Fun f, Proj proj = {}) const {
254 for (; first != last; ++first) {
255 std::invoke(f, std::invoke(proj, *first));
256 }
257 }
258
259 template <ranges::input_range R, typename Proj = std::identity, typename Fun>
260 constexpr void operator()(R&& r, Fun f, Proj proj = {}) const {
261 return operator()(ranges::begin(r), ranges::end(r), std::move(f), std::ref(proj));
262 }
263};
264
265inline constexpr for_each_fn for_each;
266
267//
268// min_element, max_element
269//
270
271struct min_element_fn {
272 template <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less>
273 constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {},
274 Proj proj = {}) const {
275 if (first == last) {
276 return last;
277 }
278
279 auto smallest = first;
280 ++first;
281 for (; first != last; ++first) {
282 if (!std::invoke(comp, std::invoke(proj, *smallest), std::invoke(proj, *first))) {
283 smallest = first;
284 }
285 }
286 return smallest;
287 }
288
289 template <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less>
290 constexpr ranges::iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
291 return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj));
292 }
293};
294
295struct max_element_fn {
296 template <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less>
297 constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {},
298 Proj proj = {}) const {
299 if (first == last) {
300 return last;
301 }
302
303 auto largest = first;
304 ++first;
305 for (; first != last; ++first) {
306 if (std::invoke(comp, std::invoke(proj, *largest), std::invoke(proj, *first))) {
307 largest = first;
308 }
309 }
310 return largest;
311 }
312
313 template <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less>
314 constexpr ranges::iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
315 return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj));
316 }
317};
318
319inline constexpr min_element_fn min_element;
320inline constexpr max_element_fn max_element;
321
322//
323// replace, replace_if
324//
325
326struct replace_fn {
327 template <typename Iterator, typename T1, typename T2, typename Proj = std::identity>
328 constexpr Iterator operator()(Iterator first, Iterator last, const T1& old_value,
329 const T2& new_value, Proj proj = {}) const {
330 for (; first != last; ++first) {
331 if (old_value == std::invoke(proj, *first)) {
332 *first = new_value;
333 }
334 }
335 return first;
336 }
337
338 template <ranges::input_range R, typename T1, typename T2, typename Proj = std::identity>
339 constexpr ranges::iterator_t<R> operator()(R&& r, const T1& old_value, const T2& new_value,
340 Proj proj = {}) const {
341 return operator()(ranges::begin(r), ranges::end(r), old_value, new_value, std::move(proj));
342 }
343};
344
345struct replace_if_fn {
346 template <typename Iterator, typename T, typename Proj = std::identity, typename Pred>
347 constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, const T& new_value,
348 Proj proj = {}) const {
349 for (; first != last; ++first) {
350 if (!!std::invoke(pred, std::invoke(proj, *first))) {
351 *first = new_value;
352 }
353 }
354 return std::move(first);
355 }
356
357 template <ranges::input_range R, typename T, typename Proj = std::identity, typename Pred>
358 constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, const T& new_value,
359 Proj proj = {}) const {
360 return operator()(ranges::begin(r), ranges::end(r), std::move(pred), new_value,
361 std::move(proj));
362 }
363};
364
365inline constexpr replace_fn replace;
366inline constexpr replace_if_fn replace_if;
367
368//
369// copy, copy_if
370//
371
372struct copy_fn {
373 template <typename InputIterator, typename OutputIterator>
374 constexpr void operator()(InputIterator first, InputIterator last,
375 OutputIterator result) const {
376 for (; first != last; ++first, (void)++result) {
377 *result = *first;
378 }
379 }
380
381 template <ranges::input_range R, typename OutputIterator>
382 constexpr void operator()(R&& r, OutputIterator result) const {
383 return operator()(ranges::begin(r), ranges::end(r), std::move(result));
384 }
385};
386
387struct copy_if_fn {
388 template <typename InputIterator, typename OutputIterator, typename Proj = std::identity,
389 typename Pred>
390 constexpr void operator()(InputIterator first, InputIterator last, OutputIterator result,
391 Pred pred, Proj proj = {}) const {
392 for (; first != last; ++first) {
393 if (std::invoke(pred, std::invoke(proj, *first))) {
394 *result = *first;
395 ++result;
396 }
397 }
398 }
399
400 template <ranges::input_range R, typename OutputIterator, typename Proj = std::identity,
401 typename Pred>
402 constexpr void operator()(R&& r, OutputIterator result, Pred pred, Proj proj = {}) const {
403 return operator()(ranges::begin(r), ranges::end(r), std::move(result), std::ref(pred),
404 std::ref(proj));
405 }
406};
407
408inline constexpr copy_fn copy;
409inline constexpr copy_if_fn copy_if;
410
411//
412// generate
413//
414
415struct generate_fn {
416 template <typename Iterator, typename F>
417 constexpr Iterator operator()(Iterator first, Iterator last, F gen) const {
418 for (; first != last; *first = std::invoke(gen), ++first)
419 ;
420 return first;
421 }
422
423 template <typename R, std::copy_constructible F>
424 requires std::invocable<F&> && ranges::output_range<R>
425 constexpr ranges::iterator_t<R> operator()(R&& r, F gen) const {
426 return operator()(ranges::begin(r), ranges::end(r), std::move(gen));
427 }
428};
429
430inline constexpr generate_fn generate;
431
432//
433// lower_bound, upper_bound
434//
435
436struct lower_bound_fn {
437 template <typename Iterator, typename T, typename Proj = std::identity,
438 typename Comp = ranges::less>
439 constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {},
440 Proj proj = {}) const {
441 Iterator it;
442 std::ptrdiff_t _count, _step;
443 _count = std::distance(first, last);
444
445 while (_count > 0) {
446 it = first;
447 _step = _count / 2;
448 ranges::advance(it, _step, last);
449 if (comp(std::invoke(proj, *it), value)) {
450 first = ++it;
451 _count -= _step + 1;
452 } else {
453 _count = _step;
454 }
455 }
456 return first;
457 }
458
459 template <ranges::input_range R, typename T, typename Proj = std::identity,
460 typename Comp = ranges::less>
461 constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Comp comp = {},
462 Proj proj = {}) const {
463 return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj));
464 }
465};
466
467struct upper_bound_fn {
468 template <typename Iterator, typename T, typename Proj = std::identity,
469 typename Comp = ranges::less>
470 constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {},
471 Proj proj = {}) const {
472 Iterator it;
473 std::ptrdiff_t _count, _step;
474 _count = std::distance(first, last);
475
476 while (_count > 0) {
477 it = first;
478 _step = _count / 2;
479 ranges::advance(it, _step, last);
480 if (!comp(value, std::invoke(proj, *it))) {
481 first = ++it;
482 _count -= _step + 1;
483 } else {
484 _count = _step;
485 }
486 }
487 return first;
488 }
489
490 template <ranges::input_range R, typename T, typename Proj = std::identity,
491 typename Comp = ranges::less>
492 constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Comp comp = {},
493 Proj proj = {}) const {
494 return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj));
495 }
496};
497
498inline constexpr lower_bound_fn lower_bound;
499inline constexpr upper_bound_fn upper_bound;
500
501//
502// adjacent_find
503//
504
505struct adjacent_find_fn {
506 template <typename Iterator, typename Proj = std::identity, typename Pred = ranges::equal_to>
507 constexpr Iterator operator()(Iterator first, Iterator last, Pred pred = {},
508 Proj proj = {}) const {
509 if (first == last)
510 return first;
511 auto _next = ranges::next(first);
512 for (; _next != last; ++_next, ++first)
513 if (std::invoke(pred, std::invoke(proj, *first), std::invoke(proj, *_next)))
514 return first;
515 return _next;
516 }
517
518 template <ranges::input_range R, typename Proj = std::identity,
519 typename Pred = ranges::equal_to>
520 constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred = {}, Proj proj = {}) const {
521 return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
522 }
523};
524
525inline constexpr adjacent_find_fn adjacent_find;
526
527} // namespace ranges
528} // namespace std
529
530#endif