Commit bcafa1b9 authored by neverlord's avatar neverlord

match()

parent 9b2d839e
...@@ -84,6 +84,7 @@ nobase_library_include_HEADERS = \ ...@@ -84,6 +84,7 @@ nobase_library_include_HEADERS = \
cppa/channel.hpp \ cppa/channel.hpp \
cppa/config.hpp \ cppa/config.hpp \
cppa/local_actor.hpp \ cppa/local_actor.hpp \
cppa/match.hpp \
cppa/cow_ptr.hpp \ cppa/cow_ptr.hpp \
cppa/cppa.hpp \ cppa/cppa.hpp \
cppa/deserializer.hpp \ cppa/deserializer.hpp \
...@@ -145,7 +146,6 @@ nobase_library_include_HEADERS = \ ...@@ -145,7 +146,6 @@ nobase_library_include_HEADERS = \
cppa/from_string.hpp \ cppa/from_string.hpp \
cppa/fsm_actor.hpp \ cppa/fsm_actor.hpp \
cppa/get.hpp \ cppa/get.hpp \
cppa/get_view.hpp \
cppa/group.hpp \ cppa/group.hpp \
cppa/intrusive_ptr.hpp \ cppa/intrusive_ptr.hpp \
cppa/invoke_rules.hpp \ cppa/invoke_rules.hpp \
......
...@@ -114,7 +114,6 @@ cppa/announce.hpp ...@@ -114,7 +114,6 @@ cppa/announce.hpp
cppa/util/shared_spinlock.hpp cppa/util/shared_spinlock.hpp
src/shared_spinlock.cpp src/shared_spinlock.cpp
cppa/util/shared_lock_guard.hpp cppa/util/shared_lock_guard.hpp
cppa/get_view.hpp
cppa/detail/object_array.hpp cppa/detail/object_array.hpp
src/object_array.cpp src/object_array.cpp
cppa/any_tuple.hpp cppa/any_tuple.hpp
...@@ -251,3 +250,5 @@ cppa/detail/matches.hpp ...@@ -251,3 +250,5 @@ cppa/detail/matches.hpp
cppa/util/is_mutable_ref.hpp cppa/util/is_mutable_ref.hpp
cppa/util/is_manipulator.hpp cppa/util/is_manipulator.hpp
cppa/util/apply_tuple.hpp cppa/util/apply_tuple.hpp
cppa/any_tuple_view.hpp
cppa/match.hpp
...@@ -92,23 +92,15 @@ class any_tuple ...@@ -92,23 +92,15 @@ class any_tuple
class const_iterator class const_iterator
{ {
any_tuple const& ref; any_tuple const& ref;
size_t p; size_t p;
public: public:
inline const_iterator(any_tuple const& data, size_t pos = 0) inline const_iterator(any_tuple const& data, size_t pos = 0)
: ref(data), p(pos) : ref(data), p(pos) { }
{
}
inline void next() { ++p; } inline void next() { ++p; }
inline bool at_end() const { return p >= ref.size(); } inline bool at_end() const { return p >= ref.size(); }
inline size_t position() const { return p; }
inline void const* value() const { return ref.at(p); } inline void const* value() const { return ref.at(p); }
inline uniform_type_info const* type() const { return ref.type_at(p); } inline uniform_type_info const* type() const { return ref.type_at(p); }
}; };
inline const_iterator begin() const { return {*this}; } inline const_iterator begin() const { return {*this}; }
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef ANY_TUPLE_VIEW_HPP
#define ANY_TUPLE_VIEW_HPP
#include <set>
#include <list>
#include <vector>
#include <utility>
#include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/is_primitive.hpp"
#include "cppa/detail/types_array.hpp"
namespace cppa {
class any_tuple_view
{
typedef std::vector< std::pair<uniform_type_info const*, void const*> >
vector_type;
vector_type m_values;
template<typename T>
void from_list(T const& list)
{
auto& arr = detail::static_types_array<typename T::value_type>::arr;
for (auto i = list.begin(); i != list.end(); ++i)
{
m_values.push_back(std::make_pair(arr[0], &(*i)));
}
}
public:
class const_iterator;
friend class const_iterator;
any_tuple_view(any_tuple_view&&) = default;
any_tuple_view(any_tuple_view const&) = default;
any_tuple_view& operator=(any_tuple_view&&) = default;
any_tuple_view& operator=(any_tuple_view const&) = default;
any_tuple_view(any_tuple const& tup)
{
for (size_t i = 0; i < tup.size(); ++i)
{
m_values.push_back(std::make_pair(tup.type_at(i), tup.at(i)));
}
}
template<typename... T>
explicit any_tuple_view(tuple<T...> const& tup)
{
for (size_t i = 0; i < tup.size(); ++i)
{
m_values.push_back(std::make_pair(tup.type_at(i), tup.at(i)));
}
}
template<typename... T>
any_tuple_view(tuple_view<T...> const& tup)
{
for (size_t i = 0; i < tup.size(); ++i)
{
m_values.push_back(std::make_pair(tup.type_at(i), tup.at(i)));
}
}
template<typename F, typename S>
any_tuple_view(std::pair<F, S> const& pair)
{
auto& arr = detail::static_types_array<F, S>::arr;
m_values.push_back(std::make_pair(arr[0], &pair.first));
m_values.push_back(std::make_pair(arr[1], &pair.second));
}
template<typename T>
any_tuple_view(std::set<T> const& vec) { from_list(vec); }
template<typename T>
any_tuple_view(std::list<T> const& vec) { from_list(vec); }
template<typename T>
any_tuple_view(std::vector<T> const& vec) { from_list(vec); }
template<typename T>
any_tuple_view(T const& val,
typename util::enable_if<util::is_primitive<T> >::type* = 0)
{
auto& arr = detail::static_types_array<T>::arr;
m_values.push_back(std::make_pair(arr[0], &val));
}
inline vector_type const& vals() const { return m_values; }
inline size_t size() const { return m_values.size(); }
inline void const* at(size_t p) const { return m_values[p].second; }
inline uniform_type_info const* type_at(size_t p) const
{
return m_values[p].first;
}
inline bool empty() const { return m_values.empty(); }
template<typename T>
inline T const& get_as(size_t p) const
{
return *reinterpret_cast<T const*>(at(p));
}
class const_iterator
{
typedef typename vector_type::const_iterator vec_iterator;
vec_iterator pos;
vec_iterator end;
public:
inline const_iterator(any_tuple_view const& view)
: pos(view.m_values.begin()), end(view.m_values.end()) { }
inline void next() { ++pos; }
inline bool at_end() const { return pos == end; }
inline void const* value() const { return pos->second; }
inline uniform_type_info const* type() const { return pos->first; }
};
inline const_iterator begin() const { return {*this}; }
};
} // namespace cppa
#endif // ANY_TUPLE_VIEW_HPP
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/tuple_cast.hpp" #include "cppa/tuple_cast.hpp"
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
#include "cppa/any_tuple_view.hpp"
#include "cppa/util/apply_tuple.hpp" #include "cppa/util/apply_tuple.hpp"
#include "cppa/util/fixed_vector.hpp" #include "cppa/util/fixed_vector.hpp"
#include "cppa/util/callable_trait.hpp" #include "cppa/util/callable_trait.hpp"
...@@ -61,6 +62,7 @@ class invokable_base ...@@ -61,6 +62,7 @@ class invokable_base
invokable_base() = default; invokable_base() = default;
virtual ~invokable_base(); virtual ~invokable_base();
virtual bool invoke(any_tuple const&) const = 0; virtual bool invoke(any_tuple const&) const = 0;
virtual bool invoke(any_tuple_view const&) const = 0;
}; };
...@@ -104,6 +106,13 @@ class timed_invokable_impl : public timed_invokable ...@@ -104,6 +106,13 @@ class timed_invokable_impl : public timed_invokable
return true; return true;
} }
bool invoke(any_tuple_view const&) const
{
m_target();
return true;
}
}; };
class invokable : public invokable_base class invokable : public invokable_base
...@@ -129,6 +138,18 @@ class invokable_impl : public invokable ...@@ -129,6 +138,18 @@ class invokable_impl : public invokable
m_iimpl; m_iimpl;
std::unique_ptr<Pattern> m_pattern; std::unique_ptr<Pattern> m_pattern;
template<typename T>
bool invoke_impl(T const& data) const
{
auto tuple_option = tuple_cast(data, *m_pattern);
if (tuple_option.valid())
{
util::apply_tuple(m_iimpl.m_fun, *tuple_option);
return true;
}
return false;
}
public: public:
template<typename F> template<typename F>
...@@ -139,13 +160,12 @@ class invokable_impl : public invokable ...@@ -139,13 +160,12 @@ class invokable_impl : public invokable
bool invoke(any_tuple const& data) const bool invoke(any_tuple const& data) const
{ {
auto tuple_option = tuple_cast(data, *m_pattern); return invoke_impl(data);
if (tuple_option.valid())
{
util::apply_tuple(m_iimpl.m_fun, *tuple_option);
return true;
} }
return false;
bool invoke(any_tuple_view const& data) const
{
return invoke_impl(data);
} }
intermediate* get_intermediate(any_tuple const& data) intermediate* get_intermediate(any_tuple const& data)
...@@ -174,6 +194,17 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable ...@@ -174,6 +194,17 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
m_iimpl; m_iimpl;
std::unique_ptr<Pattern> m_pattern; std::unique_ptr<Pattern> m_pattern;
template<typename T>
bool invoke_impl(T const& data) const
{
if (detail::matches(data.begin(), m_pattern->begin()))
{
m_iimpl.m_fun();
return true;
}
return false;
}
public: public:
template<typename F> template<typename F>
...@@ -184,12 +215,12 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable ...@@ -184,12 +215,12 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
bool invoke(any_tuple const& data) const bool invoke(any_tuple const& data) const
{ {
if (detail::matches(data.begin(), m_pattern->begin())) return invoke_impl(data);
{
m_iimpl.m_fun();
return true;
} }
return false;
bool invoke(any_tuple_view const& data) const
{
return invoke_impl(data);
} }
intermediate* get_intermediate(any_tuple const& data) intermediate* get_intermediate(any_tuple const& data)
...@@ -200,7 +231,6 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable ...@@ -200,7 +231,6 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
}; };
template<typename Fun, class Pattern> template<typename Fun, class Pattern>
struct select_invokable_impl struct select_invokable_impl
{ {
......
...@@ -78,6 +78,7 @@ template<class MappingVector, typename Iterator> ...@@ -78,6 +78,7 @@ template<class MappingVector, typename Iterator>
class push_mapping_decorator class push_mapping_decorator
{ {
size_t pos;
Iterator iter; Iterator iter;
MappingVector* mapping; MappingVector* mapping;
...@@ -86,28 +87,29 @@ class push_mapping_decorator ...@@ -86,28 +87,29 @@ class push_mapping_decorator
typedef MappingVector mapping_vector; typedef MappingVector mapping_vector;
push_mapping_decorator(Iterator const& i, MappingVector* mv) push_mapping_decorator(Iterator const& i, MappingVector* mv)
: iter(i), mapping(mv) : pos(0), iter(i), mapping(mv)
{ {
} }
push_mapping_decorator(push_mapping_decorator const& other, MappingVector* mv) push_mapping_decorator(push_mapping_decorator const& other,
: iter(other.iter), mapping(mv) MappingVector* mv)
: pos(other.pos), iter(other.iter), mapping(mv)
{ {
} }
push_mapping_decorator(push_mapping_decorator&& other) push_mapping_decorator(push_mapping_decorator&& other)
: iter(std::move(other.iter)), mapping(other.mapping) : pos(other.pos), iter(std::move(other.iter)), mapping(other.mapping)
{ {
} }
inline void next() { iter.next(); } inline void next() { ++pos; iter.next(); }
inline bool at_end() const { return iter.at_end(); } inline bool at_end() const { return iter.at_end(); }
inline void const* value() const { return iter.value(); } inline void const* value() const { return iter.value(); }
inline decltype(iter.type()) type() const { return iter.type(); } inline decltype(iter.type()) type() const { return iter.type(); }
inline bool has_mapping() const { return mapping != nullptr; } inline bool has_mapping() const { return mapping != nullptr; }
inline void push_mapping() inline void push_mapping()
{ {
if (mapping) mapping->push_back(iter.position()); if (mapping) mapping->push_back(pos);
} }
inline void push_mapping(MappingVector const& mv) inline void push_mapping(MappingVector const& mv)
{ {
......
...@@ -114,6 +114,34 @@ struct types_array : types_array_impl<util::tl_forall<util::type_list<T...>, ...@@ -114,6 +114,34 @@ struct types_array : types_array_impl<util::tl_forall<util::type_list<T...>,
util::is_builtin>::value, util::is_builtin>::value,
T...> T...>
{ {
class const_iterator
{
types_array const& m_ref;
size_t m_pos;
public:
const_iterator(const_iterator const&) = default;
const_iterator& operator=(const_iterator const&) = default;
const_iterator(types_array const& ptr) : m_ref(ptr), m_pos(0) { }
inline void next() { ++m_pos; }
inline bool at_end() const { return m_pos == sizeof...(T); }
inline uniform_type_info const* type() const
{
return m_ref[m_pos];
}
inline bool has_value() const { return false; }
inline void const* value() const { return nullptr; }
};
const_iterator begin() const { return {*this}; }
}; };
template<typename... T> template<typename... T>
......
...@@ -50,6 +50,7 @@ namespace cppa { ...@@ -50,6 +50,7 @@ namespace cppa {
class any_tuple; class any_tuple;
class invoke_rules; class invoke_rules;
class any_tuple_view;
class timed_invoke_rules; class timed_invoke_rules;
typedef std::list<detail::invokable_ptr> invokable_list; typedef std::list<detail::invokable_ptr> invokable_list;
...@@ -87,6 +88,8 @@ class invoke_rules_base ...@@ -87,6 +88,8 @@ class invoke_rules_base
*/ */
bool operator()(any_tuple const& data) const; bool operator()(any_tuple const& data) const;
bool operator()(any_tuple_view const& data) const;
/** /**
* @brief Tries to match @p data with one of the stored patterns. * @brief Tries to match @p data with one of the stored patterns.
* @param data Data tuple that should be matched. * @param data Data tuple that should be matched.
......
...@@ -28,39 +28,65 @@ ...@@ -28,39 +28,65 @@
\******************************************************************************/ \******************************************************************************/
#ifndef GET_VIEW_HPP #ifndef MATCH_HPP
#define GET_VIEW_HPP #define MATCH_HPP
#include <vector> #include <type_traits>
#include <cstddef>
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/pattern.hpp" #include "cppa/invoke_rules.hpp"
#include "cppa/anything.hpp" #include "cppa/any_tuple_view.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/util/tbind.hpp" #include "cppa/util/if_else.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/enable_if.hpp"
#include "cppa/detail/matches.hpp" #include "cppa/detail/implicit_conversions.hpp"
namespace cppa { namespace cppa {
template<typename... MatchRules> namespace detail {
typename tuple_view_type_from_type_list<typename util::tl_filter_not<util::type_list<MatchRules...>, util::tbind<std::is_same, anything>::type>::type>::type
get_view(any_tuple const& ut) template<typename Tuple>
struct match_helper
{ {
pattern<MatchRules...> p; static constexpr bool is_view = std::is_same<Tuple, any_tuple_view>::value;
typename pattern<MatchRules...>::mapping_vector mapping; Tuple what;
if (detail::matches(detail::pm_decorated(ut.begin(), &mapping), p.begin())) template<typename T>
match_helper(T const& w, typename util::enable_if_c<std::is_same<T, T>::value && is_view>::type* =0)
: what(w) { }
template<typename T>
match_helper(T const& w, typename util::enable_if_c<std::is_same<T, T>::value && !is_view>::type* =0)
: what(make_tuple(w)) { }
void operator()(invoke_rules& rules) { rules(what); }
void operator()(invoke_rules&& rules) { rules(what); }
template<typename Head, typename... Tail>
void operator()(invoke_rules&& bhvr, Head&& head, Tail&&... tail)
{
invoke_rules tmp(std::move(bhvr));
(*this)(tmp.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...);
}
template<typename Head, typename... Tail>
void operator()(invoke_rules& bhvr, Head&& head, Tail&&... tail)
{ {
return { ut.vals(), mapping }; (*this)(bhvr.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...);
} }
// todo: throw nicer exception };
throw std::runtime_error("doesn't match");
} // namespace detail
template<typename T>
auto match(T const& x)
-> detail::match_helper<
typename util::if_else<
std::is_same<typename detail::implicit_conversions<T>::type, T>,
any_tuple_view,
util::wrapped<any_tuple> >::type>
{
return {x};
} }
} // namespace cppa } // namespace cppa
#endif // GET_VIEW_HPP #endif // MATCH_HPP
...@@ -33,31 +33,33 @@ ...@@ -33,31 +33,33 @@
namespace cppa { namespace cppa {
template<typename What> template<typename T>
class option class option
{ {
union union
{ {
What m_value; T m_value;
}; };
bool m_valid; bool m_valid;
void destroy() void destroy()
{ {
if (m_valid) m_value.~What(); if (m_valid) m_value.~T();
} }
template<typename V> template<typename V>
void cr(V&& value) void cr(V&& value)
{ {
m_valid = true; m_valid = true;
new (&m_value) What (std::forward<V>(value)); new (&m_value) T (std::forward<V>(value));
} }
public: public:
typedef T value_type;
option() : m_valid(false) { } option() : m_valid(false) { }
template<typename V> template<typename V>
...@@ -131,14 +133,14 @@ class option ...@@ -131,14 +133,14 @@ class option
return *this; return *this;
} }
option& operator=(What const& value) option& operator=(T const& value)
{ {
if (m_valid) m_value = value; if (m_valid) m_value = value;
else cr(value); else cr(value);
return *this; return *this;
} }
option& operator=(What& value) option& operator=(T& value)
{ {
if (m_valid) m_value = std::move(value); if (m_valid) m_value = std::move(value);
else cr(std::move(value)); else cr(std::move(value));
...@@ -151,20 +153,20 @@ class option ...@@ -151,20 +153,20 @@ class option
inline bool operator!() const { return !m_valid; } inline bool operator!() const { return !m_valid; }
inline What& operator*() { return m_value; } inline T& operator*() { return m_value; }
inline What const& operator*() const { return m_value; } inline T const& operator*() const { return m_value; }
inline What& get() { return m_value; } inline T& get() { return m_value; }
inline What const& get() const { return m_value; } inline T const& get() const { return m_value; }
inline What& get_or_else(What const& val) inline T& get_or_else(T const& val)
{ {
if (!m_valid) cr(val); if (!m_valid) cr(val);
return m_value; return m_value;
} }
inline What& get_or_else(What&& val) inline T& get_or_else(T&& val)
{ {
if (!m_valid) cr(std::move(val)); if (!m_valid) cr(std::move(val));
return m_value; return m_value;
......
...@@ -31,18 +31,22 @@ ...@@ -31,18 +31,22 @@
#ifndef LIBCPPA_PATTERN_HPP #ifndef LIBCPPA_PATTERN_HPP
#define LIBCPPA_PATTERN_HPP #define LIBCPPA_PATTERN_HPP
#include <list>
#include <vector> #include <vector>
#include <cstddef> #include <cstddef>
#include <type_traits> #include <type_traits>
#include "cppa/option.hpp"
#include "cppa/anything.hpp" #include "cppa/anything.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/util/tbind.hpp" #include "cppa/util/tbind.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/util/arg_match_t.hpp" #include "cppa/util/arg_match_t.hpp"
#include "cppa/util/fixed_vector.hpp" #include "cppa/util/fixed_vector.hpp"
#include "cppa/util/is_primitive.hpp"
#include "cppa/detail/boxed.hpp" #include "cppa/detail/boxed.hpp"
#include "cppa/detail/tdata.hpp" #include "cppa/detail/tdata.hpp"
...@@ -84,22 +88,13 @@ class pattern ...@@ -84,22 +88,13 @@ class pattern
public: public:
const_iterator(pattern const* ptr) : m_ptr(ptr), m_pos(0) { }
const_iterator(const_iterator const&) = default; const_iterator(const_iterator const&) = default;
const_iterator& operator=(const_iterator const&) = default; const_iterator& operator=(const_iterator const&) = default;
const_iterator(pattern const* ptr) : m_ptr(ptr), m_pos(0) { }
const_iterator& next() inline void next() { ++m_pos; }
{
++m_pos;
return *this;
}
inline bool at_end() inline bool at_end() { return m_pos == sizeof...(Types); }
{
return m_pos == sizeof...(Types);
}
inline uniform_type_info const* type() const inline uniform_type_info const* type() const
{ {
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define TO_STRING_HPP #define TO_STRING_HPP
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/detail/to_uniform_name.hpp"
namespace cppa { namespace cppa {
......
...@@ -42,12 +42,14 @@ ...@@ -42,12 +42,14 @@
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/util/at.hpp" #include "cppa/util/at.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/replace_type.hpp" #include "cppa/util/replace_type.hpp"
#include "cppa/util/is_comparable.hpp" #include "cppa/util/is_comparable.hpp"
#include "cppa/util/compare_tuples.hpp" #include "cppa/util/compare_tuples.hpp"
#include "cppa/util/is_legal_tuple_type.hpp" #include "cppa/util/is_legal_tuple_type.hpp"
#include "cppa/detail/tuple_vals.hpp" #include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/decorated_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp" #include "cppa/detail/implicit_conversions.hpp"
namespace cppa { namespace cppa {
...@@ -84,6 +86,8 @@ class tuple ...@@ -84,6 +86,8 @@ class tuple
public: public:
static constexpr size_t num_elements = sizeof...(ElementTypes);
/** /**
* @brief Initializes each element with its default constructor. * @brief Initializes each element with its default constructor.
*/ */
...@@ -122,6 +126,13 @@ class tuple ...@@ -122,6 +126,13 @@ class tuple
return tuple(ptr_ctor(), ptr); return tuple(ptr_ctor(), ptr);
} }
static tuple from(cow_ptr<detail::abstract_tuple> const& ptr,
util::fixed_vector<size_t, num_elements> const& mv)
{
return tuple(ptr_ctor(),
new detail::decorated_tuple<num_elements>(ptr, mv));
}
/** /**
* @brief Gets the size of this tuple. * @brief Gets the size of this tuple.
* @returns <tt>sizeof...(ElementTypes)</tt>. * @returns <tt>sizeof...(ElementTypes)</tt>.
...@@ -150,7 +161,7 @@ class tuple ...@@ -150,7 +161,7 @@ class tuple
* of an element. * of an element.
* @returns The uniform type of the <tt>N</tt>th element. * @returns The uniform type of the <tt>N</tt>th element.
*/ */
inline uniform_type_info const* utype_at(size_t p) const inline uniform_type_info const* type_at(size_t p) const
{ {
return m_vals->type_at(p); return m_vals->type_at(p);
} }
......
...@@ -31,54 +31,128 @@ ...@@ -31,54 +31,128 @@
#ifndef TUPLE_CAST_HPP #ifndef TUPLE_CAST_HPP
#define TUPLE_CAST_HPP #define TUPLE_CAST_HPP
#include <type_traits>
#include "cppa/option.hpp" #include "cppa/option.hpp"
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/any_tuple_view.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/detail/matches.hpp" #include "cppa/detail/matches.hpp"
#include "cppa/detail/types_array.hpp" #include "cppa/detail/types_array.hpp"
#include "cppa/detail/decorated_tuple.hpp" #include "cppa/detail/decorated_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa { namespace cppa {
// cast using a pattern // cast using a pattern
template<typename... P> template<class ResultTuple, class Tuple, typename... P>
auto tuple_cast(any_tuple const& tup, pattern<P...> const& p) option<ResultTuple> tuple_cast_impl(Tuple const& tup, pattern<P...> const& p)
-> option<typename tuple_from_type_list<typename pattern<P...>::filtered_types>::type>
{ {
typedef typename pattern<P...>::mapping_vector mapping_vector;
typedef typename pattern<P...>::filtered_types filtered_types; typedef typename pattern<P...>::filtered_types filtered_types;
typedef typename tuple_from_type_list<filtered_types>::type tuple_type; typename pattern<P...>::mapping_vector mv;
option<tuple_type> result;
mapping_vector mv;
if (detail::matches(detail::pm_decorated(tup.begin(), &mv), p.begin())) if (detail::matches(detail::pm_decorated(tup.begin(), &mv), p.begin()))
{ {
if (mv.size() == tup.size()) // perfect match if (mv.size() == tup.size()) // perfect match
{ {
result = tuple_type::from(tup.vals()); return {ResultTuple::from(tup.vals())};
} }
else else
{ {
result = tuple_type::from(new detail::decorated_tuple<filtered_types::size>(tup.vals(), mv)); typedef detail::decorated_tuple<filtered_types::size> decorated;
return {ResultTuple::from(tup.vals(), mv)};
} }
} }
return std::move(result); return { };
} }
// cast using types // cast using types
template<typename... T> template<class ResultTuple, class Tuple, typename... T>
option< tuple<T...> > tuple_cast(any_tuple const& tup) option<ResultTuple> tuple_cast_impl(Tuple const& tup)
{ {
option< tuple<T...> > result; // no anything in given template parameter pack
if (ResultTuple::num_elements == sizeof...(T))
{
auto& tarr = detail::static_types_array<T...>::arr; auto& tarr = detail::static_types_array<T...>::arr;
if (tup.size() == sizeof...(T)) if (tup.size() == sizeof...(T))
{ {
for (size_t i = 0; i < sizeof...(T); ++i) for (size_t i = 0; i < sizeof...(T); ++i)
{ {
if (tarr[i] != tup.type_at(i)) return std::move(result); if (tarr[i] != tup.type_at(i)) return { };
}
// always a perfect match
return {ResultTuple::from(tup.vals())};
}
}
else
{
util::fixed_vector<size_t, ResultTuple::num_elements> mv;
if (detail::matches(detail::pm_decorated(tup.begin(), &mv),
detail::static_types_array<T...>::arr.begin()))
{
// never a perfect match
typedef detail::decorated_tuple<ResultTuple::num_elements> decorated;
return {ResultTuple::from(tup.vals(), mv)};
} }
result = tuple<T...>::from(tup.vals());
} }
return std::move(result);; return { };
}
// cast using a pattern
template<typename... P>
auto tuple_cast(any_tuple const& tup, pattern<P...> const& p)
-> option<
typename tuple_from_type_list<
typename pattern<P...>::filtered_types
>::type>
{
typedef typename pattern<P...>::filtered_types filtered_types;
typedef typename tuple_from_type_list<filtered_types>::type tuple_type;
return tuple_cast_impl<tuple_type, any_tuple, P...>(tup, p);
}
// cast using types
template<typename... T>
auto tuple_cast(any_tuple const& tup)
-> option<
typename tuple_from_type_list<
typename util::tl_filter_not<
util::type_list<T...>,
util::tbind<std::is_same, anything>::type
>::type
>::type>
{
typedef decltype(tuple_cast<T...>(tup)) result_type;
typedef typename result_type::value_type tuple_type;
return tuple_cast_impl<tuple_type, any_tuple, T...>(tup);
}
template<typename... P>
auto tuple_cast(any_tuple_view const& tup, pattern<P...> const& p)
-> option<
typename tuple_view_from_type_list<
typename pattern<P...>::filtered_types
>::type>
{
typedef typename pattern<P...>::filtered_types filtered_types;
typedef typename tuple_view_from_type_list<filtered_types>::type tuple_type;
return tuple_cast_impl<tuple_type, any_tuple_view, P...>(tup, p);
}
// cast using types
template<typename... T>
auto tuple_cast(any_tuple_view const& tup)
-> option<
typename tuple_view_from_type_list<
typename util::tl_filter_not<
util::type_list<T...>,
util::tbind<std::is_same, anything>::type
>::type
>::type>
{
typedef decltype(tuple_cast<T...>(tup)) result_type;
typedef typename result_type::value_type tuple_type;
return tuple_cast_impl<tuple_type, any_tuple_view, T...>(tup);
} }
} // namespace cppa } // namespace cppa
......
...@@ -32,9 +32,11 @@ ...@@ -32,9 +32,11 @@
#define TUPLE_VIEW_HPP #define TUPLE_VIEW_HPP
#include <vector> #include <vector>
#include <cstring>
#include "cppa/get.hpp" #include "cppa/get.hpp"
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/util/at.hpp" #include "cppa/util/at.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
...@@ -58,52 +60,45 @@ class tuple_view ...@@ -58,52 +60,45 @@ class 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: void const* m_data[sizeof...(ElementTypes)];
typedef cow_ptr<detail::abstract_tuple> vals_t;
static constexpr size_t num_elements = sizeof...(ElementTypes); tuple_view() { }
typedef util::fixed_vector<size_t, num_elements> mapping_vector; public:
tuple_view() : m_vals(tuple<ElementTypes...>().vals()) { } static constexpr size_t num_elements = sizeof...(ElementTypes);
static tuple_view from(vals_t const& vals) static tuple_view from(std::vector< std::pair<uniform_type_info const*, void const*> > const& vec)
{ {
return tuple_view(vals); tuple_view result;
} size_t j = 0;
for (auto i = vec.begin(); i != vec.end(); ++i)
static tuple_view from(vals_t&& vals)
{ {
return tuple_view(std::move(vals)); result.m_data[j++] = i->second;
} }
return std::move(result);
tuple_view(vals_t const& vals, mapping_vector& mapping)
: m_vals(new detail::decorated_tuple<num_elements>(vals, mapping))
{
} }
tuple_view(tuple_view&& other) : m_vals(std::move(other.m_vals)) static tuple_view from(std::vector< std::pair<uniform_type_info const*, void const*> > const& vec,
util::fixed_vector<size_t, sizeof...(ElementTypes)> const& mv)
{ {
} tuple_view result;
for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
tuple_view& operator=(tuple_view const& other)
{ {
m_vals = other.m_vals; result.m_data[i] = vec[mv[i]].second;
return *this; }
return std::move(result);
} }
tuple_view& operator=(tuple_view&& other) tuple_view& operator=(tuple_view const& other)
{ {
m_vals = std::move(other.m_vals); memcpy(m_data, other.m_data, num_elements * sizeof(void*));
return *this; return *this;
} }
tuple_view(tuple_view const&) = default; tuple_view(tuple_view const& other)
inline vals_t const& vals() const
{ {
return m_vals; memcpy(m_data, other.m_data, num_elements * sizeof(void*));
} }
inline size_t size() const inline size_t size() const
...@@ -111,17 +106,7 @@ class tuple_view ...@@ -111,17 +106,7 @@ class tuple_view
return sizeof...(ElementTypes); return sizeof...(ElementTypes);
} }
private: inline void const* at(size_t p) const { return m_data[p]; }
explicit tuple_view(vals_t const& vals) : m_vals(vals)
{
}
explicit tuple_view(vals_t&& vals) : m_vals(std::move(vals))
{
}
vals_t m_vals;
}; };
...@@ -130,22 +115,22 @@ const typename util::at<N, Types...>::type& get(tuple_view<Types...> const& t) ...@@ -130,22 +115,22 @@ const typename util::at<N, Types...>::type& get(tuple_view<Types...> const& t)
{ {
static_assert(N < sizeof...(Types), "N >= t.size()"); static_assert(N < sizeof...(Types), "N >= t.size()");
typedef typename util::at<N, Types...>::type result_t; typedef typename util::at<N, Types...>::type result_t;
return *reinterpret_cast<result_t const*>(t.vals()->at(N)); return *reinterpret_cast<result_t const*>(t.at(N));
} }
template<size_t N, typename... Types> //template<size_t N, typename... Types>
typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>& t) //typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>& t)
{ //{
static_assert(N < sizeof...(Types), "N >= t.size()"); // static_assert(N < sizeof...(Types), "N >= t.size()");
typedef typename util::at<N, Types...>::type result_t; // typedef typename util::at<N, Types...>::type result_t;
return *reinterpret_cast<result_t*>(t.m_vals->mutable_at(N)); // return *reinterpret_cast<result_t*>(t.m_vals->mutable_at(N));
} //}
template<typename TypeList> template<typename TypeList>
struct tuple_view_type_from_type_list; struct tuple_view_from_type_list;
template<typename... Types> template<typename... Types>
struct tuple_view_type_from_type_list<util::type_list<Types...>> struct tuple_view_from_type_list<util::type_list<Types...>>
{ {
typedef tuple_view<Types...> type; typedef tuple_view<Types...> type;
}; };
......
...@@ -39,7 +39,7 @@ struct offset_decorator : cppa::detail::abstract_tuple ...@@ -39,7 +39,7 @@ struct offset_decorator : cppa::detail::abstract_tuple
typedef cppa::cow_ptr<cppa::detail::abstract_tuple> ptr_type; typedef cppa::cow_ptr<cppa::detail::abstract_tuple> ptr_type;
offset_decorator(const ptr_type& decorated, size_t offset) offset_decorator(ptr_type const& decorated, size_t offset)
: m_offset(offset) : m_offset(offset)
, m_decorated(decorated) , m_decorated(decorated)
{ {
...@@ -99,7 +99,7 @@ any_tuple::any_tuple(any_tuple&& other) : m_vals(s_empty_tuple()) ...@@ -99,7 +99,7 @@ any_tuple::any_tuple(any_tuple&& other) : m_vals(s_empty_tuple())
m_vals.swap(other.m_vals); m_vals.swap(other.m_vals);
} }
any_tuple::any_tuple(const cow_ptr<detail::abstract_tuple>& vals) : m_vals(vals) any_tuple::any_tuple(cow_ptr<detail::abstract_tuple> const& vals) : m_vals(vals)
{ {
} }
...@@ -141,7 +141,7 @@ const cow_ptr<detail::abstract_tuple>& any_tuple::vals() const ...@@ -141,7 +141,7 @@ const cow_ptr<detail::abstract_tuple>& any_tuple::vals() const
return m_vals; return m_vals;
} }
bool any_tuple::equals(const any_tuple& other) const bool any_tuple::equals(any_tuple const& other) const
{ {
return m_vals->equals(*other.vals()); return m_vals->equals(*other.vals());
} }
......
...@@ -46,11 +46,20 @@ invoke_rules_base::~invoke_rules_base() ...@@ -46,11 +46,20 @@ invoke_rules_base::~invoke_rules_base()
{ {
} }
bool invoke_rules_base::operator()(const any_tuple& t) const bool invoke_rules_base::operator()(const any_tuple& data) const
{ {
for (auto i = m_list.begin(); i != m_list.end(); ++i) for (detail::invokable_ptr const& ptr : m_list)
{ {
if ((*i)->invoke(t)) return true; if (ptr->invoke(data)) return true;
}
return false;
}
bool invoke_rules_base::operator()(any_tuple_view const& data) const
{
for (detail::invokable_ptr const& ptr : m_list)
{
if (ptr->invoke(data)) return true;
} }
return false; return false;
} }
...@@ -59,9 +68,9 @@ detail::intermediate* ...@@ -59,9 +68,9 @@ detail::intermediate*
invoke_rules_base::get_intermediate(const any_tuple& t) const invoke_rules_base::get_intermediate(const any_tuple& t) const
{ {
detail::intermediate* result; detail::intermediate* result;
for (auto i = m_list.begin(); i != m_list.end(); ++i) for (detail::invokable_ptr const& ptr : m_list)
{ {
result = (*i)->get_intermediate(t); result = ptr->get_intermediate(t);
if (result != nullptr) return result; if (result != nullptr) return result;
} }
return nullptr; return nullptr;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "cppa/on.hpp" #include "cppa/on.hpp"
#include "cppa/atom.hpp" #include "cppa/atom.hpp"
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/match.hpp"
#include "cppa/option.hpp" #include "cppa/option.hpp"
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
...@@ -42,37 +43,29 @@ typedef std::pair<int,int> foobar; ...@@ -42,37 +43,29 @@ typedef std::pair<int,int> foobar;
static detail::types_array<int,anything,float> arr1; static detail::types_array<int,anything,float> arr1;
static detail::types_array<int,anything,foobar> arr2; static detail::types_array<int,anything,foobar> arr2;
struct match_helper template<typename T>
void match_test(T const& value)
{ {
any_tuple const& what; match(value)
match_helper(any_tuple const& w) : what(w) { } (
void operator()(invoke_rules&& rules) on<int, int, int, anything>() >> [&](int a, int b, int c)
{
cout << "(" << a << ", " << b << ", " << c << ")" << endl;
},
on_arg_match >> [&](std::string const& str)
{ {
rules(what); cout << str << endl;
} }
}; );
using namespace cppa::util;
match_helper match(any_tuple const& x)
{
return { x };
} }
size_t test__pattern() size_t test__pattern()
{ {
CPPA_TEST(test__pattern); CPPA_TEST(test__pattern);
match(make_tuple(1,2,3)) match_test(make_tuple(1,2,3));
( match_test(std::list<int>{1, 2, 3});
on_arg_match >> [&](int a, int b, int c) match_test("abc");
{
CPPA_CHECK_EQUAL(a, 1);
CPPA_CHECK_EQUAL(b, 2);
CPPA_CHECK_EQUAL(c, 3);
}
);
pattern<int, anything, int> i3; pattern<int, anything, int> i3;
any_tuple i3_any_tup = make_tuple(1, 2, 3); any_tuple i3_any_tup = make_tuple(1, 2, 3);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "cppa/on.hpp" #include "cppa/on.hpp"
#include "cppa/util.hpp" #include "cppa/util.hpp"
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/pattern.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/tuple_cast.hpp" #include "cppa/tuple_cast.hpp"
...@@ -38,13 +39,25 @@ size_t test__tuple() ...@@ -38,13 +39,25 @@ size_t test__tuple()
CPPA_CHECK((std::is_same<decltype(t0_1), int>::value)); CPPA_CHECK((std::is_same<decltype(t0_1), int>::value));
CPPA_CHECK_EQUAL(t0_0, "1"); CPPA_CHECK_EQUAL(t0_0, "1");
CPPA_CHECK_EQUAL(t0_1, 2); CPPA_CHECK_EQUAL(t0_1, 2);
// create a view of t0 that only contains the string // get a view of t0
auto v0opt = tuple_cast(t0, pattern<std::string, anything>()); auto v1opt = tuple_cast<std::string, anything>(any_tuple_view(t0));
if (!v0opt) throw std::runtime_error("tuple_cast failed!"); CPPA_CHECK((v1opt));
if (v1opt)
{
auto& v1 = *v1opt;
auto v1_0 = get<0>(v1);
CPPA_CHECK_EQUAL(v1.size(), 1);
CPPA_CHECK_EQUAL(v1_0, "1");
}
// use tuple cast to get a subtuple
auto v0opt = tuple_cast<std::string, anything>(t0);
CPPA_CHECK((v0opt));
if (v0opt)
{
auto& v0 = *v0opt; auto& v0 = *v0opt;
auto v0_0 = get<0>(v0); auto v0_0 = get<0>(v0);
CPPA_CHECK_EQUAL(v0.size(), 1);
CPPA_CHECK((std::is_same<decltype(v0_0), std::string>::value)); CPPA_CHECK((std::is_same<decltype(v0_0), std::string>::value));
CPPA_CHECK_EQUAL(v0.size(), 1);
CPPA_CHECK_EQUAL(v0_0, "1"); CPPA_CHECK_EQUAL(v0_0, "1");
// check cow semantics // check cow semantics
CPPA_CHECK_EQUAL(&get<0>(t0), &get<0>(v0)); // point to the same string CPPA_CHECK_EQUAL(&get<0>(t0), &get<0>(v0)); // point to the same string
...@@ -57,5 +70,6 @@ size_t test__tuple() ...@@ -57,5 +70,6 @@ size_t test__tuple()
auto rhs = make_tuple(static_cast<std::uint8_t>(1), 2.0, 3, 4); auto rhs = make_tuple(static_cast<std::uint8_t>(1), 2.0, 3, 4);
CPPA_CHECK_EQUAL(lhs, rhs); CPPA_CHECK_EQUAL(lhs, rhs);
CPPA_CHECK_EQUAL(rhs, lhs); CPPA_CHECK_EQUAL(rhs, lhs);
}
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
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