7#ifndef TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED
8#define TWOBLUECUBES_CATCH_GENERATORS_GENERIC_HPP_INCLUDED
16 class TakeGenerator :
public IGenerator<T> {
17 GeneratorWrapper<T> m_generator;
18 size_t m_returned = 0;
22 m_generator(
std::move(generator)),
25 assert(target != 0 &&
"Empty generators are not allowed");
27 T const&
get()
const override {
28 return m_generator.get();
32 if (m_returned >= m_target) {
36 const auto success = m_generator.next();
40 m_returned = m_target;
52 template <
typename T,
typename Predicate>
53 class FilterGenerator :
public IGenerator<T> {
54 GeneratorWrapper<T> m_generator;
57 template <
typename P = Predicate>
59 m_generator(
std::move(generator)),
60 m_predicate(
std::forward<
P>(pred))
62 if (!m_predicate(m_generator.get())) {
65 auto has_initial_value = next();
66 if (!has_initial_value) {
67 Catch::throw_exception(GeneratorException(
"No valid value found in filtered generator"));
72 T const&
get()
const override {
73 return m_generator.get();
77 bool success = m_generator.next();
81 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) ==
true);
87 template <
typename T,
typename Predicate>
93 class RepeatGenerator :
public IGenerator<T> {
94 GeneratorWrapper<T> m_generator;
95 mutable std::vector<T> m_returned;
96 size_t m_target_repeats;
97 size_t m_current_repeat = 0;
98 size_t m_repeat_index = 0;
101 m_generator(
std::move(generator)),
102 m_target_repeats(repeats)
104 assert(m_target_repeats > 0 &&
"Repeat generator must repeat at least once");
107 T const&
get()
const override {
108 if (m_current_repeat == 0) {
109 m_returned.push_back(m_generator.get());
110 return m_returned.back();
112 return m_returned[m_repeat_index];
122 if (m_current_repeat == 0) {
123 const auto success = m_generator.next();
127 return m_current_repeat < m_target_repeats;
132 if (m_repeat_index == m_returned.size()) {
136 return m_current_repeat < m_target_repeats;
140 template <
typename T>
145 template <
typename T,
typename U,
typename Func>
146 class MapGenerator :
public IGenerator<T> {
148 GeneratorWrapper<U> m_generator;
153 template <
typename F2 = Func>
155 m_generator(
std::move(generator)),
156 m_function(
std::forward<F2>(function)),
157 m_cache(m_function(m_generator.get()))
160 T const&
get()
const override {
164 const auto success = m_generator.next();
166 m_cache = m_function(m_generator.get());
172#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
176 template <
typename Func,
typename U>
177 using MapFunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>;
179 template <
typename Func,
typename U>
183 template <
typename Func,
typename U,
typename T = MapFunctionReturnType<Func, U>>
190 template <
typename T,
typename U,
typename Func>
191 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
192 return GeneratorWrapper<T>(
193 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
197 template <
typename T>
198 class ChunkGenerator final :
public IGenerator<std::vector<T>> {
199 std::vector<T> m_chunk;
201 GeneratorWrapper<T> m_generator;
202 bool m_used_up =
false;
205 m_chunk_size(size), m_generator(
std::move(generator))
207 m_chunk.reserve(m_chunk_size);
208 m_chunk.push_back(m_generator.get());
209 for (
size_t i = 1; i < m_chunk_size; ++i) {
210 if (!m_generator.next()) {
213 m_chunk.push_back(m_generator.get());
216 std::vector<T>
const&
get()
const override {
221 for (
size_t idx = 0; idx < m_chunk_size; ++idx) {
222 if (!m_generator.next()) {
225 m_chunk.push_back(m_generator.get());
231 template <
typename T>
234 pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
ChunkGenerator(size_t size, GeneratorWrapper< T > generator)
std::vector< T > const & get() const override
T const & get() const override
FilterGenerator(P &&pred, GeneratorWrapper< T > &&generator)
MapGenerator(F2 &&function, GeneratorWrapper< U > &&generator)
T const & get() const override
T const & get() const override
RepeatGenerator(size_t repeats, GeneratorWrapper< T > &&generator)
T const & get() const override
TakeGenerator(size_t target, GeneratorWrapper< T > &&generator)
std::unique_ptr< T > make_unique(Args &&... args)
typename std::remove_reference< typename std::remove_cv< typename std::result_of< Func(U)>::type >::type >::type MapFunctionReturnType
GeneratorWrapper< std::vector< T > > chunk(size_t size, GeneratorWrapper< T > &&generator)
GeneratorWrapper< T > take(size_t target, GeneratorWrapper< T > &&generator)
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
void throw_exception(std::exception const &e)
#define T(meth, val, expected)