1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef SUPPORT_INSERT_RANGE_HELPERS_H |
10 | #define SUPPORT_INSERT_RANGE_HELPERS_H |
11 | |
12 | #include <algorithm> |
13 | #include <array> |
14 | #include <cassert> |
15 | #include <concepts> |
16 | #include <map> |
17 | #include <ranges> |
18 | #include <set> |
19 | #include <type_traits> |
20 | #include <unordered_map> |
21 | #include <unordered_set> |
22 | #include <vector> |
23 | |
24 | #include "exception_safety_helpers.h" |
25 | #include "from_range_helpers.h" |
26 | #include "min_allocator.h" |
27 | #include "test_allocator.h" |
28 | #include "test_iterators.h" |
29 | #include "test_macros.h" |
30 | #include "type_algorithms.h" |
31 | |
32 | // A simple literal-type container. It can be used as a `constexpr` global variable (which isn't supported by |
33 | // `std::vector`). |
34 | template <class T, std::size_t N = 32> |
35 | class Buffer { |
36 | public: |
37 | constexpr Buffer() = default; |
38 | |
39 | constexpr Buffer(std::initializer_list<T> input) { |
40 | assert(input.size() <= N); |
41 | std::ranges::copy(input, data_); |
42 | size_ = input.size(); |
43 | } |
44 | |
45 | // Makes initializing `Buffer<char>` nicer -- allows writing `buf = "abc"` instead of `buf = {'a', 'b', 'c'}`. |
46 | // To make the two forms equivalent, omits the terminating null. |
47 | template <std::size_t N2> |
48 | constexpr Buffer(const char (&input) [N2]) |
49 | requires std::same_as<T, char> { |
50 | static_assert(N2 <= N); |
51 | std::ranges::copy(input, data_); |
52 | // Omit the terminating null. |
53 | size_ = input[N2 - 1] == '\0' ? N2 - 1 : N2; |
54 | } |
55 | |
56 | constexpr const T* begin() const { return data_; } |
57 | constexpr const T* end() const { return data_ + size_; } |
58 | constexpr std::size_t size() const { return size_; } |
59 | |
60 | private: |
61 | std::size_t size_ = 0; |
62 | T data_[N] = {}; |
63 | }; |
64 | |
65 | template <class T> |
66 | struct TestCase { |
67 | Buffer<T> initial; |
68 | std::size_t index = 0; |
69 | Buffer<T> input; |
70 | Buffer<T> expected; |
71 | }; |
72 | |
73 | template <class T, class PtrT, class Func> |
74 | constexpr void for_all_iterators_and_allocators(Func f) { |
75 | using Iterators = types::type_list< |
76 | cpp20_input_iterator<PtrT>, |
77 | forward_iterator<PtrT>, |
78 | bidirectional_iterator<PtrT>, |
79 | random_access_iterator<PtrT>, |
80 | contiguous_iterator<PtrT>, |
81 | PtrT |
82 | >; |
83 | |
84 | types::for_each(Iterators{}, [=]<class Iter>() { |
85 | f.template operator()<Iter, sentinel_wrapper<Iter>, std::allocator<T>>(); |
86 | f.template operator()<Iter, sentinel_wrapper<Iter>, test_allocator<T>>(); |
87 | f.template operator()<Iter, sentinel_wrapper<Iter>, min_allocator<T>>(); |
88 | f.template operator()<Iter, sentinel_wrapper<Iter>, safe_allocator<T>>(); |
89 | |
90 | if constexpr (std::sentinel_for<Iter, Iter>) { |
91 | f.template operator()<Iter, Iter, std::allocator<T>>(); |
92 | f.template operator()<Iter, Iter, test_allocator<T>>(); |
93 | f.template operator()<Iter, Iter, min_allocator<T>>(); |
94 | f.template operator()<Iter, Iter, safe_allocator<T>>(); |
95 | } |
96 | }); |
97 | } |
98 | |
99 | // Uses a shorter list of iterator types for use in `constexpr` mode for cases when running the full set in would take |
100 | // too long. |
101 | template <class T, class PtrT, class Func> |
102 | constexpr void for_all_iterators_and_allocators_constexpr(Func f) { |
103 | using Iterators = types::type_list< |
104 | cpp20_input_iterator<PtrT>, |
105 | forward_iterator<PtrT>, |
106 | PtrT |
107 | >; |
108 | |
109 | types::for_each(Iterators{}, [=]<class Iter>() { |
110 | f.template operator()<Iter, sentinel_wrapper<Iter>, std::allocator<T>>(); |
111 | f.template operator()<Iter, sentinel_wrapper<Iter>, test_allocator<T>>(); |
112 | f.template operator()<Iter, sentinel_wrapper<Iter>, min_allocator<T>>(); |
113 | f.template operator()<Iter, sentinel_wrapper<Iter>, safe_allocator<T>>(); |
114 | |
115 | if constexpr (std::sentinel_for<Iter, Iter>) { |
116 | f.template operator()<Iter, Iter, std::allocator<T>>(); |
117 | f.template operator()<Iter, Iter, test_allocator<T>>(); |
118 | f.template operator()<Iter, Iter, min_allocator<T>>(); |
119 | f.template operator()<Iter, Iter, safe_allocator<T>>(); |
120 | } |
121 | }); |
122 | } |
123 | |
124 | #endif // SUPPORT_INSERT_RANGE_HELPERS_H |
125 | |