CXXIter 0.2
Loading...
Searching...
No Matches
Chainer.h
1#pragma once
2
3#include <cstdlib>
4#include <utility>
5
6#include "../Common.h"
7
8namespace CXXIter {
9
10 // ################################################################################################
11 // CHAINER
12 // ################################################################################################
13 namespace op {
15 template<typename TChainInput1, typename TChainInput2>
16 class [[nodiscard(CXXITER_CHAINER_NODISCARD_WARNING)]] Chainer : public IterApi<Chainer<TChainInput1, TChainInput2>> {
17 friend struct trait::Iterator<Chainer<TChainInput1, TChainInput2>>;
18 friend struct trait::DoubleEndedIterator<Chainer<TChainInput1, TChainInput2>>;
19 friend struct trait::ExactSizeIterator<Chainer<TChainInput1, TChainInput2>>;
20 private:
21 TChainInput1 input1;
22 TChainInput2 input2;
23 bool input1Ended = false;
24 bool input2Ended = false;
25 public:
26 constexpr Chainer(TChainInput1&& input1, TChainInput2 input2) : input1(std::move(input1)), input2(std::move(input2)) {}
27 };
28 }
29 // ------------------------------------------------------------------------------------------------
31 template<typename TChainInput1, typename TChainInput2>
32 struct trait::Iterator<op::Chainer<TChainInput1, TChainInput2>> {
33 using ChainInputIterator1 = trait::Iterator<TChainInput1>;
34 using ChainInputIterator2 = trait::Iterator<TChainInput2>;
35 using InputItem = typename trait::Iterator<TChainInput1>::Item;
36 // CXXIter Interface
37 using Self = op::Chainer<TChainInput1, TChainInput2>;
38 using Item = InputItem;
39
40 static constexpr inline IterValue<Item> next(Self& self) {
41 while(true) {
42 if(self.input1Ended == false) {
43 auto item = ChainInputIterator1::next(self.input1);
44 if(!item.has_value()) [[unlikely]] {
45 self.input1Ended = true;
46 continue;
47 }
48 return item;
49 } else {
50 auto item = ChainInputIterator2::next(self.input2);
51 if(!item.has_value()) [[unlikely]] { self.input2Ended = true; }
52 return item;
53 }
54 }
55 }
56 static constexpr inline SizeHint sizeHint(const Self& self) {
57 SizeHint result = ChainInputIterator1::sizeHint(self.input1);
58 result.add(ChainInputIterator2::sizeHint(self.input2));
59 return result;
60 }
61 static constexpr inline size_t advanceBy(Self& self, size_t n) {
62 size_t skipped = 0;
63 if(!self.input1Ended) {
64 skipped += ChainInputIterator1::advanceBy(self.input1, n);
65 }
66 if(!self.input2Ended) {
67 skipped += ChainInputIterator2::advanceBy(self.input2, (n - skipped));
68 }
69 return skipped;
70 }
71 };
73 template<CXXIterDoubleEndedIterator TChainInput1, CXXIterDoubleEndedIterator TChainInput2>
74 struct trait::DoubleEndedIterator<op::Chainer<TChainInput1, TChainInput2>> {
75 using ChainInputIterator1 = trait::DoubleEndedIterator<TChainInput1>;
76 using ChainInputIterator2 = trait::DoubleEndedIterator<TChainInput2>;
77 using InputItem = typename trait::Iterator<TChainInput1>::Item;
78 // CXXIter Interface
79 using Self = op::Chainer<TChainInput1, TChainInput2>;
80 using Item = InputItem;
81
82 static constexpr inline IterValue<Item> nextBack(Self& self) {
83 while(true) {
84 if(self.input2Ended == false) {
85 auto item = ChainInputIterator2::nextBack(self.input2);
86 if(!item.has_value()) [[unlikely]] {
87 self.input2Ended = true;
88 continue;
89 }
90 return item;
91 } else {
92 auto item = ChainInputIterator1::nextBack(self.input1);
93 if(!item.has_value()) [[unlikely]] { self.input1Ended = true; }
94 return item;
95 }
96 }
97 }
98 };
100 template<CXXIterExactSizeIterator TChainInput1, CXXIterExactSizeIterator TChainInput2>
101 struct trait::ExactSizeIterator<op::Chainer<TChainInput1, TChainInput2>> {
102 static constexpr inline size_t size(const op::Chainer<TChainInput1, TChainInput2>& self) {
103 return trait::Iterator<op::Chainer<TChainInput1, TChainInput2>>::sizeHint(self).lowerBound;
104 }
105 };
106
107}
CXXIter.
Definition: CXXIter.h:48