117bbb224Svarconst //===----------------------------------------------------------------------===//
217bbb224Svarconst //
317bbb224Svarconst // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
417bbb224Svarconst // See https://llvm.org/LICENSE.txt for license information.
517bbb224Svarconst // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
617bbb224Svarconst //
717bbb224Svarconst //===----------------------------------------------------------------------===//
817bbb224Svarconst
917bbb224Svarconst #ifndef SUPPORT_INSERT_RANGE_HELPERS_H
1017bbb224Svarconst #define SUPPORT_INSERT_RANGE_HELPERS_H
1117bbb224Svarconst
1217bbb224Svarconst #include <algorithm>
1317bbb224Svarconst #include <array>
1417bbb224Svarconst #include <cassert>
1517bbb224Svarconst #include <concepts>
1617bbb224Svarconst #include <map>
1717bbb224Svarconst #include <ranges>
1817bbb224Svarconst #include <set>
1917bbb224Svarconst #include <type_traits>
2017bbb224Svarconst #include <unordered_map>
2117bbb224Svarconst #include <unordered_set>
2217bbb224Svarconst #include <vector>
2317bbb224Svarconst
24*ef70fe4dSvarconst #include "exception_safety_helpers.h"
2517bbb224Svarconst #include "from_range_helpers.h"
2617bbb224Svarconst #include "min_allocator.h"
2717bbb224Svarconst #include "test_allocator.h"
2817bbb224Svarconst #include "test_iterators.h"
2917bbb224Svarconst #include "test_macros.h"
3017bbb224Svarconst #include "type_algorithms.h"
3117bbb224Svarconst
3217bbb224Svarconst // A simple literal-type container. It can be used as a `constexpr` global variable (which isn't supported by
3317bbb224Svarconst // `std::vector`).
3417bbb224Svarconst template <class T, std::size_t N = 32>
3517bbb224Svarconst class Buffer {
3617bbb224Svarconst public:
3717bbb224Svarconst constexpr Buffer() = default;
3817bbb224Svarconst
Buffer(std::initializer_list<T> input)3917bbb224Svarconst constexpr Buffer(std::initializer_list<T> input) {
4017bbb224Svarconst assert(input.size() <= N);
4117bbb224Svarconst std::ranges::copy(input, data_);
4217bbb224Svarconst size_ = input.size();
4317bbb224Svarconst }
4417bbb224Svarconst
4517bbb224Svarconst // Makes initializing `Buffer<char>` nicer -- allows writing `buf = "abc"` instead of `buf = {'a', 'b', 'c'}`.
4617bbb224Svarconst // To make the two forms equivalent, omits the terminating null.
4717bbb224Svarconst template <std::size_t N2>
Buffer(const char (& input)[N2])4817bbb224Svarconst constexpr Buffer(const char (&input) [N2])
4917bbb224Svarconst requires std::same_as<T, char> {
5017bbb224Svarconst static_assert(N2 <= N);
5117bbb224Svarconst std::ranges::copy(input, data_);
5217bbb224Svarconst // Omit the terminating null.
5317bbb224Svarconst size_ = input[N2 - 1] == '\0' ? N2 - 1 : N2;
5417bbb224Svarconst }
5517bbb224Svarconst
begin()5617bbb224Svarconst constexpr const T* begin() const { return data_; }
end()5717bbb224Svarconst constexpr const T* end() const { return data_ + size_; }
size()5817bbb224Svarconst constexpr std::size_t size() const { return size_; }
5917bbb224Svarconst
6017bbb224Svarconst private:
6117bbb224Svarconst std::size_t size_ = 0;
6217bbb224Svarconst T data_[N] = {};
6317bbb224Svarconst };
6417bbb224Svarconst
6517bbb224Svarconst template <class T>
6617bbb224Svarconst struct TestCase {
6717bbb224Svarconst Buffer<T> initial;
6817bbb224Svarconst std::size_t index = 0;
6917bbb224Svarconst Buffer<T> input;
7017bbb224Svarconst Buffer<T> expected;
7117bbb224Svarconst };
7217bbb224Svarconst
7317bbb224Svarconst template <class T, class PtrT, class Func>
for_all_iterators_and_allocators(Func f)7417bbb224Svarconst constexpr void for_all_iterators_and_allocators(Func f) {
7517bbb224Svarconst using Iterators = types::type_list<
7617bbb224Svarconst cpp20_input_iterator<PtrT>,
7717bbb224Svarconst forward_iterator<PtrT>,
7817bbb224Svarconst bidirectional_iterator<PtrT>,
7917bbb224Svarconst random_access_iterator<PtrT>,
8017bbb224Svarconst contiguous_iterator<PtrT>,
8117bbb224Svarconst PtrT
8217bbb224Svarconst >;
8317bbb224Svarconst
8417bbb224Svarconst types::for_each(Iterators{}, [=]<class Iter>() {
8517bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, std::allocator<T>>();
8617bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, test_allocator<T>>();
8717bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, min_allocator<T>>();
8817bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, safe_allocator<T>>();
8917bbb224Svarconst
9017bbb224Svarconst if constexpr (std::sentinel_for<Iter, Iter>) {
9117bbb224Svarconst f.template operator()<Iter, Iter, std::allocator<T>>();
9217bbb224Svarconst f.template operator()<Iter, Iter, test_allocator<T>>();
9317bbb224Svarconst f.template operator()<Iter, Iter, min_allocator<T>>();
9417bbb224Svarconst f.template operator()<Iter, Iter, safe_allocator<T>>();
9517bbb224Svarconst }
9617bbb224Svarconst });
9717bbb224Svarconst }
9817bbb224Svarconst
9917bbb224Svarconst // Uses a shorter list of iterator types for use in `constexpr` mode for cases when running the full set in would take
10017bbb224Svarconst // too long.
10117bbb224Svarconst template <class T, class PtrT, class Func>
for_all_iterators_and_allocators_constexpr(Func f)10217bbb224Svarconst constexpr void for_all_iterators_and_allocators_constexpr(Func f) {
10317bbb224Svarconst using Iterators = types::type_list<
10417bbb224Svarconst cpp20_input_iterator<PtrT>,
10517bbb224Svarconst forward_iterator<PtrT>,
10617bbb224Svarconst PtrT
10717bbb224Svarconst >;
10817bbb224Svarconst
10917bbb224Svarconst types::for_each(Iterators{}, [=]<class Iter>() {
11017bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, std::allocator<T>>();
11117bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, test_allocator<T>>();
11217bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, min_allocator<T>>();
11317bbb224Svarconst f.template operator()<Iter, sentinel_wrapper<Iter>, safe_allocator<T>>();
11417bbb224Svarconst
11517bbb224Svarconst if constexpr (std::sentinel_for<Iter, Iter>) {
11617bbb224Svarconst f.template operator()<Iter, Iter, std::allocator<T>>();
11717bbb224Svarconst f.template operator()<Iter, Iter, test_allocator<T>>();
11817bbb224Svarconst f.template operator()<Iter, Iter, min_allocator<T>>();
11917bbb224Svarconst f.template operator()<Iter, Iter, safe_allocator<T>>();
12017bbb224Svarconst }
12117bbb224Svarconst });
12217bbb224Svarconst }
12317bbb224Svarconst
12417bbb224Svarconst #endif // SUPPORT_INSERT_RANGE_HELPERS_H
125