Commit 12224897 authored by neverlord's avatar neverlord

fixed_vector for pattern matching

parent 52331a6c
...@@ -42,7 +42,6 @@ libcppa_la_SOURCES = \ ...@@ -42,7 +42,6 @@ libcppa_la_SOURCES = \
src/native_socket.cpp \ src/native_socket.cpp \
src/network_manager.cpp \ src/network_manager.cpp \
src/object_array.cpp \ src/object_array.cpp \
src/pattern.cpp \
src/object.cpp \ src/object.cpp \
src/post_office.cpp \ src/post_office.cpp \
src/post_office_msg.cpp \ src/post_office_msg.cpp \
...@@ -186,6 +185,7 @@ nobase_library_include_HEADERS = \ ...@@ -186,6 +185,7 @@ nobase_library_include_HEADERS = \
cppa/util/fiber.hpp \ cppa/util/fiber.hpp \
cppa/util/filter_type_list.hpp \ cppa/util/filter_type_list.hpp \
cppa/util/first_n.hpp \ cppa/util/first_n.hpp \
cppa/util/fixed_vector.hpp \
cppa/util/has_copy_member_fun.hpp \ cppa/util/has_copy_member_fun.hpp \
cppa/util.hpp \ cppa/util.hpp \
cppa/util/if_else.hpp \ cppa/util/if_else.hpp \
......
...@@ -229,6 +229,6 @@ src/addressed_message.cpp ...@@ -229,6 +229,6 @@ src/addressed_message.cpp
unit_testing/test__yield_interface.cpp unit_testing/test__yield_interface.cpp
cppa/anything.hpp cppa/anything.hpp
cppa/pattern.hpp cppa/pattern.hpp
src/pattern.cpp
cppa/detail/pattern_details.hpp cppa/detail/pattern_details.hpp
unit_testing/test__pattern.cpp unit_testing/test__pattern.cpp
cppa/util/fixed_vector.hpp
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/detail/abstract_tuple.hpp" #include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/serialize_tuple.hpp" #include "cppa/detail/serialize_tuple.hpp"
...@@ -20,12 +21,13 @@ class decorated_tuple : public abstract_tuple ...@@ -20,12 +21,13 @@ class decorated_tuple : public abstract_tuple
public: public:
typedef util::fixed_vector<size_t, sizeof...(ElementTypes)> vector_type;
typedef util::type_list<ElementTypes...> element_types; typedef util::type_list<ElementTypes...> element_types;
typedef cow_ptr<abstract_tuple> ptr_type; typedef cow_ptr<abstract_tuple> ptr_type;
decorated_tuple(const ptr_type& d, decorated_tuple(const ptr_type& d, const vector_type& v)
const std::vector<size_t>& v)
: m_decorated(d), m_mappings(v) : m_decorated(d), m_mappings(v)
{ {
} }
...@@ -68,7 +70,7 @@ class decorated_tuple : public abstract_tuple ...@@ -68,7 +70,7 @@ class decorated_tuple : public abstract_tuple
private: private:
ptr_type m_decorated; ptr_type m_decorated;
std::vector<size_t> m_mappings; vector_type m_mappings;
element_types m_types; element_types m_types;
decorated_tuple(const decorated_tuple& other) decorated_tuple(const decorated_tuple& other)
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "cppa/invoke.hpp" #include "cppa/invoke.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/detail/intermediate.hpp" #include "cppa/detail/intermediate.hpp"
// forward declaration // forward declaration
...@@ -100,6 +101,8 @@ class invokable_impl : public invokable ...@@ -100,6 +101,8 @@ class invokable_impl : public invokable
}; };
typedef util::fixed_vector<size_t, TupleView::num_elements> vector_type;
std::unique_ptr<Pattern> m_pattern; std::unique_ptr<Pattern> m_pattern;
TargetFun m_target; TargetFun m_target;
iimpl m_iimpl; iimpl m_iimpl;
...@@ -113,7 +116,8 @@ class invokable_impl : public invokable ...@@ -113,7 +116,8 @@ class invokable_impl : public invokable
bool invoke(const any_tuple& data) const bool invoke(const any_tuple& data) const
{ {
std::vector<size_t> mv;
vector_type mv;
if ((*m_pattern)(data, &mv)) if ((*m_pattern)(data, &mv))
{ {
if (mv.size() == data.size()) if (mv.size() == data.size())
...@@ -125,7 +129,7 @@ class invokable_impl : public invokable ...@@ -125,7 +129,7 @@ class invokable_impl : public invokable
else else
{ {
// mapping needed // mapping needed
TupleView tv(data.vals(), std::move(mv)); TupleView tv(data.vals(), mv);
cppa::invoke(m_target, tv); cppa::invoke(m_target, tv);
} }
return true; return true;
...@@ -135,7 +139,7 @@ class invokable_impl : public invokable ...@@ -135,7 +139,7 @@ class invokable_impl : public invokable
intermediate* get_intermediate(const any_tuple& data) intermediate* get_intermediate(const any_tuple& data)
{ {
std::vector<size_t> mv; vector_type mv;
if ((*m_pattern)(data, &mv)) if ((*m_pattern)(data, &mv))
{ {
if (mv.size() == data.size()) if (mv.size() == data.size())
...@@ -145,7 +149,7 @@ class invokable_impl : public invokable ...@@ -145,7 +149,7 @@ class invokable_impl : public invokable
} }
else else
{ {
m_iimpl.m_args = TupleView(data.vals(), std::move(mv)); m_iimpl.m_args = TupleView(data.vals(), mv);
} }
return &m_iimpl; return &m_iimpl;
} }
......
...@@ -137,20 +137,23 @@ struct pattern_arg ...@@ -137,20 +137,23 @@ struct pattern_arg
}; };
template<typename VectorType>
struct tuple_iterator_arg struct tuple_iterator_arg
{ {
typedef VectorType vector_type;
util::any_tuple_iterator iter; util::any_tuple_iterator iter;
std::vector<size_t>* mapping; vector_type* mapping;
inline tuple_iterator_arg(const any_tuple& tup, inline tuple_iterator_arg(const any_tuple& tup,
std::vector<size_t>* mv = nullptr) vector_type* mv = nullptr)
: iter(tup), mapping(mv) : iter(tup), mapping(mv)
{ {
} }
inline tuple_iterator_arg(const util::any_tuple_iterator& from_iter, inline tuple_iterator_arg(const util::any_tuple_iterator& from_iter,
std::vector<size_t>* mv = nullptr) vector_type* mv = nullptr)
: iter(from_iter), mapping(mv) : iter(from_iter), mapping(mv)
{ {
} }
...@@ -181,7 +184,61 @@ struct tuple_iterator_arg ...@@ -181,7 +184,61 @@ struct tuple_iterator_arg
}; };
bool do_match(pattern_arg& ty_args, tuple_iterator_arg& tu_args); template<typename VectorType>
bool do_match(pattern_arg& pargs, tuple_iterator_arg<VectorType>& targs)
{
if (pargs.at_end() && targs.at_end())
{
return true;
}
if (pargs.type() == nullptr) // nullptr == wildcard
{
// perform submatching
pargs.next();
if (pargs.at_end())
{
// always true at the end of the pattern
return true;
}
auto pargs_copy = pargs;
VectorType mv;
auto mv_ptr = (targs.mapping) ? &mv : nullptr;
// iterate over tu_args until we found a match
while (targs.at_end() == false)
{
tuple_iterator_arg<VectorType> targs_copy(targs.iter, mv_ptr);
if (do_match(pargs_copy, targs_copy))
{
if (mv_ptr)
{
targs.mapping->insert(targs.mapping->end(),
mv.begin(),
mv.end());
}
return true;
}
// next iteration
mv.clear();
targs.next();
}
}
else
{
// compare types
if (targs.at_end() == false && pargs.type() == targs.type())
{
// compare values if needed
if ( pargs.has_value() == false
|| pargs.type()->equal(pargs.value(), targs.value()))
{
targs.push_mapping();
// submatch
return do_match(pargs.next(), targs.next());
}
}
}
return false;
}
} } // namespace cppa::detail } } // namespace cppa::detail
......
...@@ -17,11 +17,11 @@ template<typename... MatchRules> ...@@ -17,11 +17,11 @@ template<typename... MatchRules>
typename tuple_view_type_from_type_list<typename util::filter_type_list<anything, util::type_list<MatchRules...>>::type>::type typename tuple_view_type_from_type_list<typename util::filter_type_list<anything, util::type_list<MatchRules...>>::type>::type
get_view(const any_tuple& ut) get_view(const any_tuple& ut)
{ {
std::vector<size_t> mappings;
pattern<MatchRules...> p; pattern<MatchRules...> p;
if (p(ut, &mappings)) typename pattern<MatchRules...>::mapping_vector mapping;
if (p(ut, &mapping))
{ {
return { ut.vals(), std::move(mappings) }; return { ut.vals(), mapping };
} }
// todo: throw nicer exception // todo: throw nicer exception
throw std::runtime_error("doesn't match"); throw std::runtime_error("doesn't match");
......
...@@ -33,6 +33,11 @@ class pattern<T0, Tn...> ...@@ -33,6 +33,11 @@ class pattern<T0, Tn...>
typedef typename util::filter_type_list<anything, tpl_args>::type typedef typename util::filter_type_list<anything, tpl_args>::type
filtered_tpl_args; filtered_tpl_args;
typedef typename tuple_view_type_from_type_list<filtered_tpl_args>::type
tuple_view_type;
typedef typename tuple_view_type::mapping_vector mapping_vector;
//typedef typename detail::tdata_from_type_list<filtered_tpl_args>::type //typedef typename detail::tdata_from_type_list<filtered_tpl_args>::type
// data_type; // data_type;
...@@ -54,11 +59,12 @@ class pattern<T0, Tn...> ...@@ -54,11 +59,12 @@ class pattern<T0, Tn...>
m_utis, m_data_ptr); m_utis, m_data_ptr);
} }
// todo: calculate expected vector type
bool operator()(const cppa::any_tuple& msg, bool operator()(const cppa::any_tuple& msg,
std::vector<size_t>* mapping = nullptr) const mapping_vector* mapping = nullptr) const
{ {
detail::pattern_arg arg0(size, m_data_ptr, m_utis); detail::pattern_arg arg0(size, m_data_ptr, m_utis);
detail::tuple_iterator_arg arg1(msg, mapping); detail::tuple_iterator_arg<mapping_vector> arg1(msg, mapping);
return detail::do_match(arg0, arg1); return detail::do_match(arg0, arg1);
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "cppa/util/at.hpp" #include "cppa/util/at.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/a_matches_b.hpp" #include "cppa/util/a_matches_b.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/compare_tuples.hpp" #include "cppa/util/compare_tuples.hpp"
#include "cppa/detail/decorated_tuple.hpp" #include "cppa/detail/decorated_tuple.hpp"
...@@ -25,21 +26,19 @@ template<typename... ElementTypes> ...@@ -25,21 +26,19 @@ template<typename... ElementTypes>
class tuple_view class tuple_view
{ {
//static_assert(sizeof...(ElementTypes) > 0,
// "could not declare an empty tuple_view");
template<size_t N, typename... Types> template<size_t N, typename... Types>
friend typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>&); friend typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>&);
public: public:
typedef util::type_list<ElementTypes...> element_types; typedef cow_ptr<detail::abstract_tuple> vals_t;
// enable use of tuple_view as type_list
typedef typename element_types::head_type head_type;
typedef typename element_types::tail_type tail_type;
static_assert(sizeof...(ElementTypes) > 0, static constexpr size_t num_elements = sizeof...(ElementTypes);
"could not declare an empty tuple_view");
typedef cow_ptr<detail::abstract_tuple> vals_t; typedef util::fixed_vector<size_t, num_elements> mapping_vector;
tuple_view() : m_vals(tuple<ElementTypes...>().vals()) { } tuple_view() : m_vals(tuple<ElementTypes...>().vals()) { }
...@@ -53,8 +52,8 @@ class tuple_view ...@@ -53,8 +52,8 @@ class tuple_view
return tuple_view(std::move(vals)); return tuple_view(std::move(vals));
} }
tuple_view(const vals_t& vals, std::vector<size_t>&& mappings) tuple_view(const vals_t& vals, mapping_vector& mapping)
: m_vals(new detail::decorated_tuple<ElementTypes...>(vals, mappings)) : m_vals(new detail::decorated_tuple<ElementTypes...>(vals, mapping))
{ {
} }
...@@ -81,14 +80,10 @@ class tuple_view ...@@ -81,14 +80,10 @@ class tuple_view
return m_vals; return m_vals;
} }
/*inline const element_types& types() const
{
//return m_types;
}*/
inline size_t size() const inline size_t size() const
{ {
return m_vals->size(); return sizeof...(ElementTypes);
//return m_vals->size();
} }
private: private:
......
#ifndef FIXED_VECTOR_HPP
#define FIXED_VECTOR_HPP
#include <algorithm>
#include <stdexcept>
namespace cppa { namespace util {
// @warning does not perform any bound checks
template<typename T, size_t MaxSize>
class fixed_vector
{
size_t m_size;
// support for MaxSize == 0
T m_data[(MaxSize > 0) ? MaxSize : 1];
public:
typedef size_t size_type;
typedef T& reference;
typedef const T& const_reference;
typedef T* iterator;
typedef const T* const_iterator;
constexpr fixed_vector() : m_size(0)
{
}
fixed_vector(const fixed_vector& other) : m_size(other.m_size)
{
std::copy(other.m_data, other.m_data + other.m_size, m_data);
}
inline size_type size() const
{
return m_size;
}
inline void clear()
{
m_size = 0;
}
inline bool full() const
{
return m_size == MaxSize;
}
inline void push_back(const T& what)
{
m_data[m_size++] = what;
}
inline void push_back(T&& what)
{
m_data[m_size++] = std::move(what);
}
inline reference operator[](size_t pos)
{
return m_data[pos];
}
inline const_reference operator[](size_t pos) const
{
return m_data[pos];
}
inline iterator begin()
{
return m_data;
}
inline const_iterator begin() const
{
return m_data;
}
inline iterator end()
{
return (static_cast<T*>(m_data) + m_size);
}
inline const_iterator end() const
{
return (static_cast<T*>(m_data) + m_size);
}
template<class InputIterator>
inline void insert(iterator pos,
InputIterator first,
InputIterator last)
{
if (pos == end())
{
for (InputIterator i = first; i != last; ++i)
{
push_back(*i);
}
}
else
{
throw std::runtime_error("not implemented fixed_vector::insert");
}
}
};
} } // namespace cppa::util
#endif // FIXED_VECTOR_HPP
#include "cppa/pattern.hpp"
namespace cppa { namespace detail {
bool do_match(pattern_arg& pargs, tuple_iterator_arg& targs)
{
if (pargs.at_end() && targs.at_end())
{
return true;
}
if (pargs.type() == nullptr) // nullptr == wildcard
{
// perform submatching
pargs.next();
if (pargs.at_end())
{
// always true at the end of the pattern
return true;
}
auto pargs_copy = pargs;
std::vector<size_t> mv;
auto mv_ptr = (targs.mapping) ? &mv : nullptr;
// iterate over tu_args until we found a match
while (targs.at_end() == false)
{
tuple_iterator_arg targs_copy(targs.iter, mv_ptr);
if (do_match(pargs_copy, targs_copy))
{
if (mv_ptr)
{
targs.mapping->insert(targs.mapping->end(),
mv.begin(),
mv.end());
}
return true;
}
// next iteration
mv.clear();
targs.next();
}
}
else
{
// compare types
if (targs.at_end() == false && pargs.type() == targs.type())
{
// compare values if needed
if ( pargs.has_value() == false
|| pargs.type()->equal(pargs.value(), targs.value()))
{
targs.push_mapping();
// submatch
return do_match(pargs.next(), targs.next());
}
}
}
return false;
}
} } // namespace cppa::detail
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