Commit bcafa1b9 authored by neverlord's avatar neverlord

match()

parent 9b2d839e
......@@ -84,6 +84,7 @@ nobase_library_include_HEADERS = \
cppa/channel.hpp \
cppa/config.hpp \
cppa/local_actor.hpp \
cppa/match.hpp \
cppa/cow_ptr.hpp \
cppa/cppa.hpp \
cppa/deserializer.hpp \
......@@ -145,7 +146,6 @@ nobase_library_include_HEADERS = \
cppa/from_string.hpp \
cppa/fsm_actor.hpp \
cppa/get.hpp \
cppa/get_view.hpp \
cppa/group.hpp \
cppa/intrusive_ptr.hpp \
cppa/invoke_rules.hpp \
......
......@@ -114,7 +114,6 @@ cppa/announce.hpp
cppa/util/shared_spinlock.hpp
src/shared_spinlock.cpp
cppa/util/shared_lock_guard.hpp
cppa/get_view.hpp
cppa/detail/object_array.hpp
src/object_array.cpp
cppa/any_tuple.hpp
......@@ -251,3 +250,5 @@ cppa/detail/matches.hpp
cppa/util/is_mutable_ref.hpp
cppa/util/is_manipulator.hpp
cppa/util/apply_tuple.hpp
cppa/any_tuple_view.hpp
cppa/match.hpp
......@@ -92,23 +92,15 @@ class any_tuple
class const_iterator
{
any_tuple const& ref;
size_t p;
public:
inline const_iterator(any_tuple const& data, size_t pos = 0)
: ref(data), p(pos)
{
}
: ref(data), p(pos) { }
inline void next() { ++p; }
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 uniform_type_info const* type() const { return ref.type_at(p); }
};
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 @@
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_cast.hpp"
#include "cppa/util/duration.hpp"
#include "cppa/any_tuple_view.hpp"
#include "cppa/util/apply_tuple.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/callable_trait.hpp"
......@@ -61,6 +62,7 @@ class invokable_base
invokable_base() = default;
virtual ~invokable_base();
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
return true;
}
bool invoke(any_tuple_view const&) const
{
m_target();
return true;
}
};
class invokable : public invokable_base
......@@ -129,6 +138,18 @@ class invokable_impl : public invokable
m_iimpl;
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:
template<typename F>
......@@ -139,13 +160,12 @@ class invokable_impl : public invokable
bool invoke(any_tuple 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;
return invoke_impl(data);
}
bool invoke(any_tuple_view const& data) const
{
return invoke_impl(data);
}
intermediate* get_intermediate(any_tuple const& data)
......@@ -174,6 +194,17 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
m_iimpl;
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:
template<typename F>
......@@ -184,12 +215,12 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
bool invoke(any_tuple const& data) const
{
if (detail::matches(data.begin(), m_pattern->begin()))
{
m_iimpl.m_fun();
return true;
}
return false;
return invoke_impl(data);
}
bool invoke(any_tuple_view const& data) const
{
return invoke_impl(data);
}
intermediate* get_intermediate(any_tuple const& data)
......@@ -200,7 +231,6 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
};
template<typename Fun, class Pattern>
struct select_invokable_impl
{
......
......@@ -78,6 +78,7 @@ template<class MappingVector, typename Iterator>
class push_mapping_decorator
{
size_t pos;
Iterator iter;
MappingVector* mapping;
......@@ -86,28 +87,29 @@ class push_mapping_decorator
typedef MappingVector mapping_vector;
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)
: iter(other.iter), mapping(mv)
push_mapping_decorator(push_mapping_decorator const& other,
MappingVector* mv)
: pos(other.pos), iter(other.iter), mapping(mv)
{
}
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 void const* value() const { return iter.value(); }
inline decltype(iter.type()) type() const { return iter.type(); }
inline bool has_mapping() const { return mapping != nullptr; }
inline void push_mapping()
{
if (mapping) mapping->push_back(iter.position());
if (mapping) mapping->push_back(pos);
}
inline void push_mapping(MappingVector const& mv)
{
......
......@@ -114,6 +114,34 @@ struct types_array : types_array_impl<util::tl_forall<util::type_list<T...>,
util::is_builtin>::value,
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>
......
......@@ -50,6 +50,7 @@ namespace cppa {
class any_tuple;
class invoke_rules;
class any_tuple_view;
class timed_invoke_rules;
typedef std::list<detail::invokable_ptr> invokable_list;
......@@ -87,6 +88,8 @@ class invoke_rules_base
*/
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.
* @param data Data tuple that should be matched.
......
......@@ -28,39 +28,65 @@
\******************************************************************************/
#ifndef GET_VIEW_HPP
#define GET_VIEW_HPP
#ifndef MATCH_HPP
#define MATCH_HPP
#include <vector>
#include <cstddef>
#include <type_traits>
#include "cppa/tuple.hpp"
#include "cppa/pattern.hpp"
#include "cppa/anything.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/any_tuple_view.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/if_else.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa {
template<typename... MatchRules>
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)
namespace detail {
template<typename Tuple>
struct match_helper
{
pattern<MatchRules...> p;
typename pattern<MatchRules...>::mapping_vector mapping;
if (detail::matches(detail::pm_decorated(ut.begin(), &mapping), p.begin()))
static constexpr bool is_view = std::is_same<Tuple, any_tuple_view>::value;
Tuple what;
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
#endif // GET_VIEW_HPP
#endif // MATCH_HPP
......@@ -33,31 +33,33 @@
namespace cppa {
template<typename What>
template<typename T>
class option
{
union
{
What m_value;
T m_value;
};
bool m_valid;
void destroy()
{
if (m_valid) m_value.~What();
if (m_valid) m_value.~T();
}
template<typename V>
void cr(V&& value)
{
m_valid = true;
new (&m_value) What (std::forward<V>(value));
new (&m_value) T (std::forward<V>(value));
}
public:
typedef T value_type;
option() : m_valid(false) { }
template<typename V>
......@@ -131,14 +133,14 @@ class option
return *this;
}
option& operator=(What const& value)
option& operator=(T const& value)
{
if (m_valid) m_value = value;
else cr(value);
return *this;
}
option& operator=(What& value)
option& operator=(T& value)
{
if (m_valid) m_value = std::move(value);
else cr(std::move(value));
......@@ -151,20 +153,20 @@ class option
inline bool operator!() const { return !m_valid; }
inline What& operator*() { return m_value; }
inline What const& operator*() const { return m_value; }
inline T& operator*() { 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);
return m_value;
}
inline What& get_or_else(What&& val)
inline T& get_or_else(T&& val)
{
if (!m_valid) cr(std::move(val));
return m_value;
......
......@@ -31,18 +31,22 @@
#ifndef LIBCPPA_PATTERN_HPP
#define LIBCPPA_PATTERN_HPP
#include <list>
#include <vector>
#include <cstddef>
#include <type_traits>
#include "cppa/option.hpp"
#include "cppa/anything.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/tbind.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/arg_match_t.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/is_primitive.hpp"
#include "cppa/detail/boxed.hpp"
#include "cppa/detail/tdata.hpp"
......@@ -84,22 +88,13 @@ class pattern
public:
const_iterator(pattern const* ptr) : m_ptr(ptr), m_pos(0) { }
const_iterator(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()
{
++m_pos;
return *this;
}
inline void next() { ++m_pos; }
inline bool at_end()
{
return m_pos == sizeof...(Types);
}
inline bool at_end() { return m_pos == sizeof...(Types); }
inline uniform_type_info const* type() const
{
......
......@@ -32,6 +32,7 @@
#define TO_STRING_HPP
#include "cppa/uniform_type_info.hpp"
#include "cppa/detail/to_uniform_name.hpp"
namespace cppa {
......
......@@ -42,12 +42,14 @@
#include "cppa/ref_counted.hpp"
#include "cppa/util/at.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/replace_type.hpp"
#include "cppa/util/is_comparable.hpp"
#include "cppa/util/compare_tuples.hpp"
#include "cppa/util/is_legal_tuple_type.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/decorated_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa {
......@@ -84,6 +86,8 @@ class tuple
public:
static constexpr size_t num_elements = sizeof...(ElementTypes);
/**
* @brief Initializes each element with its default constructor.
*/
......@@ -122,6 +126,13 @@ class tuple
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.
* @returns <tt>sizeof...(ElementTypes)</tt>.
......@@ -150,7 +161,7 @@ class tuple
* of an 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);
}
......
......@@ -31,54 +31,128 @@
#ifndef TUPLE_CAST_HPP
#define TUPLE_CAST_HPP
#include <type_traits>
#include "cppa/option.hpp"
#include "cppa/pattern.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/types_array.hpp"
#include "cppa/detail/decorated_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa {
// 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>
template<class ResultTuple, class Tuple, typename... P>
option<ResultTuple> tuple_cast_impl(Tuple const& tup, pattern<P...> const& p)
{
typedef typename pattern<P...>::mapping_vector mapping_vector;
typedef typename pattern<P...>::filtered_types filtered_types;
typedef typename tuple_from_type_list<filtered_types>::type tuple_type;
option<tuple_type> result;
mapping_vector mv;
typename pattern<P...>::mapping_vector mv;
if (detail::matches(detail::pm_decorated(tup.begin(), &mv), p.begin()))
{
if (mv.size() == tup.size()) // perfect match
{
result = tuple_type::from(tup.vals());
return {ResultTuple::from(tup.vals())};
}
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
template<typename... T>
option< tuple<T...> > tuple_cast(any_tuple const& tup)
template<class ResultTuple, class Tuple, typename... T>
option<ResultTuple> tuple_cast_impl(Tuple const& tup)
{
option< tuple<T...> > result;
auto& tarr = detail::static_types_array<T...>::arr;
if (tup.size() == sizeof...(T))
// no anything in given template parameter pack
if (ResultTuple::num_elements == sizeof...(T))
{
auto& tarr = detail::static_types_array<T...>::arr;
if (tup.size() == sizeof...(T))
{
for (size_t i = 0; i < sizeof...(T); ++i)
{
if (tarr[i] != tup.type_at(i)) return { };
}
// always a perfect match
return {ResultTuple::from(tup.vals())};
}
}
else
{
for (size_t i = 0; i < sizeof...(T); ++i)
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()))
{
if (tarr[i] != tup.type_at(i)) return std::move(result);
// 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
......
......@@ -32,9 +32,11 @@
#define TUPLE_VIEW_HPP
#include <vector>
#include <cstring>
#include "cppa/get.hpp"
#include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/util/at.hpp"
#include "cppa/util/type_list.hpp"
......@@ -58,52 +60,45 @@ class tuple_view
template<size_t N, typename... Types>
friend typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>&);
public:
typedef cow_ptr<detail::abstract_tuple> vals_t;
static constexpr size_t num_elements = sizeof...(ElementTypes);
void const* m_data[sizeof...(ElementTypes)];
typedef util::fixed_vector<size_t, num_elements> mapping_vector;
tuple_view() { }
tuple_view() : m_vals(tuple<ElementTypes...>().vals()) { }
static tuple_view from(vals_t const& vals)
{
return tuple_view(vals);
}
public:
static tuple_view from(vals_t&& vals)
{
return tuple_view(std::move(vals));
}
static constexpr size_t num_elements = sizeof...(ElementTypes);
tuple_view(vals_t const& vals, mapping_vector& mapping)
: m_vals(new detail::decorated_tuple<num_elements>(vals, mapping))
static tuple_view from(std::vector< std::pair<uniform_type_info const*, void const*> > const& vec)
{
tuple_view result;
size_t j = 0;
for (auto i = vec.begin(); i != vec.end(); ++i)
{
result.m_data[j++] = i->second;
}
return std::move(result);
}
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)
{
result.m_data[i] = vec[mv[i]].second;
}
return std::move(result);
}
tuple_view& operator=(tuple_view const& other)
{
m_vals = other.m_vals;
return *this;
}
tuple_view& operator=(tuple_view&& other)
{
m_vals = std::move(other.m_vals);
memcpy(m_data, other.m_data, num_elements * sizeof(void*));
return *this;
}
tuple_view(tuple_view const&) = default;
inline vals_t const& vals() const
tuple_view(tuple_view const& other)
{
return m_vals;
memcpy(m_data, other.m_data, num_elements * sizeof(void*));
}
inline size_t size() const
......@@ -111,17 +106,7 @@ class tuple_view
return sizeof...(ElementTypes);
}
private:
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;
inline void const* at(size_t p) const { return m_data[p]; }
};
......@@ -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()");
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>
typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>& t)
{
static_assert(N < sizeof...(Types), "N >= t.size()");
typedef typename util::at<N, Types...>::type result_t;
return *reinterpret_cast<result_t*>(t.m_vals->mutable_at(N));
}
//template<size_t N, typename... Types>
//typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>& t)
//{
// static_assert(N < sizeof...(Types), "N >= t.size()");
// typedef typename util::at<N, Types...>::type result_t;
// return *reinterpret_cast<result_t*>(t.m_vals->mutable_at(N));
//}
template<typename TypeList>
struct tuple_view_type_from_type_list;
struct tuple_view_from_type_list;
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;
};
......
......@@ -39,7 +39,7 @@ struct offset_decorator : cppa::detail::abstract_tuple
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_decorated(decorated)
{
......@@ -99,7 +99,7 @@ any_tuple::any_tuple(any_tuple&& other) : m_vals(s_empty_tuple())
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
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());
}
......
......@@ -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;
}
......@@ -59,9 +68,9 @@ detail::intermediate*
invoke_rules_base::get_intermediate(const any_tuple& t) const
{
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;
}
return nullptr;
......
......@@ -6,6 +6,7 @@
#include "cppa/on.hpp"
#include "cppa/atom.hpp"
#include "cppa/tuple.hpp"
#include "cppa/match.hpp"
#include "cppa/option.hpp"
#include "cppa/pattern.hpp"
#include "cppa/announce.hpp"
......@@ -42,37 +43,29 @@ typedef std::pair<int,int> foobar;
static detail::types_array<int,anything,float> arr1;
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_helper(any_tuple const& w) : what(w) { }
void operator()(invoke_rules&& rules)
{
rules(what);
}
};
using namespace cppa::util;
match_helper match(any_tuple const& x)
{
return { x };
match(value)
(
on<int, int, int, anything>() >> [&](int a, int b, int c)
{
cout << "(" << a << ", " << b << ", " << c << ")" << endl;
},
on_arg_match >> [&](std::string const& str)
{
cout << str << endl;
}
);
}
size_t test__pattern()
{
CPPA_TEST(test__pattern);
match(make_tuple(1,2,3))
(
on_arg_match >> [&](int a, int b, int c)
{
CPPA_CHECK_EQUAL(a, 1);
CPPA_CHECK_EQUAL(b, 2);
CPPA_CHECK_EQUAL(c, 3);
}
);
match_test(make_tuple(1,2,3));
match_test(std::list<int>{1, 2, 3});
match_test("abc");
pattern<int, anything, int> i3;
any_tuple i3_any_tup = make_tuple(1, 2, 3);
......
......@@ -11,6 +11,7 @@
#include "cppa/on.hpp"
#include "cppa/util.hpp"
#include "cppa/tuple.hpp"
#include "cppa/pattern.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/to_string.hpp"
#include "cppa/tuple_cast.hpp"
......@@ -38,24 +39,37 @@ size_t test__tuple()
CPPA_CHECK((std::is_same<decltype(t0_1), int>::value));
CPPA_CHECK_EQUAL(t0_0, "1");
CPPA_CHECK_EQUAL(t0_1, 2);
// create a view of t0 that only contains the string
auto v0opt = tuple_cast(t0, pattern<std::string, anything>());
if (!v0opt) throw std::runtime_error("tuple_cast failed!");
auto& v0 = *v0opt;
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_EQUAL(v0_0, "1");
// check cow semantics
CPPA_CHECK_EQUAL(&get<0>(t0), &get<0>(v0)); // point to the same string
get_ref<0>(t0) = "hello world"; // detaches t0 from v0
CPPA_CHECK_EQUAL(get<0>(t0), "hello world"); // t0 contains new value
CPPA_CHECK_EQUAL(get<0>(v0), "1"); // v0 contains old value
CPPA_CHECK_NOT_EQUAL(&get<0>(t0), &get<0>(v0)); // no longer the same
// check operator==
auto lhs = make_tuple(1,2,3,4);
auto rhs = make_tuple(static_cast<std::uint8_t>(1), 2.0, 3, 4);
CPPA_CHECK_EQUAL(lhs, rhs);
CPPA_CHECK_EQUAL(rhs, lhs);
// get a view of t0
auto v1opt = tuple_cast<std::string, anything>(any_tuple_view(t0));
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_0 = get<0>(v0);
CPPA_CHECK((std::is_same<decltype(v0_0), std::string>::value));
CPPA_CHECK_EQUAL(v0.size(), 1);
CPPA_CHECK_EQUAL(v0_0, "1");
// check cow semantics
CPPA_CHECK_EQUAL(&get<0>(t0), &get<0>(v0)); // point to the same string
get_ref<0>(t0) = "hello world"; // detaches t0 from v0
CPPA_CHECK_EQUAL(get<0>(t0), "hello world"); // t0 contains new value
CPPA_CHECK_EQUAL(get<0>(v0), "1"); // v0 contains old value
CPPA_CHECK_NOT_EQUAL(&get<0>(t0), &get<0>(v0)); // no longer the same
// check operator==
auto lhs = make_tuple(1,2,3,4);
auto rhs = make_tuple(static_cast<std::uint8_t>(1), 2.0, 3, 4);
CPPA_CHECK_EQUAL(lhs, rhs);
CPPA_CHECK_EQUAL(rhs, lhs);
}
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