| 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 | |