GCC Code Coverage Report


Directory: ./
File: include/CXXIter/src/op/Chunked.h
Date: 2023-01-04 16:32:12
Exec Total Coverage
Lines: 20 20 100.0%
Functions: 5 5 100.0%
Branches: 12 16 75.0%

Line Branch Exec Source
1 #pragma once
2
3 #include <array>
4 #include <cstdlib>
5 #include <utility>
6 #include <type_traits>
7
8 #include "../Common.h"
9 #include "../util/TraitImpl.h"
10
11 namespace CXXIter {
12
13 template<typename TItem, const size_t CHUNK_SIZE>
14 using DynamicChunk = std::conditional_t<
15 std::is_reference_v<TItem>,
16 std::vector<std::reference_wrapper<TItem>>,
17 std::vector<TItem>>;
18
19 // ################################################################################################
20 // CHUNKED
21 // ################################################################################################
22 namespace op {
23 /** @private */
24 template<typename TChainInput, const size_t CHUNK_SIZE>
25 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] Chunked : public IterApi<Chunked<TChainInput, CHUNK_SIZE>> {
26 friend struct trait::Iterator<Chunked<TChainInput, CHUNK_SIZE>>;
27 friend struct trait::ExactSizeIterator<Chunked<TChainInput, CHUNK_SIZE>>;
28 private:
29 TChainInput input;
30 bool reachedEnd = false;
31 public:
32 14 constexpr Chunked(TChainInput&& input) : input(std::move(input)) {}
33 };
34 }
35 // ------------------------------------------------------------------------------------------------
36 /** @private */
37 template<typename TChainInput, const size_t CHUNK_SIZE>
38 struct trait::Iterator<op::Chunked<TChainInput, CHUNK_SIZE>> {
39 using ChainInputIterator = trait::Iterator<TChainInput>;
40 using InputItem = typename TChainInput::Item;
41 // CXXIter Interface
42 using Self = op::Chunked<TChainInput, CHUNK_SIZE>;
43 using Item = DynamicChunk<InputItem, CHUNK_SIZE>;
44
45 22 static constexpr inline IterValue<Item> next(Self& self) {
46
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
22 if(self.reachedEnd) [[unlikely]] { return {}; }
47 18 Item chunk;
48
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
18 chunk.reserve(CHUNK_SIZE);
49
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 6 times.
68 for(size_t i = 0; i < CHUNK_SIZE; ++i) {
50
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
56 auto item = ChainInputIterator::next(self.input);
51
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 25 times.
56 if(!item.has_value()) [[unlikely]] {
52 6 self.reachedEnd = true;
53
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
10 if(chunk.size() == 0) { return {}; } // chunk empty
54 4 return chunk;
55 } // reached end. Commit chunk if it has items
56
2/4
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 25 times.
✗ Branch 6 not taken.
50 chunk.push_back(std::move( item.value() ));
57 }
58 12 return chunk;
59 18 }
60 7 static constexpr inline SizeHint sizeHint(const Self& self) {
61 7 SizeHint result = ChainInputIterator::sizeHint(self.input);
62 7 result.lowerBound = (result.lowerBound / CHUNK_SIZE) + (result.lowerBound % CHUNK_SIZE == 0 ? 0 : 1);
63 7 if(result.upperBound.has_value()) {
64 7 result.upperBound.value() = (result.upperBound.value() / CHUNK_SIZE) + (result.upperBound.value() % CHUNK_SIZE == 0 ? 0 : 1);
65 }
66 7 return result;
67 }
68 static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); }
69 };
70 /** @private */
71 template<CXXIterExactSizeIterator TChainInput, const size_t CHUNK_SIZE>
72 struct trait::ExactSizeIterator<op::Chunked<TChainInput, CHUNK_SIZE>> {
73 static constexpr inline size_t size(const op::Chunked<TChainInput, CHUNK_SIZE>& self) {
74 return trait::ExactSizeIterator<TChainInput>::size(self.input) / CHUNK_SIZE;
75 }
76 };
77
78 }
79