Kaynağa Gözat

refactor: change filter and map to use iterator lib

Sam Jaffe 2 yıl önce
ebeveyn
işleme
f6078ed47b

+ 6 - 1
include/stream/detail/ifd_pointer.hpp

@@ -15,7 +15,8 @@ namespace stream { namespace detail {
 
     ifd_pointer() = default;
     ifd_pointer(ifd_pointer const & other)
-        : copy(other.copy), destroy(other.destroy), ptr(copy(other.ptr)) {}
+        : copy(other.copy), destroy(other.destroy),
+          ptr(copy ? copy(other.ptr) : nullptr) {}
     ifd_pointer(ifd_pointer && other) {
       *this = std::forward<ifd_pointer>(other);
     }
@@ -32,6 +33,10 @@ namespace stream { namespace detail {
     }
 
     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) {

+ 2 - 2
include/stream/detail/self_iterating_container.hpp

@@ -1,6 +1,6 @@
 #pragma once
 
-namespace stream { namespace detail {
+namespace stream::detail {
   template <typename C, typename It = typename C::const_iterator>
   class self_iterating_container {
   private:
@@ -56,4 +56,4 @@ namespace stream { namespace detail {
       std::advance(current, offset);
     }
   };
-}}
+}

+ 8 - 9
include/stream/filter.hpp

@@ -1,6 +1,9 @@
 #pragma once
 
-namespace stream { namespace detail {
+#include <iterator/filter_iterator.hpp>
+#include <stream/iterator.hpp>
+
+namespace stream::detail {
   template <typename T> class filter_iterator {
   public:
     filter_iterator(std::function<bool(T const &)> f, iterator<T> && impl,
@@ -40,16 +43,12 @@ namespace stream { namespace detail {
     filter_stream(F && func, stream_base<T> const & sb)
         : pred_(func), source_(sb) {}
 
-    iterator<T> begin() {
-      return {filter_iterator<T>{pred_, source_.begin(), source_.end()}};
-    }
+    iterator<T> begin() { return ::iterator::filter_iterator(pred_, source_); }
 
-    iterator<T> end() {
-      return {filter_iterator<T>{pred_, source_.end(), source_.end()}};
-    }
+    iterator<T> end() { return ::iterator::filter_iterator<iterator<T>>(); }
 
   private:
-    std::function<bool(T const &)> pred_;
+    typename ::iterator::filter_iterator<iterator<T>>::predicate_t pred_;
     stream_base<T> source_;
   };
 
@@ -64,4 +63,4 @@ namespace stream { namespace detail {
   auto stream_base<T>::filter(F && pred) const & -> stream_base<T> {
     return std::make_shared<filter_stream<T>>(pred, *this);
   }
-}}
+}

+ 2 - 2
include/stream/forward.hpp

@@ -2,10 +2,10 @@
 
 #include "traits.hpp"
 
-namespace stream { namespace detail {
+namespace stream::detail {
   template <typename> class stream_base;
   template <typename> class iterator_impl;
-}}
+}
 
 namespace stream {
   template <typename> class iterator;

+ 8 - 2
include/stream/iterator.hpp

@@ -5,6 +5,7 @@
 //  Created by Sam Jaffe on 3/28/23.
 //
 
+#pragma once
 #include "detail/ifd_pointer.hpp"
 
 #include <iterator/facade.h>
@@ -32,10 +33,15 @@ namespace stream {
 
     T dereference() const { return dereference_(impl_.get()); }
     void increment() { increment_(impl_.get()); }
-    bool equal_to(iterator other) const {
-      return equal_to_(impl_.get(), other.impl_.get());
+    bool equal_to(iterator const & other) const {
+      return impl_ == other.impl_ ||
+             (impl_ && other.impl_ &&
+              equal_to_(impl_.get(), other.impl_.get()));
     }
   };
+
+  template <typename Iter>
+  iterator(Iter) -> iterator<typename std::iterator_traits<Iter>::reference>;
 }
 
 MAKE_ITERATOR_FACADE_TYPEDEFS_T(::stream::iterator);

+ 2 - 2
include/stream/make_stream.hpp

@@ -16,14 +16,14 @@ namespace stream {
   }
 
   template <typename T> detail::stream_base<T &> empty() {
-    return std::make_shared<detail::range_stream<T *, T &>>(nullptr, nullptr);
+    return std::make_shared<detail::range_stream<T *>>(nullptr, nullptr);
   }
 
   /**
    * Construct a single element stream containing the pointer given
    */
   template <typename T> detail::stream_base<T &> of(T * ptr) {
-    return std::make_shared<detail::range_stream<T *, T &>>(ptr, ptr + 1);
+    return std::make_shared<detail::range_stream<T *>>(ptr, ptr + 1);
   }
 
   /**

+ 16 - 16
include/stream/map.hpp

@@ -1,23 +1,23 @@
 #pragma once
 
-namespace stream { namespace detail {
-  template <typename T, typename R> class map_iterator {
+#include <iterator/proxy.h>
+
+namespace stream::detail {
+  template <typename T, typename R>
+  class map_iterator
+      : public ::iterator::proxy<iterator<T>, map_iterator<T, R>> {
+  public:
+    using projection_t = std::function<R(T const &)>;
+    using super_t = ::iterator::proxy<iterator<T>, map_iterator<T, R>>;
+
   public:
-    map_iterator(std::function<R(T const &)> f, iterator<T> && impl)
-        : fun_(f), impl_(std::forward<iterator<T>>(impl)) {}
-
-    R operator*() { return fun_(*impl_); }
-    map_iterator & operator++() {
-      ++impl_;
-      return *this;
-    }
-    bool operator==(map_iterator const & rhs) const {
-      return impl_ == rhs.impl_;
-    }
+    map_iterator(projection_t proj, iterator<T> && impl)
+        : proj_(std::move(proj)), super_t(std::move(impl)) {}
+
+    R dereference() const { return proj_(super_t::dereference()); }
 
   private:
-    std::function<R(T const &)> fun_;
-    iterator<T> impl_;
+    std::function<R(T const &)> proj_;
   };
 
   template <typename T, typename R> class map_stream {
@@ -47,4 +47,4 @@ namespace stream { namespace detail {
   stream_base<traits::mapped_t<T, F>> stream_base<T>::map(F && func) const & {
     return std::make_shared<map_stream<T, traits::mapped_t<T, F>>>(func, *this);
   }
-}}
+}

+ 5 - 29
include/stream/source.hpp

@@ -3,47 +3,23 @@
 #include <iterator>
 
 namespace stream { namespace detail {
-  template <typename Iter> class source_iterator {
-  public:
-    using value_type = typename std::iterator_traits<Iter>::reference;
-    explicit source_iterator(Iter it) : impl_(it) {}
-
-    value_type operator*() { return *impl_; }
-    source_iterator & operator++() {
-      ++impl_;
-      return *this;
-    }
-    bool operator==(source_iterator const & rhs) const {
-      return impl_ == rhs.impl_;
-    }
-
-  private:
-    Iter impl_;
-  };
-
   template <typename C> class source_stream {
   public:
-    typedef decltype(std::declval<C>().begin()) _iterator;
-    typedef decltype(*std::declval<_iterator>()) reference;
-
     explicit source_stream(C && cont) : source_(std::forward<C>(cont)) {}
 
-    iterator<reference> begin() { return {source_.begin()}; }
-    iterator<reference> end() { return {source_.end()}; }
+    auto begin() { return iterator(source_.begin()); }
+    auto end() { return iterator(source_.end()); }
 
   private:
     C source_;
   };
 
-  template <typename It, typename R = typename It::reference>
-  class range_stream {
+  template <typename It> class range_stream {
   public:
-    using reference = R;
-
     explicit range_stream(It b, It e) : begin_(b), end_(e) {}
 
-    iterator<reference> begin() { return {begin_}; }
-    iterator<reference> end() { return {end_}; }
+    auto begin() { return iterator(begin_); }
+    auto end() { return iterator(end_); }
 
   private:
     It begin_, end_;