herald  2.0.0
ranges.h
1 // Copyright 2021 Herald Project Contributors
2 // SPDX-License-Identifier: Apache-2.0
3 //
4 
5 #ifndef HERALD_RANGES_H
6 #define HERALD_RANGES_H
7 
8 // TODO if def for C++20 support check (so we don't have to roll our own ranges lib)
9 // i.e. map std::views on to herald::analysis::views, otherwise include the following.
10 
14 
15 #include <array>
16 #include <map>
17 #include <variant>
18 #include <vector>
19 #include <cstdint>
20 #include <type_traits>
21 
22 #include "sampling.h"
23 #include "../datatype/date.h"
24 
25 namespace herald {
26 namespace analysis {
27 namespace views {
28 
29 // Note: The following are SAMPLE filters, and only work with Samples
30 struct since {
31  since(herald::datatype::Date after) : from(after) {}
32  ~since() = default;
33 
34  template <typename ValT>
35  bool operator()(const herald::analysis::sampling::Sample<ValT>& s) const {
36  return s.taken > from;
37  }
38 
39 private:
41 };
42 
43 // Note: The following are value filters, and work with Samples and any other type
44 
46 template <typename Pred1,typename Pred2>
47 struct dual_filter {
48  dual_filter(const Pred1 p1, const Pred2 p2) : pred1(p1), pred2(p2) {}
49  ~dual_filter() = default;
50 
51  template <typename VTOther>
52  bool operator()(const VTOther& value) const {
53  return pred1(value) && pred2(value);
54  }
55 
56 private:
57  const Pred1 pred1;
58  const Pred2 pred2;
59 };
60 
61 // Is genericised to...
62 template <typename VT>
63 struct in_range {
64  in_range(const VT min, const VT max) : min(min), max(max) {}
65  ~in_range() = default;
66 
67  template <typename VTOther>
68  bool operator()(const VTOther& value) const {
69  return value >= min && value <= max;
70  }
71 
72 private:
73  const VT min;
74  const VT max;
75 };
76 
77 template <typename VT>
78 struct greater_than {
79  greater_than(const VT min) : min(min) {}
80  ~greater_than() = default;
81 
82  template <typename VTOther>
83  bool operator()(const VTOther& value) const {
84  return value > min;
85  }
86 
87 private:
88  const VT min;
89 };
90 
91 template <typename VT>
92 struct less_than {
93  less_than(const VT max) : max(max) {}
94  ~less_than() = default;
95 
96  template <typename VTOther>
97  bool operator()(const VTOther& value) const {
98  return value < max;
99  }
100 
101 private:
102  const VT max;
103 };
104 
105 // TODO consider clamping modifications as well as in_range filtering
106 
115 template <typename Coll,
116  //typename ValT = typename std::remove_cv<typename Coll::value_type::first_type>::type,
117  typename ValT = typename std::remove_cv<typename Coll::value_type>::type, // works for intrinsic types and complex types
118  typename IterT = typename Coll::iterator,
119  typename SizeT = typename Coll::size_type
120  >
122  using base_iterator = IterT;
123  using base_value_type = ValT;
124  using base_size_type = SizeT;
125 
126  iterator_proxy(Coll& coll) : coll(coll), iter(std::move(std::begin(coll))), endIter(std::move(std::end(coll))) {}
127  iterator_proxy(iterator_proxy&& other) : coll(other.coll), iter(std::move(other.iter)), endIter(std::move(other.endIter)) {}
128  iterator_proxy(const iterator_proxy& other) : coll(other.coll), iter(other.iter), endIter(other.endIter) {}
129  ~iterator_proxy() = default;
130 
131  auto operator*() -> const ValT& {
132  return *iter;
133  }
134 
137  ++iter;
138  return *this; // reference to instance
139  }
140 
141  // postfix operator
143  iterator_proxy<Coll> cp = *this; // copy of instance
144  ++(*this);
145  return cp;
146  }
147 
148  bool operator==(IterT otherIter) const {
149  return iter == otherIter;
150  }
151 
152  bool operator!=(IterT otherIter) const {
153  return iter != otherIter;
154  }
155 
156  friend bool operator!=(IterT otherIter,iterator_proxy<Coll> thisIter) {
157  return otherIter != thisIter.iter;
158  }
159 
160  friend bool operator==(IterT otherIter,iterator_proxy<Coll> thisIter) {
161  return otherIter == thisIter.iter;
162  }
163 
164  IterT& wrapped() {
165  return iter;
166  }
167 
168  IterT& end() {
169  return endIter;
170  }
171 
172  bool ended() {
173  return endIter == iter;
174  }
175 
176  Coll& collection() const {
177  return coll;
178  }
179 
180 private:
181  Coll& coll;
182  IterT iter;
183  IterT endIter;
184 };
185 
191 template <typename Pred>
192 struct filter_fn {
193  filter_fn(const Pred pred) : pred(pred) {}
194  ~filter_fn() = default;
195 
196  template <typename ValT>
197  auto operator()(const ValT& val) -> bool {
198  return pred(val);
199  }
200 
201  const Pred predicate() const {
202  return pred;
203  }
204 
205 private:
206  const Pred pred;
207 };
208 
211 template <typename IterProxyT,
212  typename BaseValT = typename IterProxyT::base_value_type,
213  typename BaseIterT = typename IterProxyT::base_iterator,
214  typename BaseSizeT = typename IterProxyT::base_size_type>
215 struct view {
216  // Make this look like an STL collection (so filter<Coll,Pred> works with a view)
217  using value_type = BaseValT;
218  using iterator = BaseIterT;
219  using size_type = BaseSizeT;
220 
221  using is_proxy = std::true_type;
222 
223  view(IterProxyT srcIter) : source(std::forward<IterProxyT>(srcIter)) {} // TAKE OWNERSHIP
224  ~view() = default;
225 
226  auto begin() -> IterProxyT {
227  return source;
228  }
229 
230  auto end() -> BaseIterT {
231  return source.end();
232  }
233 
234  // auto latest() -> BaseValT {
235  // //return source.latest();
236  // return *(source.end() - 1);
237  // }
238  Date latest() {
239  return (*(source.end() - 1)).taken;
240  }
241 
242  template <typename IterT>
243  bool operator==(const IterT& other) {
244  return other == source;
245  }
246 
247  template <typename IterT>
248  bool operator!=(const IterT& other) {
249  return other != source;
250  }
251 
252  auto size() -> BaseSizeT {
253  // return source.size(); // this is the UNFILTERED size
254  BaseSizeT sz = 0;
255  auto iter = source; // copy the iterator so as not to alter its state
256  auto end = source.end(); // copy the iterator so as not to alter its state
257  while (iter != end) {
258  ++sz;
259  ++iter;
260  }
261  // minus one as we don't want the distance to end() but the last element the 1 before it
262  return sz;
263  // return std::distance(source.wrapped(),source.end() - 1);
264  }
265 
266  auto operator[](BaseSizeT position) -> BaseValT {
267  return *(source + position);
268  }
269 
270 private:
271  IterProxyT source;
272 };
273 
282 template <typename Coll,
283  typename Pred,
284  // typename ValT = typename std::remove_cv<typename Coll::value_type::first_type>::type,
285  typename ValT = typename std::remove_cv<typename Coll::value_type>::type, // works for intrinsic types and complex types
286  typename IterT = typename Coll::iterator,
287  typename SizeT = typename Coll::size_type
288  >
290  using base_iterator = IterT;
291  using base_coll_type = Coll; // for chaining
292  using base_pred_type = Pred; // for chaining
293  using base_value_type = ValT;
294  using base_size_type = SizeT;
295 
296  using value_type = ValT;
297  using iterator = IterT;
298  using size_type = SizeT;
299  // using difference_type = typename Coll::difference_type;
300 
301  using is_proxy = std::true_type;
302 
303  filtered_iterator_proxy(Coll& coll, Pred pred) : coll(coll), iter(std::move(std::begin(coll))), endIter(std::move(std::end(coll))), filter(pred) {
304  // move forward to the first match (or end)
305  moveToFirst();
306  }
307 
308  // chaining ctor
309  // filtered_iterator_proxy(filtered_iterator_proxy&& other, Pred pred) : iter(std::move(other.iter)), endIter(std::move(other.endIter)), filter(dual_filter(other.filter,pred)) {}
310  filtered_iterator_proxy(filtered_iterator_proxy&& other) : coll(other.coll), iter(std::move(other.iter)), endIter(std::move(other.endIter)), filter(other.filter) {}
311  filtered_iterator_proxy(const filtered_iterator_proxy& other) : coll(other.coll), iter(other.iter), endIter(other.endIter), filter(other.filter) {}
312  ~filtered_iterator_proxy() = default;
313 
314  auto operator*() -> const ValT& {
315  return *iter;
316  }
317 
320  // move forward until we get a match (or end)
321  moveToNext();
322  return *this;
323  }
324 
325  // postfix operator
327  filtered_iterator_proxy<Coll,Pred> cp = *this; // copy of instance
328  ++(*this);
329  return cp;
330  }
331 
332  filtered_iterator_proxy<Coll,Pred> operator+(int by) {
333  filtered_iterator_proxy<Coll,Pred> cp = *this; // copy of instance
334  for (int i = 0;i < by;++i) {
335  ++cp;
336  }
337  return cp;
338  }
339 
340  bool operator==(IterT otherIter) const {
341  return iter == otherIter;
342  }
343 
344  bool operator!=(IterT otherIter) const {
345  return iter != otherIter;
346  }
347 
348  friend bool operator!=(IterT otherIter,filtered_iterator_proxy<Coll,Pred> thisIter) {
349  return otherIter != thisIter.iter;
350  }
351 
352  friend bool operator==(IterT otherIter,filtered_iterator_proxy<Coll,Pred> thisIter) {
353  return otherIter == thisIter.iter;
354  }
355 
356  IterT& wrapped() {
357  return iter;
358  }
359 
360  IterT& end() {
361  return endIter;
362  }
363 
364  bool ended() {
365  return endIter == iter;
366  }
367 
368  Coll& collection() const {
369  return coll;
370  }
371 
372  Pred predicate() const {
373  return filter.predicate();
374  }
375 
376 private:
377  Coll& coll;
378  IterT iter;
379  IterT endIter;
380  filter_fn<Pred> filter;
381 
382  // Need this function so as not to incorrectly always filter the first value in the underlying proxy
383  void moveToFirst() {
384  while (endIter != iter && !filter(*iter)) {
385  ++iter;
386  };
387  }
388 
389  void moveToNext() {
390  if (endIter == iter) return; // guard
391  do {
392  ++iter;
393  } while (endIter != iter && !filter(*iter));
394  }
395 };
396 
403 template <typename Pred>
404 struct filter {
405 public:
406  filter(const Pred& pred) : pred(pred) {}
407  ~filter() = default;
408 
409  template <typename Coll>
410  auto operator()(Coll& c) -> filtered_iterator_proxy<Coll,Pred> {
411  return filtered_iterator_proxy<Coll,Pred>(c,pred);
412  }
413 
414  template <typename OtherColl, typename OtherPred> // first argument must be l-value below
416  return filtered_iterator_proxy<OtherColl,dual_filter<OtherPred,Pred>>(c.collection(),dual_filter(c.predicate(),pred.pred));
417  }
418 
419  template <typename Coll>
420  friend auto operator|(Coll& c,filter<Pred> pred) -> filtered_iterator_proxy<Coll,Pred> {
421  return filtered_iterator_proxy<Coll,Pred>(c,pred.pred);
422  }
423 
424 private:
425  Pred pred;
426 };
427 
430 struct to_view {
431  to_view() = default;
432  ~to_view() = default;
433 
434  // convert something with a proxy (likely a filtered iterator proxy) into a view
435  template <typename IterProxyT>
436  friend auto operator|(IterProxyT proxy,to_view view) -> herald::analysis::views::view<IterProxyT> {
438  }
439 
441  // template <typename Coll,
442  // typename IterProxyT = iterator_proxy<Coll>,
443  // std::enable_if_t<!std::is_same_v<Coll,iterator_proxy> && !std::is_same_v<Coll,filtered_iterator_proxy>, bool> = true
444  // >
445  // friend auto operator|(Coll coll,to_view view) -> herald::analysis::views::view<IterProxyT> {
446  // return herald::analysis::views::view<IterProxyT>(iterator_proxy<Coll>(coll));
447  // }
448 
449  template <typename SampleT,
450  std::size_t ListSize,
452  >
455  }
456 };
457 
458 } // end namespace views
459 }
460 }
461 
462 #endif
Definition: date.h:18
Acts as a non-global memory arena for arbitrary classes.
Definition: aggregates.h:15
The Sample taken from an object with ID of type SampledID.
Definition: sampling.h:28
Definition: sampling.h:102
dual or chained filter
Definition: ranges.h:47
Definition: ranges.h:192
Definition: ranges.h:404
filtered_iterator_proxy< Coll, Pred > & operator++()
prefix operator
Definition: ranges.h:319
Definition: ranges.h:63
iterator_proxy< Coll > & operator++()
prefix operator
Definition: ranges.h:136
Definition: ranges.h:92
Definition: ranges.h:30
Definition: ranges.h:430
friend auto operator|(herald::analysis::sampling::SampleList< SampleT, ListSize > &coll, to_view view) -> herald::analysis::views::view< IterProxyT >
Convert an unfiltered source collection into a view.
Definition: ranges.h:453
Definition: ranges.h:215