|
|
@@ -1,6 +1,6 @@
|
|
|
/*
|
|
|
* File stream.hpp
|
|
|
- *
|
|
|
+ *
|
|
|
* Stream style functional composition
|
|
|
*
|
|
|
* @author Sam Jaffe
|
|
|
@@ -10,25 +10,23 @@
|
|
|
#pragma once
|
|
|
|
|
|
#include <algorithm>
|
|
|
-#include <utility>
|
|
|
#include <functional>
|
|
|
#include <iterator>
|
|
|
+#include <utility>
|
|
|
|
|
|
namespace stream {
|
|
|
|
|
|
-template <typename T> class stream {
|
|
|
+ template <typename T> class stream {
|
|
|
public:
|
|
|
virtual ~stream() = default;
|
|
|
- //template<template <class...> class C>
|
|
|
- //C<T> complete() const;
|
|
|
-};
|
|
|
+ // template<template <class...> class C>
|
|
|
+ // C<T> complete() const;
|
|
|
+ };
|
|
|
|
|
|
-template <typename T, typename It>
|
|
|
-class iter_stream : public stream<T> {
|
|
|
+ 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 {
|
|
|
+ template <template <class...> class C> C<T> complete() const {
|
|
|
C<T> out;
|
|
|
std::copy(begin(), end(), std::back_inserter(out));
|
|
|
return out;
|
|
|
@@ -36,42 +34,46 @@ class iter_stream : public stream<T> {
|
|
|
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> {
|
|
|
+ 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;}
|
|
|
+ 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;
|
|
|
-};
|
|
|
+ const C<T> * data;
|
|
|
+ };
|
|
|
|
|
|
-template <typename InStream, typename O, typename F>
|
|
|
-struct map_stream_iterator {
|
|
|
+ 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 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);
|
|
|
- }
|
|
|
+ O operator*() const { return f(*impl); }
|
|
|
|
|
|
- map_stream_iterator& operator++() {
|
|
|
+ map_stream_iterator & operator++() {
|
|
|
++impl;
|
|
|
return *this;
|
|
|
}
|
|
|
@@ -82,52 +84,61 @@ struct map_stream_iterator {
|
|
|
return tmp;
|
|
|
}
|
|
|
|
|
|
- bool operator==(const map_stream_iterator& other) const {
|
|
|
+ bool operator==(const map_stream_iterator & other) const {
|
|
|
return impl == other.impl;
|
|
|
}
|
|
|
|
|
|
- bool operator!=(const map_stream_iterator& other) const {
|
|
|
+ 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)> > > {
|
|
|
+ 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 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) {}
|
|
|
+ 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 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 {
|
|
|
+ template <typename InStream> struct filter_stream_iterator {
|
|
|
public:
|
|
|
typedef typename InStream::value_type value_type;
|
|
|
- typedef value_type& reference;
|
|
|
- typedef value_type* pointer;
|
|
|
+ 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) {}
|
|
|
+ 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;
|
|
|
- }
|
|
|
+ value_type operator*() const { return *impl; }
|
|
|
|
|
|
- filter_stream_iterator& operator++() {
|
|
|
+ filter_stream_iterator & operator++() {
|
|
|
do {
|
|
|
++impl;
|
|
|
} while (impl != end && !pred(*impl));
|
|
|
@@ -140,11 +151,11 @@ struct filter_stream_iterator {
|
|
|
return tmp;
|
|
|
}
|
|
|
|
|
|
- bool operator==(const filter_stream_iterator& other) const {
|
|
|
+ bool operator==(const filter_stream_iterator & other) const {
|
|
|
return impl == other.impl;
|
|
|
}
|
|
|
|
|
|
- bool operator!=(const filter_stream_iterator& other) const {
|
|
|
+ bool operator!=(const filter_stream_iterator & other) const {
|
|
|
return impl != other.impl;
|
|
|
}
|
|
|
|
|
|
@@ -152,40 +163,48 @@ struct filter_stream_iterator {
|
|
|
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>> {
|
|
|
+ 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) {}
|
|
|
+ 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); }
|
|
|
+ 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 {
|
|
|
+ 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 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++() {
|
|
|
+
|
|
|
+ cons_stream_iterator & operator++() {
|
|
|
if (scurr == send) {
|
|
|
++citer;
|
|
|
scurr = citer->begin();
|
|
|
@@ -201,46 +220,50 @@ struct cons_stream_iterator {
|
|
|
operator++();
|
|
|
return tmp;
|
|
|
}
|
|
|
-
|
|
|
- bool operator==(const cons_stream_iterator& other) const {
|
|
|
+
|
|
|
+ bool operator==(const cons_stream_iterator & other) const {
|
|
|
return citer == other.citer && scurr == other.scurr;
|
|
|
}
|
|
|
|
|
|
- bool operator!=(const cons_stream_iterator& other) const {
|
|
|
+ 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>>> {
|
|
|
+ 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 {
|
|
|
+ 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 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));
|
|
|
@@ -250,7 +273,7 @@ struct flatmap_stream_iterator {
|
|
|
return *curr;
|
|
|
}
|
|
|
|
|
|
- flatmap_stream_iterator& operator++() {
|
|
|
+ flatmap_stream_iterator & operator++() {
|
|
|
++curr;
|
|
|
if (curr == end) {
|
|
|
++generator;
|
|
|
@@ -265,47 +288,57 @@ struct flatmap_stream_iterator {
|
|
|
operator++();
|
|
|
return tmp;
|
|
|
}
|
|
|
+
|
|
|
private:
|
|
|
GenIter generator;
|
|
|
- MapStream* mapped = nullptr;
|
|
|
+ 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 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;
|
|
|
+ }
|
|
|
|
|
|
-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;
|
|
|
-}
|
|
|
-
|
|
|
-}
|
|
|
-
|