瀏覽代碼

refactor: use iterator lib for filter/flatmap

Sam Jaffe 2 年之前
父節點
當前提交
8927ee4ff8

+ 1 - 1
external/iterator

@@ -1 +1 @@
-Subproject commit f2cf5bee422d03fffd0621ae27927def2b9529b4
+Subproject commit 84d6c7f62399488cb8b02689c2a00294736feecb

+ 46 - 46
include/stream/detail/ifd_pointer.hpp

@@ -1,53 +1,53 @@
 #pragma once
 
-namespace stream { namespace detail {
-  class ifd_pointer {
-  private:
-    void * (*copy)(void *){nullptr};
-    void (*destroy)(void *){nullptr};
-    void * ptr{nullptr};
+namespace stream::detail {
+class ifd_pointer {
+private:
+  void * (*copy)(void *){nullptr};
+  void (*destroy)(void *){nullptr};
+  void * ptr{nullptr};
 
-  public:
-    template <typename T>
-    ifd_pointer(T && value)
-        : copy(&ifd_pointer::copy_<T>), destroy(&ifd_pointer::destroy_<T>),
-          ptr(copy(&value)) {}
+public:
+  template <typename T>
+  ifd_pointer(T && value)
+      : copy(&ifd_pointer::copy_<T>), destroy(&ifd_pointer::destroy_<T>),
+        ptr(copy(&value)) {}
 
-    ifd_pointer() = default;
-    ifd_pointer(ifd_pointer const & other)
-        : copy(other.copy), destroy(other.destroy),
-          ptr(copy ? copy(other.ptr) : nullptr) {}
-    ifd_pointer(ifd_pointer && other) {
-      *this = std::forward<ifd_pointer>(other);
-    }
-    ifd_pointer & operator=(ifd_pointer const & other) {
-      return *this = ifd_pointer(other);
-    }
-    ~ifd_pointer() {
-      if (destroy) destroy(ptr);
-    }
+  ifd_pointer() = default;
+  ifd_pointer(ifd_pointer const & other)
+      : copy(other.copy), destroy(other.destroy),
+        ptr(copy ? copy(other.ptr) : nullptr) {}
+  ifd_pointer(ifd_pointer && other) {
+    *this = std::forward<ifd_pointer>(other);
+  }
+  ifd_pointer & operator=(ifd_pointer const & other) {
+    return *this = ifd_pointer(other);
+  }
+  ~ifd_pointer() {
+    if (destroy) destroy(ptr);
+  }
 
-    ifd_pointer & operator=(ifd_pointer && other) {
-      swap(*this, other);
-      return *this;
-    }
+  ifd_pointer & operator=(ifd_pointer && other) {
+    swap(*this, other);
+    return *this;
+  }
 
-    void * get() const { return ptr; }
-    operator bool() const { return ptr; }
-    friend bool operator==(ifd_pointer const & lhs, ifd_pointer const & rhs) {
-      return lhs.ptr == rhs.ptr;
-    }
+  void * get() const { return ptr; }
+  operator bool() const { return ptr; }
+  friend bool operator==(ifd_pointer const & lhs, ifd_pointer const & rhs) {
+    return lhs.ptr == rhs.ptr;
+  }
 
-  private:
-    friend void swap(ifd_pointer & lhs, ifd_pointer & rhs) {
-      using ::std::swap;
-      swap(lhs.copy, rhs.copy);
-      swap(lhs.destroy, rhs.destroy);
-      swap(lhs.ptr, rhs.ptr);
-    }
-    template <typename T> static void * copy_(void * p) {
-      return (void *)new T(*(T *)(p));
-    }
-    template <typename T> static void destroy_(void * p) { delete (T *)(p); }
-  };
-}}
+private:
+  friend void swap(ifd_pointer & lhs, ifd_pointer & rhs) {
+    using ::std::swap;
+    swap(lhs.copy, rhs.copy);
+    swap(lhs.destroy, rhs.destroy);
+    swap(lhs.ptr, rhs.ptr);
+  }
+  template <typename T> static void * copy_(void * p) {
+    return (void *)new T(*(T *)(p));
+  }
+  template <typename T> static void destroy_(void * p) { delete (T *)(p); }
+};
+}

+ 0 - 58
include/stream/detail/self_iterating_container.hpp

@@ -1,58 +0,0 @@
-#pragma once
-
-namespace stream::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);
-  }
-};
-}

+ 7 - 37
include/stream/filter.hpp

@@ -1,54 +1,24 @@
 #pragma once
 
-#include <iterator/filter_iterator.hpp>
 #include <stream/iterator.hpp>
 
+#include <iterator/filter_iterator.hpp>
+
 namespace stream::detail {
-template <typename T> class filter_iterator {
+template <typename T> class filter_stream {
 public:
-  filter_iterator(std::function<bool(T const &)> f, iterator<T> && impl,
-                  iterator<T> && end)
-      : pred_(f), impl_(std::forward<iterator<T>>(impl)),
-        end_(std::forward<iterator<T>>(end)) {
-    advance();
-  }
-
-  T operator*() { return mem_; }
-
-  filter_iterator & operator++() {
-    ++impl_;
-    advance();
-    return *this;
-  }
-
-  bool operator==(filter_iterator const & rhs) const {
-    return impl_ == rhs.impl_;
-  }
+  using iter_type = ::iterator::filter_iterator<iterator<T>, true>;
 
-private:
-  void advance() {
-    while (impl_ != end_ && !pred_(mem_ = *impl_)) {
-      ++impl_;
-    }
-  }
-
-  std::function<bool(T const &)> pred_;
-  ref_or_val<T> mem_; // To avoid re-calcs, we store this
-  iterator<T> impl_, end_;
-};
-
-template <typename T> class filter_stream {
 public:
   template <typename F>
   filter_stream(F && func, stream_base<T> const & sb)
       : pred_(func), source_(sb) {}
 
-  iterator<T> begin() { return ::iterator::filter_iterator(pred_, source_); }
-
-  iterator<T> end() { return ::iterator::filter_iterator<iterator<T>>(); }
+  iterator<T> begin() { return iter_type(pred_, source_); }
+  iterator<T> end() { return iter_type(); }
 
 private:
-  typename ::iterator::filter_iterator<iterator<T>>::predicate_t pred_;
+  typename iter_type::predicate_t pred_;
   stream_base<T> source_;
 };
 

+ 36 - 74
include/stream/join.hpp

@@ -2,77 +2,39 @@
 
 #include <iterator>
 
-#include "detail/self_iterating_container.hpp"
-
-namespace stream { namespace detail {
-  template <typename C> class join_iterator {
-  public:
-    using reference = typename C::const_iterator::reference;
-
-  public:
-    join_iterator(iterator<C> && f, iterator<C> && l)
-        : start_(std::move(f)), finish_(std::move(l)) {
-      if (start_ != finish_) {
-        current_ = *start_;
-        advance();
-      }
-    }
-
-    reference operator*() { return *current_; }
-
-    join_iterator & operator++() {
-      ++current_;
-      advance();
-      return *this;
-    }
-
-    bool operator==(join_iterator const & rhs) const {
-      return start_ == rhs.start_;
-    }
-
-  private:
-    void advance() {
-      while (!current_ && start_ != finish_) {
-        if (++start_ == finish_) { break; }
-        current_ = *start_;
-      }
-    }
-    iterator<C> start_;
-    iterator<C> finish_;
-    self_iterating_container<C> current_;
-  };
-
-  template <typename C> class join_stream {
-  public:
-    using T = typename C::value_type;
-    explicit join_stream(stream_base<C> const & sb) : source_(sb) {}
-
-    iterator<T> begin() {
-      return {join_iterator<C>{source_.begin(), source_.end()}};
-    }
-    iterator<T> end() {
-      return {join_iterator<C>{source_.end(), source_.end()}};
-    }
-
-  private:
-    stream_base<C> source_;
-  };
-
-  template <typename C>
-  stream_base<typename C::value_type> make_join(stream_base<C> const & sb) {
-    return std::make_shared<join_stream<C>>(sb);
-  }
-
-  template <typename T>
-  template <typename F>
-  stream_base<traits::fmapped_t<T, F>> stream_base<T>::flatmap(F && func) && {
-    return make_join(std::move(*this).map(func));
-  }
-
-  template <typename T>
-  template <typename F>
-  stream_base<traits::fmapped_t<T, F>>
-  stream_base<T>::flatmap(F && func) const & {
-    return make_join(map(func));
-  }
-}}
+#include <iterator/join_iterator.hpp>
+#include <stream/iterator.hpp>
+
+namespace stream::detail {
+template <typename C> class join_stream {
+public:
+  using iter_type = ::iterator::joining_iterator<iterator<C>>;
+
+  using T = typename C::value_type;
+  explicit join_stream(stream_base<C> const & sb) : source_(sb) {}
+
+  iterator<T> begin() { return iter_type(source_); }
+  iterator<T> end() { return iter_type(); }
+
+private:
+  stream_base<C> source_;
+};
+
+template <typename C>
+stream_base<typename C::value_type> make_join(stream_base<C> const & sb) {
+  return std::make_shared<join_stream<C>>(sb);
+}
+
+template <typename T>
+template <typename F>
+stream_base<traits::fmapped_t<T, F>> stream_base<T>::flatmap(F && func) && {
+  return make_join(std::move(*this).map(func));
+}
+
+template <typename T>
+template <typename F>
+stream_base<traits::fmapped_t<T, F>>
+stream_base<T>::flatmap(F && func) const & {
+  return make_join(map(func));
+}
+}

+ 18 - 18
include/stream/source.hpp

@@ -2,26 +2,26 @@
 
 #include <iterator>
 
-namespace stream { namespace detail {
-  template <typename C> class source_stream {
-  public:
-    explicit source_stream(C && cont) : source_(std::forward<C>(cont)) {}
+namespace stream::detail {
+template <typename C> class source_stream {
+public:
+  explicit source_stream(C && cont) : source_(std::forward<C>(cont)) {}
 
-    auto begin() { return iterator(source_.begin()); }
-    auto end() { return iterator(source_.end()); }
+  auto begin() { return iterator(source_.begin()); }
+  auto end() { return iterator(source_.end()); }
 
-  private:
-    C source_;
-  };
+private:
+  C source_;
+};
 
-  template <typename It> class range_stream {
-  public:
-    explicit range_stream(It b, It e) : begin_(b), end_(e) {}
+template <typename It> class range_stream {
+public:
+  explicit range_stream(It b, It e) : begin_(b), end_(e) {}
 
-    auto begin() { return iterator(begin_); }
-    auto end() { return iterator(end_); }
+  auto begin() { return iterator(begin_); }
+  auto end() { return iterator(end_); }
 
-  private:
-    It begin_, end_;
-  };
-}}
+private:
+  It begin_, end_;
+};
+}

+ 1 - 0
include/stream/streams.hpp

@@ -2,6 +2,7 @@
 
 #include <stream/forward.hpp>
 
+#include <stream/iterator.hpp>
 #include <stream/make_stream.hpp>
 #include <stream/stream_base.hpp>
 

+ 47 - 66
include/stream/traits.hpp

@@ -9,79 +9,60 @@
 
 #include <utility>
 
-namespace stream { namespace detail {
-  template <typename T> struct ref_or_val {
-    ref_or_val operator=(T && val) {
-      value = std::move(val);
-      return *this;
-    }
-    operator T const &() const { return value; }
-    T value;
-  };
+namespace stream::detail {
+template <typename F> struct map_member_object;
+template <typename T, typename R> struct map_member_object<R T::*> {
+  using type = R const &;
+  type operator()(T const & val) const { return val.*mem; }
+  R T::*mem;
+};
 
-  template <typename T> struct ref_or_val<T &> {
-    ref_or_val operator=(T & val) {
-      value = &val;
-      return *this;
-    }
-    operator T &() const { return *value; }
-    T * value;
-  };
+template <typename F> struct map_member_function;
+template <typename T, typename R> struct map_member_function<R (T::*)() const> {
+  using type = R;
+  type operator()(T const & val) const { return (val.*mem)(); }
+  R (T::*mem)() const;
+};
 
-  template <typename F> struct map_member_object;
-  template <typename T, typename R> struct map_member_object<R T::*> {
-    using type = R const &;
-    type operator()(T const & val) const { return val.*mem; }
-    R T::*mem;
-  };
+template <typename F> struct map_member_function;
+template <typename T, typename R>
+struct map_member_function<R (T::*)() const noexcept> {
+  using type = R;
+  type operator()(T const & val) const noexcept { return (val.*mem)(); }
+  R (T::*mem)() const;
+};
+}
 
-  template <typename F> struct map_member_function;
-  template <typename T, typename R>
-  struct map_member_function<R (T::*)() const> {
-    using type = R;
-    type operator()(T const & val) const { return (val.*mem)(); }
-    R (T::*mem)() const;
-  };
+namespace stream::traits {
+template <typename F>
+using memvar_f = typename detail::map_member_object<F>::type;
+template <typename F>
+using memfun_f = typename detail::map_member_function<F>::type;
 
-  template <typename F> struct map_member_function;
-  template <typename T, typename R>
-  struct map_member_function<R (T::*)() const noexcept> {
-    using type = R;
-    type operator()(T const & val) const noexcept { return (val.*mem)(); }
-    R (T::*mem)() const;
-  };
-}}
+template <typename F>
+using is_memvar_t =
+    typename std::enable_if<std::is_member_object_pointer<F>::value>::type;
+template <typename F>
+using is_memfun_t =
+    typename std::enable_if<std::is_member_function_pointer<F>::value>::type;
 
-namespace stream { namespace traits {
-  template <typename F>
-  using memvar_f = typename detail::map_member_object<F>::type;
-  template <typename F>
-  using memfun_f = typename detail::map_member_function<F>::type;
+template <typename T, typename = void>
+struct is_dereferencable : public std::false_type {};
 
-  template <typename F>
-  using is_memvar_t =
-      typename std::enable_if<std::is_member_object_pointer<F>::value>::type;
-  template <typename F>
-  using is_memfun_t =
-      typename std::enable_if<std::is_member_function_pointer<F>::value>::type;
+template <> struct is_dereferencable<void *> : public std::false_type {};
 
-  template <typename T, typename = void>
-  struct is_dereferencable : public std::false_type {};
+template <typename T>
+struct is_dereferencable<T, typename std::enable_if<!std::is_void<
+                                decltype(*std::declval<T>())>::value>::type>
+    : public std::true_type {};
 
-  template <> struct is_dereferencable<void *> : public std::false_type {};
+template <typename T>
+constexpr bool is_dereferencable_v = is_dereferencable<T>{};
 
-  template <typename T>
-  struct is_dereferencable<T, typename std::enable_if<!std::is_void<
-                                  decltype(*std::declval<T>())>::value>::type>
-      : public std::true_type {};
+template <typename T, typename F>
+using mapped_t = decltype(std::declval<F>()(std::declval<T>()));
 
-  template <typename T>
-  constexpr bool is_dereferencable_v = is_dereferencable<T>{};
-
-  template <typename T, typename F>
-  using mapped_t = decltype(std::declval<F>()(std::declval<T>()));
-
-  template <typename T, typename F>
-  using fmapped_t =
-      typename decltype(std::declval<F>()(std::declval<T>()))::value_type;
-}}
+template <typename T, typename F>
+using fmapped_t =
+    typename decltype(std::declval<F>()(std::declval<T>()))::value_type;
+}

+ 0 - 2
stream.xcodeproj/project.pbxproj

@@ -74,7 +74,6 @@
 		CD5281F029D3B173001A84DE /* forward.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = forward.hpp; sourceTree = "<group>"; };
 		CD5281F129D3B173001A84DE /* make_stream.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = make_stream.hpp; sourceTree = "<group>"; };
 		CD5281F329D3B173001A84DE /* ifd_pointer.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ifd_pointer.hpp; sourceTree = "<group>"; };
-		CD5281F429D3B173001A84DE /* self_iterating_container.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = self_iterating_container.hpp; sourceTree = "<group>"; };
 		CD5281F529D3B173001A84DE /* filter.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = filter.hpp; sourceTree = "<group>"; };
 		CD5281F629D3B173001A84DE /* source.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = source.hpp; sourceTree = "<group>"; };
 		CD5281F729D3B173001A84DE /* streams.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = streams.hpp; sourceTree = "<group>"; };
@@ -156,7 +155,6 @@
 			isa = PBXGroup;
 			children = (
 				CD5281F329D3B173001A84DE /* ifd_pointer.hpp */,
-				CD5281F429D3B173001A84DE /* self_iterating_container.hpp */,
 			);
 			path = detail;
 			sourceTree = "<group>";