join_iterator.hpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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 "end_aware_iterator.hpp"
  10. template <typename MetaIterator>
  11. class joining_iterator {
  12. public:
  13. using join_iter = MetaIterator;
  14. using joinable_type = typename join_iter::value_type;
  15. using iter_type = decltype(std::begin(*std::declval<MetaIterator>()));
  16. using value_type = typename std::iterator_traits<iter_type>::value_type;
  17. using reference = typename std::iterator_traits<iter_type>::reference;
  18. using pointer = typename std::iterator_traits<iter_type>::pointer;
  19. using difference_type = typename std::iterator_traits<iter_type>::difference_type;
  20. using iterator_category = std::forward_iterator_tag;
  21. public:
  22. explicit joining_iterator( )
  23. : joiner_({}, {}), iterator_({}, {}) {
  24. }
  25. template <typename I>
  26. joining_iterator( joining_iterator<I> const & other )
  27. : joiner_(other.join_iterator()), iterator_(other.element_iterator()) {
  28. }
  29. joining_iterator( join_iter start, join_iter end )
  30. : joiner_(start, end), iterator_({}, {}) {
  31. update_iterator();
  32. }
  33. joining_iterator( join_iter start, join_iter end, iter_type lstart, iter_type lend, bool update = false )
  34. : joiner_(start, end), iterator_(lstart, lend) {
  35. if ( update ) { update_iterator(); }
  36. }
  37. joining_iterator & operator++() {
  38. if ( (++iterator_).done() ) {
  39. ++joiner_;
  40. update_iterator();
  41. }
  42. return *this;
  43. }
  44. joining_iterator operator++(int) {
  45. joining_iterator tmp{*this};
  46. operator++();
  47. return tmp;
  48. }
  49. reference operator*() { return iterator_.operator*(); }
  50. pointer operator->() { return iterator_.operator->(); }
  51. bool operator==(joining_iterator const & other) const {
  52. return joiner_ == other.joiner_ && ((joiner_.done() && other.joiner_.done()) ||
  53. iterator_ == other.iterator_);
  54. }
  55. bool operator!=(joining_iterator const & other) {
  56. return !(operator==(other));
  57. }
  58. end_aware_iterator<join_iter> join_iterator() const { return joiner_; }
  59. end_aware_iterator<iter_type> element_iterator() const { return iterator_; }
  60. private:
  61. void update_iterator() {
  62. while ( !joiner_.done() && std::begin(*joiner_) == std::end(*joiner_) ) {
  63. ++joiner_;
  64. }
  65. if ( !joiner_.done() ) {
  66. iterator_ = { std::begin(*joiner_), std::end(*joiner_) };
  67. }
  68. }
  69. end_aware_iterator<join_iter> joiner_;
  70. end_aware_iterator<iter_type> iterator_;
  71. };