CPARK 1.0
A light-weighted, distributed computing framework for C++ that offers a fast and general-purpose large data processing solution.
Loading...
Searching...
No Matches
merged_view.h
1#ifndef CPARK_MERGED_VIEW_H
2#define CPARK_MERGED_VIEW_H
3
4#include <concepts>
5#include <ranges>
6#include <vector>
7
8namespace cpark {
9
10namespace concepts {
11template <typename R>
12concept RangeOfView =
13 std::ranges::forward_range<R> && std::ranges::view<std::ranges::range_value_t<R>>;
14} // namespace concepts
15
21template <concepts::RangeOfView R>
22class MergedSameView : public std::ranges::view_interface<MergedSameView<R>> {
23public:
24 using ViewType = std::ranges::range_value_t<R>;
25
30 class Iterator : public std::forward_iterator_tag {
31 public:
32 using difference_type = std::ptrdiff_t;
33 using value_type = std::ranges::range_value_t<ViewType>;
34
35 public:
42 Iterator(std::ranges::iterator_t<const ViewType> start_iterator, std::vector<ViewType>* views,
43 std::vector<ViewType>::size_type start_index)
44 : inner_iterator_{std::move(start_iterator)}, views_{views}, index_of_view_{start_index} {
45 // Move the inner iterator to the first element which is not an 'end'.
46 while (index_of_view_ < std::ranges::size(*views_) &&
47 inner_iterator_ == std::ranges::end((*views_)[index_of_view_])) {
48 ++index_of_view_;
49 if (index_of_view_ < std::ranges::size(*views_)) {
50 inner_iterator_ = std::ranges::begin((*views_)[index_of_view_]);
51 }
52 }
53 }
54
55 Iterator() = default;
56
57 value_type operator*() const { return *inner_iterator_; }
58
59 Iterator& operator++() {
60 ++inner_iterator_;
61 // Move the inner iterator to the first element which is not an 'end'.
62 while (index_of_view_ < std::ranges::size(*views_) &&
63 inner_iterator_ == std::ranges::end((*views_)[index_of_view_])) {
64 ++index_of_view_;
65 if (index_of_view_ < std::ranges::size(*views_)) {
66 inner_iterator_ = std::ranges::begin((*views_)[index_of_view_]);
67 }
68 }
69 return *this;
70 }
71
72 Iterator operator++(int) {
73 auto old = *this;
74 ++(*this);
75 return old;
76 }
77
83 bool operator==(const Iterator& other) const {
84 if (isEnd() && other.isEnd()) {
85 return true;
86 }
87 return views_ == other.views_ && inner_iterator_ == other.inner_iterator_ &&
88 index_of_view_ == other.index_of_view_;
89 }
90
91 bool operator!=(const Iterator& other) const { return !(*this == other); }
92
93 Iterator& operator--() requires std::ranges::bidirectional_range<ViewType> {}
94
95 private:
96 bool isEnd() const { return !(index_of_view_ < std::ranges::size(*views_)); }
97
98 private:
99 // Iterator pointing to the current element.
100 std::ranges::iterator_t<const ViewType> inner_iterator_{};
101 // The sequence of views to be combined.
102 std::vector<ViewType>* views_{nullptr};
103 // Index of the view that has the current `inner_iterator_`.
104 std::vector<ViewType>::size_type index_of_view_{0};
105 };
106
107public:
111 explicit MergedSameView(const R& views)
112 : views_{std::ranges::begin(views), std::ranges::end(views)} {}
113
115 constexpr auto begin() const {
116 auto start_iterator = std::ranges::empty(views_) ? std::ranges::iterator_t<ViewType>{}
117 : std::ranges::begin(views_.front());
118 return Iterator{start_iterator, const_cast<std::vector<ViewType>*>(&views_),
119 static_cast<std::vector<ViewType>::size_type>(0)};
120 }
121
123 constexpr auto end() const {
124 return Iterator{std::ranges::iterator_t<ViewType>{},
125 const_cast<std::vector<ViewType>*>(&views_), std::ranges::size(views_)};
126 }
127
128private:
129 std::vector<ViewType> views_;
130};
131
136template <std::ranges::view V1, std::ranges::view V2>
137requires std::same_as<std::ranges::range_value_t<V1>,
138 std::ranges::range_value_t<V2>> class MergedTwoDiffView
139 : public std::ranges::view_interface<MergedTwoDiffView<V1, V2>> {
140public:
144 class Iterator : public std::forward_iterator_tag {
145 public:
146 using difference_type = std::ptrdiff_t;
147 using value_type = std::ranges::range_value_t<V1>;
148
149 private:
150 // Types of the iterators of the two original views.
151 using OriginalIterator1 = std::ranges::iterator_t<const V1>;
152 using OriginalIterator2 = std::ranges::iterator_t<const V2>;
153
154 public:
164 template <typename Iter>
166 : hold1_{if_hold1}, view1_{view1}, view2_{view2} {
167 // If two inner iterator types are the same, use hold1() to determine which iterator to be
168 // assigned.
169 if constexpr (std::same_as<OriginalIterator1, OriginalIterator2>) {
170 if (hold1()) {
171 get1() = iterator;
172 } else {
173 get2() = iterator;
174 }
175 } else {
176 if constexpr (std::convertible_to<Iter, OriginalIterator1>) {
177 get1() = iterator;
178 } else {
179 get2() = iterator;
180 }
181 }
182
183 if (hold1() && get1() == std::ranges::end(*view1_)) {
184 get2() = std::ranges::begin(*view2_);
185 hold1_ = false;
186 }
187 }
188
189 Iterator() = default;
190
191 value_type operator*() const { return hold1() ? *get1() : *get2(); }
192
193 Iterator& operator++() {
194 if (hold1())
195 ++get1();
196 else
197 ++get2();
198 if (hold1() && get1() == std::ranges::end(*view1_)) {
199 get2() = std::ranges::begin(*view2_);
200 hold1_ = false;
201 }
202 return *this;
203 }
204
205 Iterator operator++(int) {
206 auto old = *this;
207 ++(*this);
208 return old;
209 }
210
211 bool operator==(const Iterator& other) const {
212 return (hold1() && other.hold1() && get1() == other.get1()) ||
213 (hold2() && other.hold2() && get2() == other.get2());
214 }
215
216 bool operator!=(const Iterator& other) const { return !(*this == other); }
217
218 private:
219 bool hold1() const { return hold1_; }
220 decltype(auto) get1() { return (inner_iterator1_); }
221 decltype(auto) get1() const { return (inner_iterator1_); }
222
223 bool hold2() const { return !hold1_; }
224 decltype(auto) get2() { return (inner_iterator2_); }
225 decltype(auto) get2() const { return (inner_iterator2_); }
226
227 private:
228 // In case OriginalIterator1 and OriginalIterator2 are same type, std::variant can not be used.
229 OriginalIterator1 inner_iterator1_;
230 OriginalIterator2 inner_iterator2_;
231 bool hold1_{true};
232 V1* view1_{nullptr};
233 V2* view2_{nullptr};
234 };
235
236public:
240 MergedTwoDiffView(V1 view1, V2 view2) : view1_{std::move(view1)}, view2_{std::move(view2)} {}
241
242 MergedTwoDiffView() = default;
243
245 constexpr auto begin() const {
246 return Iterator{std::ranges::begin(view1_), const_cast<V1*>(&view1_), const_cast<V2*>(&view2_),
247 true};
248 }
249
251 constexpr auto end() const {
252 return Iterator{std::ranges::end(view2_), const_cast<V1*>(&view1_), const_cast<V2*>(&view2_),
253 false};
254 }
255
256private:
257 V1 view1_;
258 V2 view2_;
259};
260
261template <std::ranges::view FirstView>
262auto MergedDiffView(const FirstView& view) {
263 return view;
264}
265
267template <std::ranges::view FirstView, std::ranges::view... OtherViews>
268auto MergedDiffView(const FirstView& first_view, const OtherViews&... other_views) {
269 return MergedTwoDiffView{first_view, MergedDiffView(other_views...)};
270}
271
272} // namespace cpark
273
274#endif // CPARK_MERGED_VIEW_H
Definition base_rdd.h:94
Definition merged_view.h:30
Iterator(std::ranges::iterator_t< const ViewType > start_iterator, std::vector< ViewType > *views, std::vector< ViewType >::size_type start_index)
Definition merged_view.h:42
bool operator==(const Iterator &other) const
Definition merged_view.h:83
Definition merged_view.h:22
constexpr auto end() const
Definition merged_view.h:123
constexpr auto begin() const
Definition merged_view.h:115
MergedSameView(const R &views)
Definition merged_view.h:111
Definition merged_view.h:144
Iterator(Iter iterator, V1 *view1, V2 *view2, bool if_hold1)
Definition merged_view.h:165
Definition merged_view.h:139
constexpr auto begin() const
Definition merged_view.h:245
constexpr auto end() const
Definition merged_view.h:251
MergedTwoDiffView(V1 view1, V2 view2)
Definition merged_view.h:240
Definition merged_view.h:12