|
|
@@ -0,0 +1,309 @@
|
|
|
+/*
|
|
|
+ * File stream.hpp
|
|
|
+ *
|
|
|
+ * Stream style functional composition
|
|
|
+ *
|
|
|
+ * @author Sam Jaffe
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+#include <algorithm>
|
|
|
+#include <utility>
|
|
|
+#include <functional>
|
|
|
+#include <iterator>
|
|
|
+
|
|
|
+namespace stream {
|
|
|
+
|
|
|
+template <typename T> class stream {
|
|
|
+ public:
|
|
|
+ virtual ~stream() = default;
|
|
|
+ //template<template <class...> class C>
|
|
|
+ //C<T> complete() const;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename T, typename It>
|
|
|
+class iter_stream : public stream<T> {
|
|
|
+ public:
|
|
|
+ virtual ~iter_stream() = default;
|
|
|
+ template<template <class...> class C>
|
|
|
+ C<T> complete() const {
|
|
|
+ C<T> out;
|
|
|
+ std::copy(begin(), end(), std::back_inserter(out));
|
|
|
+ return out;
|
|
|
+ }
|
|
|
+ typedef It const_iterator;
|
|
|
+ virtual const_iterator begin() const = 0;
|
|
|
+ virtual const_iterator end() const = 0;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename T, template <class...> class C>
|
|
|
+class cont_stream : public iter_stream<T, typename C<T>::const_iterator> {
|
|
|
+ public:
|
|
|
+ typedef typename C<T>::value_type value_type;
|
|
|
+ typedef iter_stream<T, typename C<T>::const_iterator> super;
|
|
|
+ typedef typename super::const_iterator const_iterator;
|
|
|
+ public:
|
|
|
+ cont_stream(const C<T>& data) : super(), data(&data), owning(false) {}
|
|
|
+ cont_stream(C<T>&& data) : super(), data(new C<T>(std::forward<C<T>>(data))), owning(true) {}
|
|
|
+ virtual ~cont_stream() { if (owning && data) delete data;}
|
|
|
+ virtual const_iterator begin() const { return data->begin(); }
|
|
|
+ virtual const_iterator end() const { return data->end(); }
|
|
|
+ private:
|
|
|
+ const bool owning;
|
|
|
+ const C<T>* data;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename InStream, typename O, typename F>
|
|
|
+struct map_stream_iterator {
|
|
|
+ public:
|
|
|
+ typedef typename InStream::value_type value_type;
|
|
|
+ typedef value_type& reference;
|
|
|
+ typedef value_type* pointer;
|
|
|
+ typedef std::ptrdiff_t difference_type;
|
|
|
+ typedef std::input_iterator_tag iterator_category;
|
|
|
+ typedef typename InStream::const_iterator Impl;
|
|
|
+ public:
|
|
|
+ map_stream_iterator(Impl it, F func) : impl(it), f(func) {}
|
|
|
+
|
|
|
+ O operator*() const {
|
|
|
+ return f(*impl);
|
|
|
+ }
|
|
|
+
|
|
|
+ map_stream_iterator& operator++() {
|
|
|
+ ++impl;
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ map_stream_iterator operator++(int) {
|
|
|
+ map_stream_iterator tmp(*this);
|
|
|
+ operator++();
|
|
|
+ return tmp;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool operator==(const map_stream_iterator& other) const {
|
|
|
+ return impl == other.impl;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool operator!=(const map_stream_iterator& other) const {
|
|
|
+ return impl != other.impl;
|
|
|
+ }
|
|
|
+
|
|
|
+ private:
|
|
|
+ F f;
|
|
|
+ Impl impl;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename O, typename I, typename InStream>
|
|
|
+class map_stream : public iter_stream<O, map_stream_iterator<InStream, O, std::function<O(I)> > > {
|
|
|
+ public:
|
|
|
+ typedef O value_type;
|
|
|
+ typedef iter_stream<O, map_stream_iterator<InStream, O, std::function<O(I)> > > super;
|
|
|
+ typedef typename super::const_iterator const_iterator;
|
|
|
+ public:
|
|
|
+ map_stream(const InStream& in, std::function<O(I)> func) : super(), in(in), f(func) {}
|
|
|
+ virtual ~map_stream() = default;
|
|
|
+ virtual const_iterator begin() const { return const_iterator(in.begin(), f); }
|
|
|
+ virtual const_iterator end() const { return const_iterator(in.end(), f); }
|
|
|
+ private:
|
|
|
+ const InStream in;
|
|
|
+ std::function<O(I)> f;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename InStream>
|
|
|
+struct filter_stream_iterator {
|
|
|
+ public:
|
|
|
+ typedef typename InStream::value_type value_type;
|
|
|
+ typedef value_type& reference;
|
|
|
+ typedef value_type* pointer;
|
|
|
+ typedef std::ptrdiff_t difference_type;
|
|
|
+ typedef std::input_iterator_tag iterator_category;
|
|
|
+ typedef typename InStream::const_iterator Impl;
|
|
|
+ public:
|
|
|
+ filter_stream_iterator(Impl it, Impl end, std::function<bool(value_type)> predicate) : impl(it), end(end), pred(predicate) {}
|
|
|
+
|
|
|
+ value_type operator*() const {
|
|
|
+ return *impl;
|
|
|
+ }
|
|
|
+
|
|
|
+ filter_stream_iterator& operator++() {
|
|
|
+ do {
|
|
|
+ ++impl;
|
|
|
+ } while (impl != end && !pred(*impl));
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ filter_stream_iterator operator++(int) {
|
|
|
+ filter_stream_iterator tmp(*this);
|
|
|
+ operator++();
|
|
|
+ return tmp;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool operator==(const filter_stream_iterator& other) const {
|
|
|
+ return impl == other.impl;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool operator!=(const filter_stream_iterator& other) const {
|
|
|
+ return impl != other.impl;
|
|
|
+ }
|
|
|
+
|
|
|
+ private:
|
|
|
+ std::function<bool(value_type)> pred;
|
|
|
+ Impl impl;
|
|
|
+ Impl end;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename T, typename InStream>
|
|
|
+class filter_stream : public iter_stream<T, filter_stream_iterator<InStream>> {
|
|
|
+ public:
|
|
|
+ typedef T value_type;
|
|
|
+ typedef iter_stream<T, filter_stream_iterator<InStream>> super;
|
|
|
+ typedef typename super::const_iterator const_iterator;
|
|
|
+ public:
|
|
|
+ filter_stream(const InStream& in, std::function<bool(T)> predicate) : super(), in(in), pred(predicate) {}
|
|
|
+ virtual ~filter_stream() = default;
|
|
|
+ virtual const_iterator begin() const { return const_iterator(in.begin(), in.end(), pred); }
|
|
|
+ virtual const_iterator end() const { return const_iterator(in.end(), in.end(), pred); }
|
|
|
+ private:
|
|
|
+ const InStream in;
|
|
|
+ std::function<bool(T)> pred;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename Cons>
|
|
|
+struct cons_stream_iterator {
|
|
|
+ public:
|
|
|
+ typedef typename Cons::value_type InStream;
|
|
|
+ typedef typename InStream::value_type value_type;
|
|
|
+ typedef value_type& reference;
|
|
|
+ typedef value_type* pointer;
|
|
|
+ typedef std::ptrdiff_t difference_type;
|
|
|
+ typedef std::input_iterator_tag iterator_category;
|
|
|
+
|
|
|
+ typedef typename Cons::const_iterator ConsIter;
|
|
|
+ typedef typename InStream::const_iterator StreamIter;
|
|
|
+ public:
|
|
|
+ cons_stream_iterator(ConsIter iter) : citer(iter) {}
|
|
|
+
|
|
|
+ cons_stream_iterator& operator++() {
|
|
|
+ if (scurr == send) {
|
|
|
+ ++citer;
|
|
|
+ scurr = citer->begin();
|
|
|
+ send = citer->end();
|
|
|
+ } else {
|
|
|
+ ++scurr;
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ cons_stream_iterator operator++(int) {
|
|
|
+ cons_stream_iterator tmp(*this);
|
|
|
+ operator++();
|
|
|
+ return tmp;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool operator==(const cons_stream_iterator& other) const {
|
|
|
+ return citer == other.citer && scurr == other.scurr;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool operator!=(const cons_stream_iterator& other) const {
|
|
|
+ return citer != other.citer || scurr != other.scurr;
|
|
|
+ }
|
|
|
+ private:
|
|
|
+ ConsIter citer;
|
|
|
+ StreamIter scurr;
|
|
|
+ StreamIter send;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename T, typename InStream>
|
|
|
+class cons_stream : public iter_stream<T, cons_stream_iterator<std::vector<InStream>>> {
|
|
|
+ public:
|
|
|
+ typedef T value_type;
|
|
|
+ typedef iter_stream<T, cons_stream_iterator<std::list<InStream>>> super;
|
|
|
+ typedef typename super::const_iterator const_iterator;
|
|
|
+ public:
|
|
|
+ virtual ~cons_stream() = default;
|
|
|
+ virtual const_iterator begin() const { return const_iterator(in.begin()); }
|
|
|
+ virtual const_iterator end() const { return const_iterator(in.end()); }
|
|
|
+ private:
|
|
|
+ std::list<InStream> in;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename GenIter, typename It>
|
|
|
+struct flatmap_stream_iterator {
|
|
|
+ public:
|
|
|
+ typedef typename GenIter::value_type MapStream;
|
|
|
+ typedef typename It::value_type value_type;
|
|
|
+ typedef value_type& reference;
|
|
|
+ typedef value_type* pointer;
|
|
|
+ typedef std::ptrdiff_t difference_type;
|
|
|
+ typedef std::input_iterator_tag iterator_category;
|
|
|
+ public:
|
|
|
+ flatmap_stream_iterator(GenIter gen) : generator(gen) {}
|
|
|
+
|
|
|
+ value_type operator*() {
|
|
|
+ if (!mapped) {
|
|
|
+ mapped = new MapStream(std::forward<MapStream>(*generator));
|
|
|
+ curr = mapped->begin();
|
|
|
+ end = mapped->end();
|
|
|
+ }
|
|
|
+ return *curr;
|
|
|
+ }
|
|
|
+
|
|
|
+ flatmap_stream_iterator& operator++() {
|
|
|
+ ++curr;
|
|
|
+ if (curr == end) {
|
|
|
+ ++generator;
|
|
|
+ delete mapped;
|
|
|
+ mapped = nullptr;
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+
|
|
|
+ flatmap_stream_iterator operator++(int) {
|
|
|
+ flatmap_stream_iterator tmp(*this);
|
|
|
+ operator++();
|
|
|
+ return tmp;
|
|
|
+ }
|
|
|
+ private:
|
|
|
+ GenIter generator;
|
|
|
+ MapStream* mapped = nullptr;
|
|
|
+ It curr;
|
|
|
+ It end;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename O, typename I, typename InStream, typename MapStream>
|
|
|
+class flatmap_stream : public iter_stream<O, flatmap_stream_iterator<typename InStream::const_iterator, typename MapStream::const_iterator>> {
|
|
|
+};
|
|
|
+
|
|
|
+template <typename T, template <class...> class C>
|
|
|
+cont_stream<T, C> make_stream(const C<T>& data) {
|
|
|
+ return cont_stream<T, C>(data);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename F, typename InStream>
|
|
|
+auto map(const InStream& stream, F func) -> map_stream<decltype(func(std::declval<typename InStream::value_type>())), typename InStream::value_type, InStream> {
|
|
|
+ using I = typename InStream::value_type;
|
|
|
+ using O = decltype(func(std::declval<I>()));
|
|
|
+ return map_stream<O, I, InStream>(stream, func);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename P, typename InStream>
|
|
|
+auto filter(const InStream& stream, P predicate) -> filter_stream<typename InStream::value_type, InStream> {
|
|
|
+ using T = typename InStream::value_type;
|
|
|
+ return filter_stream<T, InStream>(stream, predicate);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename P, typename F, typename InStream>
|
|
|
+auto map_if(const InStream& stream, P predicate, F func) -> decltype(map(std::declval<decltype(filter(stream, predicate))>(), func)) {
|
|
|
+ return map(filter(stream, predicate), func);
|
|
|
+}
|
|
|
+
|
|
|
+//void flatMap(const InStream& stream, F func)
|
|
|
+
|
|
|
+template <typename F, typename InStream, typename Arg1>
|
|
|
+auto reduce(const InStream& stream, F func, Arg1 accum) -> Arg1 {
|
|
|
+ std::for_each(stream.begin(), stream.end(), [&accum, func](typename InStream::value_type i) { accum = func(accum, i); });
|
|
|
+ return accum;
|
|
|
+}
|
|
|
+
|
|
|
+}
|
|
|
+
|