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