GCC Code Coverage Report


Directory: ./
File: include/CXXIter/src/op/FlatMap.h
Date: 2023-01-04 16:32:12
Exec Total Coverage
Lines: 15 15 100.0%
Functions: 12 12 100.0%
Branches: 15 22 68.2%

Line Branch Exec Source
1 #pragma once
2
3 #include <utility>
4 #include <optional>
5
6 #include "../Common.h"
7 #include "../sources/ContainerSources.h"
8 #include "../util/TraitImpl.h"
9
10 namespace CXXIter {
11
12 // ################################################################################################
13 // FLATMAP
14 // ################################################################################################
15 namespace op {
16 /** @private */
17 template<typename TChainInput, typename TFlatMapFn, typename TItemContainer>
18 requires (!std::is_reference_v<TItemContainer>)
19 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] FlatMap : public IterApi<FlatMap<TChainInput, TFlatMapFn, TItemContainer>> {
20 friend struct trait::Iterator<FlatMap<TChainInput, TFlatMapFn, TItemContainer>>;
21 private:
22 TChainInput input;
23 std::optional<SrcMov<TItemContainer>> current;
24 TFlatMapFn mapFn;
25 public:
26 8 constexpr FlatMap(TChainInput&& input, TFlatMapFn mapFn) : input(std::move(input)), mapFn(mapFn) {}
27 };
28 }
29 // ------------------------------------------------------------------------------------------------
30 /** @private */
31 template<typename TChainInput, typename TFlatMapFn, typename TItemContainer>
32 struct trait::Iterator<op::FlatMap<TChainInput, TFlatMapFn, TItemContainer>> {
33 using NestedChainIterator = trait::Iterator<SrcMov<TItemContainer>>;
34 using ChainInputIterator = trait::Iterator<TChainInput>;
35 using InputItem = typename ChainInputIterator::Item;
36 // CXXIter Interface
37 using Self = op::FlatMap<TChainInput, TFlatMapFn, TItemContainer>;
38 using Item = typename TItemContainer::value_type;
39
40 48 static constexpr inline IterValue<Item> next(Self& self) {
41 11 while(true) {
42
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 22 times.
48 if(!self.current) { // pull new container from the outer iterator
43
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
16 auto item = ChainInputIterator::next(self.input);
44
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7 times.
16 if(!item.has_value()) [[unlikely]] { return {}; } // end of iteration
45
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
11 self.current = SrcMov(std::move(
46
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
11 self.mapFn(std::forward<InputItem>( item.value() ))
47 ));
48
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 3 times.
16 }
49
50 // if the outer iterator yielded a container, take from it until we reach the end
51
1/2
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
43 auto item = NestedChainIterator::next(*self.current);
52
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 7 times.
43 if(item.has_value()) [[likely]] { // inner yielded a usable item
53
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
32 return item.value();
54 11 } else [[unlikely]] {
55 11 self.current.reset(); // inner container ended, unset current cache
56 }
57 }
58 }
59 7 static constexpr inline SizeHint sizeHint(const Self&) { return SizeHint(); }
60 static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); }
61 };
62
63 }
64