CXXIter 0.2
Loading...
Searching...
No Matches
Chunked.h
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
11namespace 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 {
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 constexpr Chunked(TChainInput&& input) : input(std::move(input)) {}
33 };
34 }
35 // ------------------------------------------------------------------------------------------------
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 static constexpr inline IterValue<Item> next(Self& self) {
46 if(self.reachedEnd) [[unlikely]] { return {}; }
47 Item chunk;
48 chunk.reserve(CHUNK_SIZE);
49 for(size_t i = 0; i < CHUNK_SIZE; ++i) {
50 auto item = ChainInputIterator::next(self.input);
51 if(!item.has_value()) [[unlikely]] {
52 self.reachedEnd = true;
53 if(chunk.size() == 0) { return {}; } // chunk empty
54 return chunk;
55 } // reached end. Commit chunk if it has items
56 chunk.push_back(std::move( item.value() ));
57 }
58 return chunk;
59 }
60 static constexpr inline SizeHint sizeHint(const Self& self) {
61 SizeHint result = ChainInputIterator::sizeHint(self.input);
62 result.lowerBound = (result.lowerBound / CHUNK_SIZE) + (result.lowerBound % CHUNK_SIZE == 0 ? 0 : 1);
63 if(result.upperBound.has_value()) {
64 result.upperBound.value() = (result.upperBound.value() / CHUNK_SIZE) + (result.upperBound.value() % CHUNK_SIZE == 0 ? 0 : 1);
65 }
66 return result;
67 }
68 static constexpr inline size_t advanceBy(Self& self, size_t n) { return util::advanceByPull(self, n); }
69 };
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}
CXXIter.
Definition: CXXIter.h:48