join_iterator.hpp 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. //
  2. // join_iterator.hpp
  3. // iterator
  4. //
  5. // Created by Sam Jaffe on 2/7/17.
  6. //
  7. #pragma once
  8. #include "iterator_fwd.hpp"
  9. #include "end_aware_iterator.hpp"
  10. #include <iterator>
  11. namespace iterator {
  12. template <typename MetaIterator>
  13. class joining_iterator {
  14. public:
  15. using join_iter = MetaIterator;
  16. using joinable_type = typename join_iter::value_type;
  17. using iter_type = detail::value_iterator<MetaIterator>;
  18. using value_type = typename std::iterator_traits<iter_type>::value_type;
  19. using reference = typename std::iterator_traits<iter_type>::reference;
  20. using pointer = typename std::iterator_traits<iter_type>::pointer;
  21. using difference_type = typename std::iterator_traits<iter_type>::difference_type;
  22. using iterator_category = std::forward_iterator_tag;
  23. public:
  24. explicit joining_iterator( )
  25. : joiner_({}, {}), iterator_({}, {}) {
  26. }
  27. template <typename I>
  28. joining_iterator( joining_iterator<I> const & other )
  29. : joiner_(other.join_iterator()), iterator_(other.element_iterator()) {
  30. }
  31. joining_iterator( join_iter start, join_iter end )
  32. : joiner_(start, end), iterator_({}, {}) {
  33. update_iterator();
  34. }
  35. joining_iterator( join_iter start, join_iter end, iter_type lstart, iter_type lend, bool update = false )
  36. : joiner_(start, end), iterator_(lstart, lend) {
  37. if ( update ) { update_iterator(); }
  38. }
  39. joining_iterator & operator++() {
  40. if ( (++iterator_).done() ) {
  41. ++joiner_;
  42. update_iterator();
  43. }
  44. return *this;
  45. }
  46. joining_iterator operator++(int) {
  47. joining_iterator tmp{*this};
  48. operator++();
  49. return tmp;
  50. }
  51. reference operator*() { return iterator_.operator*(); }
  52. pointer operator->() { return iterator_.operator->(); }
  53. bool operator==(joining_iterator const & other) const {
  54. return joiner_ == other.joiner_ && ((joiner_.done() && other.joiner_.done()) ||
  55. iterator_ == other.iterator_);
  56. }
  57. bool operator!=(joining_iterator const & other) {
  58. return !(operator==(other));
  59. }
  60. end_aware_iterator<join_iter> join_iterator() const { return joiner_; }
  61. end_aware_iterator<iter_type> element_iterator() const { return iterator_; }
  62. private:
  63. void update_iterator() {
  64. while ( !joiner_.done() && std::begin(*joiner_) == std::end(*joiner_) ) {
  65. ++joiner_;
  66. }
  67. if ( !joiner_.done() ) {
  68. iterator_ = { std::begin(*joiner_), std::end(*joiner_) };
  69. }
  70. }
  71. end_aware_iterator<join_iter> joiner_;
  72. end_aware_iterator<iter_type> iterator_;
  73. };
  74. }