GCC Code Coverage Report


Directory: ./
File: include/CXXIter/src/op/GenerateFrom.h
Date: 2023-01-04 16:32:12
Exec Total Coverage
Lines: 13 13 100.0%
Functions: 21 21 100.0%
Branches: 15 19 78.9%

Line Branch Exec Source
1 #pragma once
2
3 #ifdef CXXITER_HAS_COROUTINE
4
5 #include "../Common.h"
6 #include "../Generator.h"
7 #include "../util/TraitImpl.h"
8
9 namespace CXXIter {
10
11 // ################################################################################################
12 // GENERATE FROM
13 // ################################################################################################
14
15 template<typename T, typename TItem>
16 concept GeneratorFromFunction = (util::invocable_byvalue<T, TItem> && util::is_template_instance_v<std::invoke_result_t<T, TItem>, Generator>);
17
18 namespace op {
19 /** @private */
20 template<typename TChainInput, typename TGeneratorFn, typename TGenerator>
21 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] GenerateFrom : public IterApi<GenerateFrom<TChainInput, TGeneratorFn, TGenerator>> {
22 friend struct trait::Iterator<GenerateFrom<TChainInput, TGeneratorFn, TGenerator>>;
23 friend struct trait::ExactSizeIterator<GenerateFrom<TChainInput, TGeneratorFn, TGenerator>>;
24 private:
25 TChainInput input;
26 TGeneratorFn generatorFn;
27 std::optional<TGenerator> currentGenerator;
28 public:
29 14 constexpr GenerateFrom(TChainInput&& input, TGeneratorFn& generatorFn) : input(std::move(input)), generatorFn(generatorFn) {}
30 };
31 }
32 // ------------------------------------------------------------------------------------------------
33 /** @private */
34 template<typename TChainInput, typename TGeneratorFn, typename TGenerator>
35 struct trait::Iterator<op::GenerateFrom<TChainInput, TGeneratorFn, TGenerator>> {
36 using ChainInputIterator = trait::Iterator<TChainInput>;
37 using InputItem = typename TChainInput::Item;
38 using InputItemOwned = typename TChainInput::ItemOwned;
39 // CXXIter Interface
40 using Self = op::GenerateFrom<TChainInput, TGeneratorFn, TGenerator>;
41 using Item = typename TGenerator::value_type;
42
43 120 static constexpr inline IterValue<Item> next(Self& self) {
44
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 10 times.
72 while(true) {
45
2/2
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 39 times.
120 if(!self.currentGenerator.has_value()) {
46
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
42 auto item = ChainInputIterator::next(self.input);
47
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 15 times.
42 if(!item.has_value()) { return {}; } // reached end
48
3/5
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 11 times.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
30 self.currentGenerator.emplace(self.generatorFn( std::forward<InputItem>(item.value()) ));
49 }
50
51
3/4
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 53 times.
✓ Branch 5 taken 1 times.
108 auto item = self.currentGenerator.value().next();
52
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 39 times.
106 if(!item.has_value()) {
53 28 self.currentGenerator.reset();
54 28 continue;
55 }
56 78 return item;
57 }
58 }
59 14 static constexpr inline SizeHint sizeHint(const Self& self) { return ChainInputIterator::sizeHint(self.input); }
60 static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); }
61 };
62
63 }
64
65 #endif
66