join_iterator.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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::joining {
  15. template <typename Iter, typename = void>
  16. class iterator {
  17. protected:
  18. using inner_t = decltype(*std::declval<Iter>());
  19. protected:
  20. iterator() = default;
  21. template <typename I>
  22. iterator(iterator<I> const & other)
  23. : iterator(other.join_iterator(), other.element_iterator()) {}
  24. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  25. iterator(C && container)
  26. : iterator(end_aware_iterator(std::forward<C>(container))) {}
  27. iterator(end_aware_iterator<Iter> join) : iterator(join, {}, true) {}
  28. iterator(end_aware_iterator<Iter> join,
  29. end_aware_iterator<iter<inner_t>> elem, bool update = false)
  30. : joiner_(join), element_(elem) {
  31. if (update) { update_iterator(); }
  32. }
  33. void update_iterator() {
  34. while (!joiner_.at_end() &&
  35. (element_ = end_aware_iterator(*joiner_)).at_end()) {
  36. ++joiner_;
  37. }
  38. }
  39. protected:
  40. end_aware_iterator<Iter> joiner_;
  41. end_aware_iterator<iter<inner_t>> element_;
  42. };
  43. template <typename Iter>
  44. class iterator<Iter, std::enable_if_t<detail::is_rvalue_iterator_v<Iter>>> {
  45. protected:
  46. using inner_t = decltype(*std::declval<Iter>());
  47. protected:
  48. iterator() = default;
  49. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  50. iterator(C && container) : joiner_(std::forward<C>(container)) {
  51. update_iterator();
  52. }
  53. iterator(end_aware_iterator<Iter> join) : joiner_(join) {
  54. update_iterator();
  55. }
  56. iterator(iterator const &other) { *this = other; }
  57. iterator(iterator &&other) { *this = std::move(other); }
  58. iterator &operator=(iterator const &other) {
  59. joiner_ = other.joiner_;
  60. sync(std::distance(end_aware_iterator(cache_.get()), element_));
  61. return *this;
  62. }
  63. iterator &operator=(iterator &&other) {
  64. joiner_ = std::move(joiner_);
  65. sync(std::distance(end_aware_iterator(cache_.get()), element_));
  66. return *this;
  67. }
  68. void update_iterator() {
  69. while (!joiner_.at_end() && sync().at_end()) {
  70. ++joiner_;
  71. }
  72. }
  73. private:
  74. end_aware_iterator<iter<inner_t>> const & sync(size_t n = 0) {
  75. if (joiner_.at_end()) { return element_ = {}; }
  76. cache_ = *joiner_;
  77. element_ = end_aware_iterator(cache_.get());
  78. std::advance(element_, n);
  79. return element_;
  80. }
  81. protected:
  82. end_aware_iterator<Iter> joiner_;
  83. detail::value_proxy<decltype(*std::declval<Iter>())> cache_;
  84. end_aware_iterator<iter<inner_t>> element_;
  85. };
  86. }
  87. namespace iterator {
  88. template <typename Iter>
  89. class joining_iterator : public facade<joining_iterator<Iter>>, public joining::iterator<Iter> {
  90. public:
  91. using super_t = joining::iterator<Iter>;
  92. public:
  93. using super_t::super_t;
  94. template <typename C, typename = std::enable_if_t<detail::is_container_v<C>>>
  95. joining_iterator(C && container) : super_t(std::forward<C>(container)) {}
  96. joining_iterator(end_aware_iterator<Iter> join) : super_t(join) {}
  97. void increment() {
  98. if ((++super_t::element_).at_end()) {
  99. ++super_t::joiner_;
  100. super_t::update_iterator();
  101. }
  102. }
  103. decltype(auto) dereference() const { return *super_t::element_; }
  104. bool equal_to(joining_iterator const & other) const {
  105. return join_iterator() == other.join_iterator() &&
  106. element_iterator() == other.element_iterator();
  107. }
  108. auto const &join_iterator() const { return super_t::joiner_; }
  109. auto const &element_iterator() const { return super_t::element_; }
  110. };
  111. template <typename C> joining_iterator(C &&) -> joining_iterator<iter<C>>;
  112. template <typename JI>
  113. joining_iterator(end_aware_iterator<JI>) -> joining_iterator<JI>;
  114. }
  115. MAKE_ITERATOR_FACADE_TYPEDEFS_T(::iterator::joining_iterator);