join_iterator.hpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. //
  2. // join_iterator.hpp
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/7/17.
  6. //
  7. #pragma once
  8. #include <iterator>
  9. #include <utility>
  10. #include <iterator/detail/arrow_proxy.h>
  11. #include <iterator/end_aware_iterator.hpp>
  12. #include <iterator/facade.h>
  13. #include <iterator/iterator_fwd.hpp>
  14. namespace iterator {
  15. template <typename MetaIterator>
  16. class joining_iterator : public facade<joining_iterator<MetaIterator>> {
  17. public:
  18. using join_iter = MetaIterator;
  19. using joinable_type = typename join_iter::value_type;
  20. using iter_type = decltype(std::begin(*std::declval<join_iter>()));
  21. using value_type = typename std::iterator_traits<iter_type>::value_type;
  22. using reference = typename std::iterator_traits<iter_type>::reference;
  23. using pointer = typename std::iterator_traits<iter_type>::pointer;
  24. using difference_type =
  25. typename std::iterator_traits<iter_type>::difference_type;
  26. using iterator_category = std::forward_iterator_tag;
  27. public:
  28. explicit joining_iterator() = default;
  29. template <typename I>
  30. joining_iterator(joining_iterator<I> const & other)
  31. : joiner_(other.join_iterator()), iterator_(other.element_iterator()) {}
  32. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  33. joining_iterator(C && container)
  34. : joining_iterator(end_aware_iterator(std::forward<C>(container))) {}
  35. joining_iterator(end_aware_iterator<join_iter> join)
  36. : joining_iterator(join, {}, true) {}
  37. joining_iterator(end_aware_iterator<join_iter> join,
  38. end_aware_iterator<iter_type> elem, bool update = false)
  39. : joiner_(join), iterator_(elem) {
  40. if (update) { update_iterator(); }
  41. }
  42. void increment() {
  43. if ((iterator_++).at_end()) {
  44. ++joiner_;
  45. update_iterator();
  46. }
  47. }
  48. decltype(auto) dereference() const { return *iterator_; }
  49. bool equal_to(joining_iterator const & other) const {
  50. return joiner_ == other.joiner_ && iterator_ == other.iterator_;
  51. }
  52. end_aware_iterator<join_iter> join_iterator() const { return joiner_; }
  53. end_aware_iterator<iter_type> element_iterator() const { return iterator_; }
  54. private:
  55. void update_iterator() {
  56. while (!joiner_.at_end() && end_aware_iterator(*joiner_).at_end()) {
  57. ++joiner_;
  58. }
  59. if (!joiner_.at_end()) {
  60. cache_ = *joiner_;
  61. iterator_ = end_aware_iterator(cache_.get());
  62. }
  63. }
  64. end_aware_iterator<join_iter> joiner_;
  65. detail::value_proxy<decltype(*std::declval<join_iter>())> cache_;
  66. end_aware_iterator<iter_type> iterator_;
  67. };
  68. template <typename C> joining_iterator(C &&) -> joining_iterator<iter<C>>;
  69. template <typename JI>
  70. joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
  71. template <typename JI, typename IT>
  72. joining_iterator(end_aware_iterator<JI>, end_aware_iterator<IT>)
  73. -> joining_iterator<JI>;
  74. }
  75. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);