Commit 1bede491 authored by Dominik Charousset's avatar Dominik Charousset

added match_stream functions

parent 5b11dc0f
...@@ -31,11 +31,17 @@ ...@@ -31,11 +31,17 @@
#ifndef CPPA_MATCH_HPP #ifndef CPPA_MATCH_HPP
#define CPPA_MATCH_HPP #define CPPA_MATCH_HPP
#include <vector>
#include <istream>
#include <iterator>
#include <type_traits> #include <type_traits>
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/type_list.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
struct match_helper { struct match_helper {
...@@ -126,6 +132,165 @@ struct pmatch_each_helper { ...@@ -126,6 +132,165 @@ struct pmatch_each_helper {
} }
}; };
// Case is a projection_partial_function_pair
template<typename T, typename InputIterator, class Case>
size_t run_case(std::vector<T>& vec,
bool& match_returned_false,
InputIterator& pos,
const InputIterator& end,
Case& target);
template<size_t N, size_t Size>
struct unwind_and_call {
typedef unwind_and_call<N+1,Size> next;
template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, std::vector<T>& vec, Unwinded&&... args) {
return next::_(target, vec, std::forward<Unwinded>(args)..., vec[N]);
}
template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, bool& sub_result, std::vector<T>& vec, Unwinded&&... args) {
return next::_(target, sub_result, vec, std::forward<Unwinded>(args)..., vec[N]);
}
template<typename T, typename InputIterator, class MatchExpr>
static inline bool _(std::vector<T>& vec, InputIterator& pos, InputIterator end, MatchExpr& ex) {
bool match_returned_false = false;
if (run_case(vec, match_returned_false, pos, end, get<N>(ex.cases())) == 0) {
if (match_returned_false) {
return false;
}
return next::_(vec, pos, end, ex);
}
return true;
}
};
template<size_t Size>
struct unwind_and_call<Size, Size> {
template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, std::vector<T>&, Unwinded&&... args) {
return target.first(target.second, std::forward<Unwinded>(args)...);
}
template<class Target, typename T, typename... Unwinded>
static inline bool _(Target& target, bool& sub_result, std::vector<T>&, Unwinded&&... args) {
return target.first.invoke(target.second, sub_result, std::forward<Unwinded>(args)...);
}
template<typename T, typename... Args>
static inline bool _(std::vector<T>&, Args&&...) { return false; }
};
template<bool EvaluateSubResult> // default = false
struct run_case_impl {
template<class Case, typename T>
static inline bool _(Case& target, std::vector<T>& vec, bool&) {
return unwind_and_call<0, Case::pattern_type::size>::_(target, vec);
}
};
template<>
struct run_case_impl<true> {
template<class Case, typename T>
static inline bool _(Case& target, std::vector<T>& vec, bool& match_returned_false) {
bool sub_result;
if (unwind_and_call<0, Case::pattern_type::size>::_(target, sub_result, vec)) {
if (sub_result == false) {
match_returned_false = true;
}
return true;
}
return false;
}
};
// Case is a projection_partial_function_pair
template<typename T, typename InputIterator, class Case>
size_t run_case(std::vector<T>& vec,
bool& match_returned_false,
InputIterator& pos,
const InputIterator& end,
Case& target) {
static constexpr size_t num_args = Case::pattern_type::size;
typedef typename Case::second_type partial_fun_type;
typedef typename partial_fun_type::result_type result_type;
typedef typename partial_fun_type::arg_types arg_types;
typedef typename util::tl_map<arg_types, util::rm_ref>::type plain_args;
static_assert(num_args > 0,
"empty match expressions are not allowed in stream matching");
static_assert(util::tl_forall<plain_args, util::tbind<std::is_same, T>::template type>::value,
"match_stream<T>: at least one callback argument "
" is not of type T");
while (vec.size() < num_args) {
if (pos == end) {
return 0;
}
vec.emplace_back(*pos++);
}
if (run_case_impl<std::is_same<result_type, bool>::value>::_(target, vec, match_returned_false)) {
if (vec.size() == num_args) {
vec.clear();
}
else {
auto i = vec.begin();
vec.erase(i, i + num_args);
}
return match_returned_false ? 0 : num_args;
}
return 0;
}
template<typename T, typename InputIterator>
class stream_matcher {
public:
typedef InputIterator iter;
stream_matcher(iter first, iter last) : m_pos(first), m_end(last) { }
template<typename... Cases>
bool operator()(match_expr<Cases...>& expr) {
while (m_pos != m_end) {
if (!unwind_and_call<0, match_expr<Cases...>::cases_list::size>::_(m_cache, m_pos, m_end, expr)) {
return false;
}
}
return true;
}
template<typename... Cases>
bool operator()(match_expr<Cases...>&& expr) {
auto tmp = std::move(expr);
return (*this)(tmp);
}
template<typename... Cases>
bool operator()(const match_expr<Cases...>& expr) {
auto tmp = expr;
return (*this)(tmp);
}
template<typename Arg0, typename... Args>
bool operator()(Arg0&& arg0, Args&&... args) {
return (*this)(match_expr_collect(std::forward<Arg0>(arg0),
std::forward<Args>(args)...));
}
private:
iter m_pos;
iter m_end;
std::vector<T> m_cache;
};
} } // namespace cppa::detail } } // namespace cppa::detail
namespace cppa { namespace cppa {
...@@ -199,6 +364,19 @@ auto match_each(InputIterator first, InputIterator last, Projection proj) ...@@ -199,6 +364,19 @@ auto match_each(InputIterator first, InputIterator last, Projection proj)
return {first, last, std::move(proj)}; return {first, last, std::move(proj)};
} }
template<typename T>
detail::stream_matcher<T, std::istream_iterator<T> > match_stream(std::istream& stream) {
std::istream_iterator<T> first(stream);
std::istream_iterator<T> last; // 'end of stream' iterator
return {first, last};
}
template<typename T, typename InputIterator>
detail::stream_matcher<T, InputIterator> match_stream(InputIterator first,
InputIterator last ) {
return {first, last};
}
} // namespace cppa } // namespace cppa
#endif // CPPA_MATCH_HPP #endif // CPPA_MATCH_HPP
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment