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 TEST_STD_CONTAINERS_SEQUENCES_VECTOR_COMMON_H |
10 | #define TEST_STD_CONTAINERS_SEQUENCES_VECTOR_COMMON_H |
11 | |
12 | #include <array> |
13 | #include <cassert> |
14 | #include <cstddef> |
15 | #include <cstdlib> |
16 | #include <memory> |
17 | #include <string> |
18 | #include <type_traits> |
19 | #include <utility> |
20 | #include <vector> |
21 | |
22 | #include "count_new.h" |
23 | #include "test_macros.h" |
24 | |
25 | struct throwing_t { |
26 | int* throw_after_n_ = nullptr; |
27 | throwing_t() { throw 0; } |
28 | |
29 | explicit throwing_t(int& throw_after_n) : throw_after_n_(&throw_after_n) { |
30 | if (throw_after_n == 0) |
31 | throw 0; |
32 | --throw_after_n; |
33 | } |
34 | |
35 | throwing_t(const throwing_t& rhs) : throw_after_n_(rhs.throw_after_n_) { |
36 | if (throw_after_n_ == nullptr || *throw_after_n_ == 0) |
37 | throw 1; |
38 | --*throw_after_n_; |
39 | } |
40 | |
41 | throwing_t& operator=(const throwing_t& rhs) { |
42 | throw_after_n_ = rhs.throw_after_n_; |
43 | if (throw_after_n_ == nullptr || *throw_after_n_ == 0) |
44 | throw 1; |
45 | --*throw_after_n_; |
46 | return *this; |
47 | } |
48 | |
49 | friend bool operator==(const throwing_t& lhs, const throwing_t& rhs) { |
50 | return lhs.throw_after_n_ == rhs.throw_after_n_; |
51 | } |
52 | friend bool operator!=(const throwing_t& lhs, const throwing_t& rhs) { |
53 | return lhs.throw_after_n_ != rhs.throw_after_n_; |
54 | } |
55 | }; |
56 | |
57 | #if TEST_STD_VER >= 11 |
58 | |
59 | template <typename T> |
60 | struct move_only_throwing_t { |
61 | T data_; |
62 | int* throw_after_n_ = nullptr; |
63 | bool moved_from_ = false; |
64 | |
65 | move_only_throwing_t() = default; |
66 | |
67 | explicit move_only_throwing_t(const T& data, int& throw_after_n) : data_(data), throw_after_n_(&throw_after_n) { |
68 | if (throw_after_n == 0) |
69 | throw 1; |
70 | --throw_after_n; |
71 | } |
72 | |
73 | explicit move_only_throwing_t(T&& data, int& throw_after_n) : data_(std::move(data)), throw_after_n_(&throw_after_n) { |
74 | if (throw_after_n == 0) |
75 | throw 1; |
76 | --throw_after_n; |
77 | } |
78 | |
79 | move_only_throwing_t(const move_only_throwing_t&) = delete; |
80 | move_only_throwing_t& operator=(const move_only_throwing_t&) = delete; |
81 | |
82 | move_only_throwing_t(move_only_throwing_t&& rhs) : data_(std::move(rhs.data_)), throw_after_n_(rhs.throw_after_n_) { |
83 | rhs.throw_after_n_ = nullptr; |
84 | rhs.moved_from_ = true; |
85 | if (throw_after_n_ == nullptr || *throw_after_n_ == 0) |
86 | throw 1; |
87 | --*throw_after_n_; |
88 | } |
89 | |
90 | move_only_throwing_t& operator=(move_only_throwing_t&& rhs) { |
91 | if (this == &rhs) |
92 | return *this; |
93 | data_ = std::move(rhs.data_); |
94 | throw_after_n_ = rhs.throw_after_n_; |
95 | rhs.moved_from_ = true; |
96 | rhs.throw_after_n_ = nullptr; |
97 | if (throw_after_n_ == nullptr || *throw_after_n_ == 0) |
98 | throw 1; |
99 | --*throw_after_n_; |
100 | return *this; |
101 | } |
102 | |
103 | friend bool operator==(const move_only_throwing_t& lhs, const move_only_throwing_t& rhs) { |
104 | return lhs.data_ == rhs.data_; |
105 | } |
106 | friend bool operator!=(const move_only_throwing_t& lhs, const move_only_throwing_t& rhs) { |
107 | return lhs.data_ != rhs.data_; |
108 | } |
109 | }; |
110 | |
111 | #endif |
112 | |
113 | template <typename T> |
114 | struct throwing_data { |
115 | T data_; |
116 | int* throw_after_n_ = nullptr; |
117 | throwing_data() { throw 0; } |
118 | |
119 | throwing_data(const T& data, int& throw_after_n) : data_(data), throw_after_n_(&throw_after_n) { |
120 | if (throw_after_n == 0) |
121 | throw 0; |
122 | --throw_after_n; |
123 | } |
124 | |
125 | throwing_data(const throwing_data& rhs) : data_(rhs.data_), throw_after_n_(rhs.throw_after_n_) { |
126 | if (throw_after_n_ == nullptr || *throw_after_n_ == 0) |
127 | throw 1; |
128 | --*throw_after_n_; |
129 | } |
130 | |
131 | throwing_data& operator=(const throwing_data& rhs) { |
132 | data_ = rhs.data_; |
133 | throw_after_n_ = rhs.throw_after_n_; |
134 | if (throw_after_n_ == nullptr || *throw_after_n_ == 0) |
135 | throw 1; |
136 | --*throw_after_n_; |
137 | return *this; |
138 | } |
139 | |
140 | friend bool operator==(const throwing_data& lhs, const throwing_data& rhs) { |
141 | return lhs.data_ == rhs.data_ && lhs.throw_after_n_ == rhs.throw_after_n_; |
142 | } |
143 | friend bool operator!=(const throwing_data& lhs, const throwing_data& rhs) { return !(lhs == rhs); } |
144 | }; |
145 | |
146 | template <class T> |
147 | struct throwing_allocator { |
148 | using value_type = T; |
149 | |
150 | bool throw_on_copy_ = false; |
151 | |
152 | explicit throwing_allocator(bool throw_on_ctor = true) { |
153 | if (throw_on_ctor) |
154 | throw 0; |
155 | } |
156 | |
157 | explicit throwing_allocator(bool throw_on_ctor, bool throw_on_copy) : throw_on_copy_(throw_on_copy) { |
158 | if (throw_on_ctor) |
159 | throw 0; |
160 | } |
161 | |
162 | throwing_allocator(const throwing_allocator& rhs) : throw_on_copy_(rhs.throw_on_copy_) { |
163 | if (throw_on_copy_) |
164 | throw 0; |
165 | } |
166 | |
167 | template <class U> |
168 | throwing_allocator(const throwing_allocator<U>& rhs) : throw_on_copy_(rhs.throw_on_copy_) { |
169 | if (throw_on_copy_) |
170 | throw 0; |
171 | } |
172 | |
173 | T* allocate(std::size_t n) { return std::allocator<T>().allocate(n); } |
174 | void deallocate(T* ptr, std::size_t n) { std::allocator<T>().deallocate(ptr, n); } |
175 | |
176 | template <class U> |
177 | friend bool operator==(const throwing_allocator&, const throwing_allocator<U>&) { |
178 | return true; |
179 | } |
180 | }; |
181 | |
182 | template <class T, class IterCat> |
183 | struct throwing_iterator { |
184 | using iterator_category = IterCat; |
185 | using difference_type = std::ptrdiff_t; |
186 | using value_type = T; |
187 | using reference = T&; |
188 | using pointer = T*; |
189 | |
190 | int i_; |
191 | T v_; |
192 | |
193 | explicit throwing_iterator(int i = 0, const T& v = T()) : i_(i), v_(v) {} |
194 | |
195 | reference operator*() { |
196 | if (i_ == 1) |
197 | throw 1; |
198 | return v_; |
199 | } |
200 | |
201 | friend bool operator==(const throwing_iterator& lhs, const throwing_iterator& rhs) { return lhs.i_ == rhs.i_; } |
202 | friend bool operator!=(const throwing_iterator& lhs, const throwing_iterator& rhs) { return lhs.i_ != rhs.i_; } |
203 | |
204 | throwing_iterator& operator++() { |
205 | ++i_; |
206 | return *this; |
207 | } |
208 | |
209 | throwing_iterator operator++(int) { |
210 | auto tmp = *this; |
211 | ++i_; |
212 | return tmp; |
213 | } |
214 | }; |
215 | |
216 | inline void check_new_delete_called() { |
217 | assert(globalMemCounter.new_called == globalMemCounter.delete_called); |
218 | assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called); |
219 | assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called); |
220 | assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called); |
221 | } |
222 | |
223 | template <class T, typename Alloc> |
224 | void use_unspecified_but_valid_state_vector(std::vector<T, Alloc> const& v) { |
225 | assert(v.size() >= 0); // make sure it can be called |
226 | assert(v.capacity() >= 0); |
227 | assert(v.empty() || !v.empty()); |
228 | for (auto it = v.begin(); it != v.end(); ++it) { |
229 | auto& element = *it; |
230 | (void)element; |
231 | } |
232 | } |
233 | |
234 | static const std::array<char, 62> letters = { |
235 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', |
236 | 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', |
237 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; |
238 | |
239 | inline std::string getString(std::size_t n, std::size_t len) { |
240 | std::string s; |
241 | s.reserve(res: len); |
242 | for (std::size_t i = 0; i < len; ++i) |
243 | s += letters[(i * i + n) % letters.size()]; |
244 | return s; |
245 | } |
246 | |
247 | inline std::vector<int> getIntegerInputs(std::size_t n) { |
248 | std::vector<int> v; |
249 | v.reserve(n: n); |
250 | for (std::size_t i = 0; i < n; ++i) |
251 | v.push_back(x: static_cast<int>(i * i + n)); |
252 | return v; |
253 | } |
254 | |
255 | inline std::vector<std::string> getStringInputsWithLength(std::size_t n, std::size_t len) { |
256 | std::vector<std::string> v; |
257 | v.reserve(n: n); |
258 | for (std::size_t i = 0; i < n; ++i) |
259 | v.push_back(x: getString(n: i, len)); |
260 | return v; |
261 | } |
262 | |
263 | #endif // TEST_STD_CONTAINERS_SEQUENCES_VECTOR_COMMON_H |
264 | |