Browse Source

Extract the parts of join_iterator that needed that dumb JOIN_CTOR macro.

Sam Jaffe 5 years ago
parent
commit
7a322ca770
2 changed files with 66 additions and 40 deletions
  1. 8 40
      include/stream/streams/join.hpp
  2. 58 0
      include/stream/streams/self_iterating_contianer.hpp

+ 8 - 40
include/stream/streams/join.hpp

@@ -1,17 +1,9 @@
 #pragma once
 
 #include <iterator>
+#include "self_iterating_contianer.hpp"
 
-namespace stream { namespace detail {
-#define JOIN_CTOR(mod)                                                         \
-  start_ = mod(other.start_);                                                  \
-  finish_ = mod(other.finish_);                                                \
-  std::ptrdiff_t n = std::distance(other.mem_.cbegin(), other.curr_);          \
-  mem_ = mod(other.mem_);                                                      \
-  curr_ = mem_.begin();                                                        \
-  std::advance(curr_, n);                                                      \
-  end_ = mem_.end();
-
+namespace stream { namespace detail {  
   template <typename C> class join_iterator {
   public:
     using reference = typename C::const_iterator::reference;
@@ -20,35 +12,15 @@ namespace stream { namespace detail {
     join_iterator(iterator<C> && f, iterator<C> && l)
         : start_(std::move(f)), finish_(std::move(l)) {
       if (start_ != finish_) {
-        mem_ = *(start_);
-        curr_ = mem_.begin();
-        end_ = mem_.end();
+        current_ = *start_;
         advance();
       }
     }
 
-    join_iterator(join_iterator const & other) {
-      JOIN_CTOR()
-    }
-    
-    join_iterator(join_iterator && other){
-      JOIN_CTOR(std::move)
-    }
-
-    join_iterator & operator=(join_iterator const & other) {
-      JOIN_CTOR()
-      return *this;
-    }
-
-    join_iterator & operator=(join_iterator && other) {
-      JOIN_CTOR(std::move)
-      return *this;
-    }
-
-    reference operator*() { return *curr_; }
+    reference operator*() { return *current_; }
 
     join_iterator & operator++() {
-      ++curr_;
+      ++current_;
       advance();
       return *this;
     }
@@ -56,18 +28,14 @@ namespace stream { namespace detail {
     bool operator==(join_iterator const & rhs) const { return start_ == rhs.start_; }
   private:
     void advance() {
-      while (curr_ == end_ && start_ != finish_) {
+      while (!current_ && start_ != finish_) {
         if (++start_ == finish_) { break; }
-        mem_ = *start_;
-        curr_ = mem_.begin();
-        end_ = mem_.end();
+        current_ = *start_;
       }
     }
     iterator<C> start_;
     iterator<C> finish_;
-    C mem_;
-    typename C::const_iterator curr_;
-    typename C::const_iterator end_;
+    self_iterating_container<C> current_;
   };
 
   template <typename C> class join_stream {

+ 58 - 0
include/stream/streams/self_iterating_contianer.hpp

@@ -0,0 +1,58 @@
+#pragma once
+
+namespace stream { namespace detail {
+template <typename C, typename It = typename C::const_iterator>
+class self_iterating_container {
+private:
+  std::ptrdiff_t offset{0};
+  C container;
+  It current;
+  It end;
+
+public:
+  self_iterating_container() = default;
+  self_iterating_container(C const & container)
+      : container(container), current(container.cbegin()),
+        end(container.cend()) {}
+  
+  self_iterating_container(C && container)
+      : container(std::move(container)), current(container.cbegin()),
+        end(container.cend()) {}
+  
+  self_iterating_container(self_iterating_container const & other) {
+    *this = other;
+  }
+  
+  self_iterating_container(self_iterating_container && other) {
+    *this = std::move(other);
+  }
+
+  self_iterating_container & operator=(self_iterating_container const & other) {
+    offset = other.offset;
+    container = other.container;
+    setup();
+    return *this;
+  }
+  
+  self_iterating_container & operator=(self_iterating_container && other) {
+    offset = other.offset;
+    container = std::move(other.container);
+    setup();
+    return *this;
+  }
+  
+  void operator++() {
+    ++offset;
+    ++current;
+  }
+  auto& operator*() const { return *current; }
+  operator bool() const { return current != end; }
+  
+private:
+  void setup() {
+    current = container.cbegin();
+    end = container.cend();
+    std::advance(current, offset);
+  }
+};
+}}