Commit 58318857 authored by neverlord's avatar neverlord

match() and match_each()

parent a7c57cea
......@@ -74,7 +74,6 @@ nobase_library_include_HEADERS = \
cppa/actor_proxy.hpp \
cppa/announce.hpp \
cppa/any_tuple.hpp \
cppa/any_tuple_view.hpp \
cppa/anything.hpp \
cppa/atom.hpp \
cppa/attachable.hpp \
......@@ -96,6 +95,7 @@ nobase_library_include_HEADERS = \
cppa/detail/boxed.hpp \
cppa/detail/buffer.hpp \
cppa/detail/channel.hpp \
cppa/detail/container_tuple_view.hpp \
cppa/detail/converted_thread_context.hpp \
cppa/detail/decorated_tuple.hpp \
cppa/detail/default_uniform_type_info_impl.hpp \
......@@ -111,6 +111,7 @@ nobase_library_include_HEADERS = \
cppa/detail/list_member.hpp \
cppa/detail/mailman.hpp \
cppa/detail/map_member.hpp \
cppa/detail/matches.hpp \
cppa/detail/mock_scheduler.hpp \
cppa/detail/native_socket.hpp \
cppa/detail/network_manager.hpp \
......@@ -132,6 +133,7 @@ nobase_library_include_HEADERS = \
cppa/detail/to_uniform_name.hpp \
cppa/detail/tuple_cast_impl.hpp \
cppa/detail/tuple_vals.hpp \
cppa/detail/tuple_view.hpp \
cppa/detail/type_to_ptype.hpp \
cppa/detail/types_array.hpp \
cppa/detail/unboxed.hpp \
......@@ -172,7 +174,6 @@ nobase_library_include_HEADERS = \
cppa/to_string.hpp \
cppa/tuple.hpp \
cppa/tuple_cast.hpp \
cppa/tuple_view.hpp \
cppa/type_value_pair.hpp \
cppa/uniform_type_info.hpp \
cppa/util/abstract_uniform_type_info.hpp \
......
......@@ -11,7 +11,6 @@ src/uniform_type_info.cpp
cppa/config.hpp
unit_testing/test__tuple.cpp
cppa/detail/abstract_tuple.hpp
cppa/tuple_view.hpp
cppa/detail/tuple_vals.hpp
cppa/detail/decorated_tuple.hpp
cppa/cow_ptr.hpp
......@@ -234,7 +233,6 @@ cppa/tuple_cast.hpp
cppa/util/is_mutable_ref.hpp
cppa/util/is_manipulator.hpp
cppa/util/apply_tuple.hpp
cppa/any_tuple_view.hpp
benchmarks/Matching.scala
benchmarks/matching.cpp
benchmarks/matching.erl
......@@ -256,3 +254,7 @@ cppa/intrusive/forward_iterator.hpp
unit_testing/test__intrusive_containers.cpp
examples/dancing_kirby.cpp
cppa/util/is_comparable.hpp
cppa/detail/tuple_view.hpp
cppa/detail/container_tuple_view.hpp
cppa/detail/matches.hpp
unit_testing/test__match.cpp
......@@ -34,7 +34,16 @@
#include "cppa/tuple.hpp"
#include "cppa/config.hpp"
#include "cppa/cow_ptr.hpp"
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/is_iterable.hpp"
#include "cppa/detail/tuple_view.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/container_tuple_view.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa {
......@@ -149,19 +158,99 @@ class any_tuple
return m_vals->impl_type();
}
template<typename T>
static inline any_tuple view(T&& value,
typename util::enable_if<util::is_iterable<typename util::rm_ref<T>::type> >::type* = 0)
{
static constexpr bool can_optimize = std::is_reference<T>::value
&& !std::is_const<T>::value;
std::integral_constant<bool, can_optimize> token;
return any_tuple{container_view(std::forward<T>(value), token)};
}
template<typename T>
static inline any_tuple view(T&& value,
typename util::disable_if<util::is_iterable<typename util::rm_ref<T>::type> >::type* = 0)
{
typedef typename util::rm_ref<T>::type vtype;
typedef typename detail::implicit_conversions<vtype>::type converted;
static_assert(util::is_legal_tuple_type<converted>::value,
"T is not a valid tuple type");
static constexpr bool can_optimize =
std::is_same<converted, vtype>::value
&& std::is_reference<T>::value
&& !std::is_const<T>::value;
std::integral_constant<bool, can_optimize> token;
return any_tuple{simple_view(std::forward<T>(value), token)};
}
private:
cow_ptr<detail::abstract_tuple> m_vals;
explicit any_tuple(cow_ptr<detail::abstract_tuple> const& vals);
typedef detail::abstract_tuple* tup_ptr;
template<typename T>
static inline tup_ptr simple_view(T& value,
std::integral_constant<bool, true>)
{
return new detail::tuple_view<T>(&value);
}
template<typename First, typename Second>
static inline tup_ptr simple_view(std::pair<First, Second>& p,
std::integral_constant<bool, true>)
{
return new detail::tuple_view<First, Second>(&p.first, &p.second);
}
template<typename T>
static inline tup_ptr simple_view(T&& value,
std::integral_constant<bool, false>)
{
typedef typename util::rm_ref<T>::type vtype;
typedef typename detail::implicit_conversions<vtype>::type converted;
return new detail::tuple_vals<converted>(std::forward<T>(value));
}
template<typename First, typename Second>
static inline any_tuple view(std::pair<First, Second> p,
std::integral_constant<bool, false>)
{
return new detail::tuple_vals<First, Second>(std::move(p.first),
std::move(p.second));
}
template<typename T>
static inline detail::abstract_tuple* container_view(T& value,
std::integral_constant<bool, true>)
{
return new detail::container_tuple_view<T>(&value);
}
template<typename T>
static inline detail::abstract_tuple* container_view(T&& value,
std::integral_constant<bool, false>)
{
typedef typename util::rm_ref<T>::type ctype;
return new detail::container_tuple_view<T>(new ctype(std::forward<T>(value)));
}
};
/**
* @relates any_tuple
*/
inline bool operator==(any_tuple const& lhs, any_tuple const& rhs)
{
return lhs.equals(rhs);
}
/**
* @relates any_tuple
*/
inline bool operator!=(any_tuple const& lhs, any_tuple const& rhs)
{
return !(lhs == rhs);
......
......@@ -28,132 +28,78 @@
\******************************************************************************/
#ifndef ANY_TUPLE_VIEW_HPP
#define ANY_TUPLE_VIEW_HPP
#ifndef CONTAINER_TUPLE_VIEW_HPP
#define CONTAINER_TUPLE_VIEW_HPP
#include <set>
#include <list>
#include <vector>
#include <utility>
#include <iterator>
#include <algorithm>
#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"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/object_array.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/disablable_delete.hpp"
namespace cppa {
namespace cppa { namespace detail {
class any_tuple_view
template<class Container>
class container_tuple_view : public abstract_tuple
{
typedef std::vector<type_value_pair> vector_type;
public:
vector_type m_values;
typedef typename Container::value_type value_type;
template<typename T>
void from_list(T const& list)
container_tuple_view(Container* c, bool take_ownership = false) : m_ptr(c)
{
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)));
}
CPPA_REQUIRE(c != nullptr);
if (!take_ownership) m_ptr.get_deleter().disable();
}
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& tup)
size_t size() const
{
if (tup.size() > 0)
{
// force tuple to detach
tup.mutable_at(0);
std::back_insert_iterator<vector_type> back_iter{m_values};
std::copy(tup.begin(), tup.end(), back_iter);
}
return m_ptr->size();
}
template<typename... T>
any_tuple_view(tuple_view<T...> const& tup)
abstract_tuple* copy() const
{
for (size_t i = 0; i < tup.size(); ++i)
{
m_values.push_back(std::make_pair(tup.type_at(i), tup.at(i)));
}
return new container_tuple_view{new Container(*m_ptr), true};
}
template<typename F, typename S>
any_tuple_view(std::pair<F, S> const& pair)
void const* at(size_t pos) const
{
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));
CPPA_REQUIRE(pos < size());
auto i = m_ptr->begin();
std::advance(i, pos);
return &(*i);
}
template<typename T>
any_tuple_view(std::set<T>& vec) { from_list(vec); }
template<typename T>
any_tuple_view(std::list<T>& vec) { from_list(vec); }
template<typename T>
any_tuple_view(std::vector<T>& vec) { from_list(vec); }
template<typename T>
any_tuple_view(T& val,
typename util::enable_if<util::is_primitive<T> >::type* = 0)
void* mutable_at(size_t pos)
{
auto& arr = detail::static_types_array<T>::arr;
m_values.push_back(std::make_pair(arr[0], &val));
CPPA_REQUIRE(pos < size());
auto i = m_ptr->begin();
std::advance(i, pos);
return &(*i);
}
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; }
void* mutable_at(size_t p) { return const_cast<void*>(m_values[p].second); }
inline uniform_type_info const* type_at(size_t p) const
uniform_type_info const* type_at(size_t pos) const
{
return m_values[p].first;
CPPA_REQUIRE(pos < size());
return static_types_array<value_type>::arr[0];
}
inline bool empty() const { return m_values.empty(); }
template<typename T>
inline T const& get_as(size_t p) const
void const* type_token() const
{
return *reinterpret_cast<T const*>(at(p));
return &(typeid(Container));
}
inline std::type_info const& impl_type() const
std::type_info const* impl_type() const
{
// this is a lie, but the pattern matching implementation
// needs to do a full runtime check of each element
return typeid(detail::object_array);
return &(typeid(detail::object_array));
}
private:
std::unique_ptr<Container, disablable_delete<Container> > m_ptr;
};
} // namespace cppa
} } // namespace cppa::detail
#endif // ANY_TUPLE_VIEW_HPP
#endif // CONTAINER_TUPLE_VIEW_HPP
......@@ -36,7 +36,6 @@
#include <cstddef>
#include <cstdint>
#include "cppa/match.hpp"
#include "cppa/pattern.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_cast.hpp"
......@@ -45,6 +44,7 @@
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/callable_trait.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/intermediate.hpp"
// forward declaration
......@@ -90,11 +90,11 @@ struct abstract_invokable : public invokable
}
bool types_match(any_tuple const& value) const
{
return match_types(value, m_pattern);
return matches_types(value, m_pattern);
}
bool could_invoke(any_tuple const& value) const
{
return match(value, m_pattern);
return matches(value, m_pattern);
}
};
......@@ -218,9 +218,9 @@ class invokable_impl<true, 0, Fun, Tuple, Pattern> : public abstract_invokable<T
: super(std::forward<Args>(args)...), m_iimpl(std::forward<F>(fun))
{
}
bool invoke(any_tuple const& data) const
bool invoke(any_tuple const& value) const
{
return match(data, this->m_pattern) ? m_iimpl() : false;
return matches(value, this->m_pattern) ? m_iimpl() : false;
}
bool unsafe_invoke(any_tuple const& value) const
{
......@@ -228,7 +228,7 @@ class invokable_impl<true, 0, Fun, Tuple, Pattern> : public abstract_invokable<T
}
intermediate* get_intermediate(any_tuple const& value)
{
return match(value, this->m_pattern) ? &m_iimpl : nullptr;
return matches(value, this->m_pattern) ? &m_iimpl : nullptr;
}
intermediate* get_unsafe_intermediate(any_tuple const& value)
{
......
This diff is collapsed.
......@@ -50,6 +50,18 @@ uniform_type_info const* uniform_typeid(std::type_info const&);
namespace cppa { namespace detail {
template<typename T>
inline void* ptr_to(T& what) { return &what; }
template<typename T>
inline void const* ptr_to(T const& what) { return &what; }
template<typename T>
inline void* ptr_to(T* what) { return what; }
template<typename T>
inline void const* ptr_to(T const* what) { return what; }
/*
* "enhanced std::tuple"
*/
......@@ -153,7 +165,7 @@ struct tdata<Head, Tail...> : tdata<Tail...>
inline void const* at(size_t p) const
{
return (p == 0) ? &head : super::at(p-1);
return (p == 0) ? ptr_to(head) : super::at(p-1);
}
inline uniform_type_info const* type_at(size_t p) const
......@@ -215,7 +227,7 @@ struct tdata<option<Head>, Tail...> : tdata<Tail...>
inline void const* at(size_t p) const
{
return (p == 0) ? &head : super::at(p-1);
return (p == 0) ? ptr_to(head) : super::at(p-1);
}
inline uniform_type_info const* type_at(size_t p) const
......
......@@ -31,10 +31,11 @@
#ifndef TUPLE_CAST_IMPL_HPP
#define TUPLE_CAST_IMPL_HPP
#include "cppa/match.hpp"
#include "cppa/pattern.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/type_value_pair.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/object_array.hpp"
......@@ -60,22 +61,19 @@ struct tuple_cast_impl
static constexpr size_t first_wc =
static_cast<size_t>(util::tl_find<util::type_list<T...>, anything>::value);
typedef util::fixed_vector<size_t, size> mapping_vector;
template<class Tuple>
static inline option<Result> safe(Tuple const& tup)
static inline option<Result> safe(any_tuple const& tup)
{
mapping_vector mv;
if (match<T...>(tup, mv)) return {Result::from(tup.vals(), mv)};
if (matches<T...>(tup, mv)) return {Result::from(tup.vals(), mv)};
return {};
}
template<class Tuple>
static inline option<Result> safe(Tuple const& tup, pattern<T...> const& p)
static inline option<Result> safe(any_tuple const& tup, pattern<T...> const& p)
{
mapping_vector mv;
if (match(tup, p, mv)) return {Result::from(tup.vals(), mv)};
if (matches(tup, p, mv)) return {Result::from(tup.vals(), mv)};
return {};
}
template<class Tuple>
static inline option<Result> unsafe(Tuple const& tup, pattern<T...> const& p)
static inline option<Result> unsafe(any_tuple const& tup, pattern<T...> const& p)
{
mapping_vector mv;
if (WP == wildcard_position::in_between)
......@@ -94,12 +92,11 @@ struct tuple_cast_impl
}
else
{
if (match(tup, p, mv)) return {Result::from(tup.vals(), mv)};
if (matches(tup, p, mv)) return {Result::from(tup.vals(), mv)};
}
return {};
}
template<class Tuple>
static inline Result force(Tuple const& tup, pattern<T...> const& p)
static inline Result force(any_tuple const& tup, pattern<T...> const& p)
{
mapping_vector mv;
if (WP == wildcard_position::in_between)
......@@ -115,7 +112,7 @@ struct tuple_cast_impl
}
else
{
match(tup, p, mv);
matches(tup, p, mv);
return {Result::from(tup.vals(), mv)};
}
}
......@@ -124,20 +121,17 @@ struct tuple_cast_impl
template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::nil, Result, T...>
{
template<class Tuple>
static inline option<Result> safe(Tuple const& tup)
static inline option<Result> safe(any_tuple const& tup)
{
if (match<T...>(tup)) return {Result::from(tup.vals())};
if (matches<T...>(tup)) return {Result::from(tup.vals())};
return {};
}
template<class Tuple>
static inline option<Result> safe(Tuple const& tup, pattern<T...> const& p)
static inline option<Result> safe(any_tuple const& tup, pattern<T...> const& p)
{
if (match(tup, p)) return {Result::from(tup.vals())};
if (matches(tup, p)) return {Result::from(tup.vals())};
return {};
}
template<class Tuple>
static inline option<Result> unsafe(Tuple const& tup, pattern<T...> const& p)
static inline option<Result> unsafe(any_tuple const& tup, pattern<T...> const& p)
{
if ( p.has_values() == false
|| matcher<wildcard_position::nil, T...>::vmatch(tup, p))
......@@ -146,8 +140,7 @@ struct tuple_cast_impl<wildcard_position::nil, Result, T...>
}
return {};
}
template<class Tuple>
static inline Result force(Tuple const& tup, pattern<T...> const&)
static inline Result force(any_tuple const& tup, pattern<T...> const&)
{
return {Result::from(tup.vals())};
}
......@@ -157,8 +150,7 @@ template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::trailing, Result, T...>
: tuple_cast_impl<wildcard_position::nil, Result, T...>
{
template<class Tuple>
static inline option<Result> unsafe(Tuple const& tup, pattern<T...> const& p)
static inline option<Result> unsafe(any_tuple const& tup, pattern<T...> const& p)
{
if ( p.has_values() == false
|| matcher<wildcard_position::trailing, T...>::vmatch(tup, p))
......@@ -167,8 +159,7 @@ struct tuple_cast_impl<wildcard_position::trailing, Result, T...>
}
return {};
}
template<class Tuple>
static inline Result force(Tuple const& tup, pattern<T...> const&)
static inline Result force(any_tuple const& tup, pattern<T...> const&)
{
return {Result::from(tup.vals())};
}
......@@ -177,22 +168,19 @@ struct tuple_cast_impl<wildcard_position::trailing, Result, T...>
template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::leading, Result, T...>
{
template<class Tuple>
static inline option<Result> safe(Tuple const& tup)
static inline option<Result> safe(any_tuple const& tup)
{
size_t o = tup.size() - (sizeof...(T) - 1);
if (match<T...>(tup)) return {Result::offset_subtuple(tup.vals(), o)};
if (matches<T...>(tup)) return {Result::offset_subtuple(tup.vals(), o)};
return {};
}
template<class Tuple>
static inline option<Result> safe(Tuple const& tup, pattern<T...> const& p)
static inline option<Result> safe(any_tuple const& tup, pattern<T...> const& p)
{
size_t o = tup.size() - (sizeof...(T) - 1);
if (match(tup, p)) return {Result::offset_subtuple(tup.vals(), o)};
if (matches(tup, p)) return {Result::offset_subtuple(tup.vals(), o)};
return {};
}
template<class Tuple>
static inline option<Result> unsafe(Tuple const& tup, pattern<T...> const& p)
static inline option<Result> unsafe(any_tuple const& tup, pattern<T...> const& p)
{
if ( p.has_values() == false
|| matcher<wildcard_position::leading, T...>::vmatch(tup, p))
......@@ -202,8 +190,7 @@ struct tuple_cast_impl<wildcard_position::leading, Result, T...>
}
return {};
}
template<class Tuple>
static inline Result force(Tuple const& tup, pattern<T...> const&)
static inline Result force(any_tuple const& tup, pattern<T...> const&)
{
size_t o = tup.size() - (sizeof...(T) - 1);
return Result::offset_subtuple(tup.vals(), o);
......
......@@ -53,22 +53,23 @@ class tuple_vals : public abstract_tuple
typedef abstract_tuple super;
public:
typedef tdata<ElementTypes...> data_type;
typedef types_array<ElementTypes...> element_types;
data_type m_data;
static types_array<ElementTypes...> m_types;
public:
tuple_vals() : m_data() { }
tuple_vals(tuple_vals const& other) : super(), m_data(other.m_data) { }
tuple_vals(ElementTypes const&... args) : m_data(args...) { }
inline data_type& data()
{
return m_data;
}
inline data_type const& data() const
{
return m_data;
......@@ -92,6 +93,7 @@ class tuple_vals : public abstract_tuple
void* mutable_at(size_t pos)
{
CPPA_REQUIRE(pos < size());
return const_cast<void*>(at(pos));
}
......@@ -122,6 +124,12 @@ class tuple_vals : public abstract_tuple
return detail::static_type_list<ElementTypes...>::list;
}
private:
data_type m_data;
static types_array<ElementTypes...> m_types;
};
template<typename... ElementTypes>
......
......@@ -31,156 +31,108 @@
#ifndef TUPLE_VIEW_HPP
#define TUPLE_VIEW_HPP
#include <vector>
#include <cstring>
#include "cppa/util/static_foreach.hpp"
#include "cppa/get.hpp"
#include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/util/at.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/compare_tuples.hpp"
namespace cppa { namespace detail {
#include "cppa/detail/decorated_tuple.hpp"
namespace cppa {
template<size_t N, typename... Types>
typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>& t);
struct tuple_view_copy_helper
{
size_t pos;
abstract_tuple* target;
tuple_view_copy_helper(abstract_tuple* trgt) : pos(0), target(trgt) { }
template<typename T>
void operator()(T const* value)
{
*(reinterpret_cast<T*>(target->mutable_at(pos++))) = *value;
}
};
/**
* @brief Describes a view of an fixed-length tuple.
*/
template<typename... ElementTypes>
class tuple_view
class tuple_view : public abstract_tuple
{
template<size_t N, typename... Types>
friend typename util::at<N, Types...>::type& get_ref(tuple_view<Types...>&);
static_assert(sizeof...(ElementTypes) > 0,
"tuple_vals is not allowed to be empty");
void* m_data[sizeof...(ElementTypes)];
public:
tuple_view() { }
typedef tdata<ElementTypes*...> data_type;
public:
typedef types_array<ElementTypes...> element_types;
static constexpr size_t num_elements = sizeof...(ElementTypes);
tuple_view() = delete;
tuple_view(tuple_view const&) = delete;
typedef util::type_list<ElementTypes...> types;
/**
* @warning @p tuple_view does @b NOT takes ownership for given pointers
*/
tuple_view(ElementTypes*... args) : m_data(args...) { }
static tuple_view from(std::vector<type_value_pair> const& vec)
inline data_type& data()
{
tuple_view result;
size_t j = 0;
for (type_value_pair const& tvp : vec)
{
result.m_data[j++] = const_cast<void*>(tvp.second);
}
return std::move(result);
return m_data;
}
static tuple_view from(std::vector<type_value_pair> const& vec,
util::fixed_vector<size_t, sizeof...(ElementTypes)> const& mv)
inline data_type const& data() const
{
tuple_view result;
for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{
result.m_data[i] = const_cast<void*>(vec[mv[i]].second);
}
return std::move(result);
return m_data;
}
tuple_view& operator=(tuple_view const& other)
size_t size() const
{
memcpy(m_data, other.m_data, num_elements * sizeof(void*));
return *this;
return sizeof...(ElementTypes);
}
tuple_view(tuple_view const& other)
abstract_tuple* copy() const
{
memcpy(m_data, other.m_data, num_elements * sizeof(void*));
auto result = new tuple_vals<ElementTypes...>;
tuple_view_copy_helper f{result};
util::static_foreach<0, sizeof...(ElementTypes)>::_(m_data, f);
return result;
}
inline size_t size() const
void const* at(size_t pos) const
{
return sizeof...(ElementTypes);
CPPA_REQUIRE(pos < size());
return m_data.at(pos);
}
inline void const* at(size_t p) const { return m_data[p]; }
inline void* mutable_at(size_t p) { return m_data[p]; }
};
template<size_t N, typename... Types>
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.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.mutable_at(N));
}
void* mutable_at(size_t pos)
{
CPPA_REQUIRE(pos < size());
return const_cast<void*>(at(pos));
}
template<typename TypeList>
struct tuple_view_from_type_list;
uniform_type_info const* type_at(size_t pos) const
{
CPPA_REQUIRE(pos < size());
return m_types[pos];
}
template<typename... Types>
struct tuple_view_from_type_list<util::type_list<Types...>>
{
typedef tuple_view<Types...> type;
};
void const* type_token() const
{
return detail::static_type_list<ElementTypes...>::list;
}
template<typename... LhsTypes, typename... RhsTypes>
inline bool operator==(tuple_view<LhsTypes...> const& lhs,
tuple_view<RhsTypes...> const& rhs)
{
return util::compare_tuples(lhs, rhs);
}
std::type_info const* impl_type() const
{
return detail::static_type_list<ElementTypes...>::list;
}
template<typename... LhsTypes, typename... RhsTypes>
inline bool operator==(tuple<LhsTypes...> const& lhs,
tuple_view<RhsTypes...> const& rhs)
{
return util::compare_tuples(lhs, rhs);
}
private:
template<typename... LhsTypes, typename... RhsTypes>
inline bool operator==(tuple_view<LhsTypes...> const& lhs,
tuple<RhsTypes...> const& rhs)
{
return util::compare_tuples(lhs, rhs);
}
data_type m_data;
template<typename... LhsTypes, typename... RhsTypes>
inline bool operator!=(tuple_view<LhsTypes...> const& lhs,
tuple_view<RhsTypes...> const& rhs)
{
return !(lhs == rhs);
}
static types_array<ElementTypes...> m_types;
template<typename... LhsTypes, typename... RhsTypes>
inline bool operator!=(tuple<LhsTypes...> const& lhs,
tuple_view<RhsTypes...> const& rhs)
{
return !(lhs == rhs);
}
};
template<typename... LhsTypes, typename... RhsTypes>
inline bool operator!=(tuple_view<LhsTypes...> const& lhs,
tuple<RhsTypes...> const& rhs)
{
return !(lhs == rhs);
}
template<typename... ElementTypes>
types_array<ElementTypes...> tuple_view<ElementTypes...>::m_types;
} // namespace cppa
} } // namespace cppa::detail
#endif // TUPLE_VIEW_HPP
......@@ -44,9 +44,6 @@ namespace detail { template<typename...> class tdata; }
// forward declaration of tuple
template<typename...> class tuple;
// forward declaration of tuple_view
template<typename...> class tuple_view;
// forward declaration of get(detail::tdata<...> const&)
template<size_t N, typename... Tn>
const typename util::at<N, Tn...>::type& get(detail::tdata<Tn...> const&);
......@@ -55,10 +52,6 @@ const typename util::at<N, Tn...>::type& get(detail::tdata<Tn...> const&);
template<size_t N, typename... Tn>
const typename util::at<N, Tn...>::type& get(tuple<Tn...> const&);
// forward declarations of get(tuple_view<...> const&)
template<size_t N, typename... Tn>
const typename util::at<N, Tn...>::type& get(tuple_view<Tn...> const&);
// forward declarations of get_ref(detail::tdata<...>&)
template<size_t N, typename... Tn>
typename util::at<N, Tn...>::type& get_ref(detail::tdata<Tn...>&);
......@@ -67,10 +60,6 @@ typename util::at<N, Tn...>::type& get_ref(detail::tdata<Tn...>&);
template<size_t N, typename... Tn>
typename util::at<N, Tn...>::type& get_ref(tuple<Tn...>&);
// forward declarations of get_ref(tuple_view<...>&)
template<size_t N, typename... Tn>
typename util::at<N, Tn...>::type& get_ref(tuple_view<Tn...>&);
} // namespace cppa
#endif // GET_HPP
This diff is collapsed.
......@@ -38,8 +38,6 @@
#include "cppa/option.hpp"
#include "cppa/anything.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/type_value_pair.hpp"
#include "cppa/uniform_type_info.hpp"
......
......@@ -33,15 +33,17 @@
#include <type_traits>
#include "cppa/match.hpp"
#include "cppa/option.hpp"
#include "cppa/pattern.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/tuple_cast_impl.hpp"
namespace cppa {
// cast using a pattern
/**
* @brief Tries to cast @p tup to {@link tuple tuple<T...>}.
*/
template<typename... T>
auto tuple_cast(any_tuple const& tup, pattern<T...> const& p)
-> option<
......@@ -56,7 +58,9 @@ auto tuple_cast(any_tuple const& tup, pattern<T...> const& p)
return detail::tuple_cast_impl<impl, tuple_type, T...>::safe(tup, p);
}
// cast using types
/**
* @brief Tries to cast @p tup to {@link tuple tuple<T...>}.
*/
template<typename... T>
auto tuple_cast(any_tuple const& tup)
-> option<
......
......@@ -105,12 +105,18 @@ class type_value_pair_const_iterator
};
/**
* @relates type_value_pair_const_iterator
*/
inline bool operator==(type_value_pair_const_iterator const& lhs,
type_value_pair_const_iterator const& rhs)
{
return lhs.base() == rhs.base();
}
/**
* @relates type_value_pair_const_iterator
*/
inline bool operator!=(type_value_pair_const_iterator const& lhs,
type_value_pair_const_iterator const& rhs)
{
......
......@@ -263,12 +263,18 @@ class uniform_type_info
};
/**
* @relates uniform_type_info
*/
template<typename T>
inline uniform_type_info const* uniform_typeid()
{
return uniform_typeid(typeid(T));
}
/**
* @relates uniform_type_info
*/
inline bool operator==(uniform_type_info const& lhs,
uniform_type_info const& rhs)
{
......@@ -277,27 +283,42 @@ inline bool operator==(uniform_type_info const& lhs,
return &lhs == &rhs;
}
/**
* @relates uniform_type_info
*/
inline bool operator!=(uniform_type_info const& lhs,
uniform_type_info const& rhs)
{
return !(lhs == rhs);
}
/**
* @relates uniform_type_info
*/
inline bool operator==(uniform_type_info const& lhs, std::type_info const& rhs)
{
return lhs.equals(rhs);
}
/**
* @relates uniform_type_info
*/
inline bool operator!=(uniform_type_info const& lhs, std::type_info const& rhs)
{
return !(lhs.equals(rhs));
}
/**
* @relates uniform_type_info
*/
inline bool operator==(std::type_info const& lhs, uniform_type_info const& rhs)
{
return rhs.equals(lhs);
}
/**
* @relates uniform_type_info
*/
inline bool operator!=(std::type_info const& lhs, uniform_type_info const& rhs)
{
return !(rhs.equals(lhs));
......
......@@ -67,7 +67,7 @@ class is_iterable
public:
static constexpr bool value = util::is_primitive<T>::value == false
&& std::is_same<bool, result_type>::value;
&& std::is_same<bool, result_type>::value;
};
......
......@@ -31,6 +31,8 @@
#ifndef STATIC_FOREACH_HPP
#define STATIC_FOREACH_HPP
#include "cppa/get.hpp"
namespace cppa { namespace util {
/**
......
......@@ -32,8 +32,8 @@
#include <algorithm>
#include "cppa/self.hpp"
#include "cppa/match.hpp"
#include "cppa/exception.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/invokable.hpp"
#include "cppa/detail/intermediate.hpp"
#include "cppa/detail/converted_thread_context.hpp"
......@@ -111,7 +111,7 @@ void converted_thread_context::dequeue(behavior& rules) /*override*/
converted_thread_context::throw_on_exit_result
converted_thread_context::throw_on_exit(any_tuple const& msg)
{
if (match(msg, m_exit_msg_pattern))
if (matches(msg, m_exit_msg_pattern))
{
auto reason = msg.get_as<std::uint32_t>(1);
if (reason != exit_reason::normal)
......
......@@ -15,6 +15,7 @@ unit_tests_SOURCES = main.cpp \
test__queue_performance.cpp \
test__remote_actor.cpp \
test__ripemd_160.cpp \
test__match.cpp \
test__serialization.cpp \
test__spawn.cpp \
test__tuple.cpp \
......
......@@ -16,6 +16,7 @@
#include "cppa/cppa.hpp"
#include "cppa/tuple.hpp"
#include "cppa/match.hpp"
#include "cppa/config.hpp"
#include "cppa/anything.hpp"
#include "cppa/detail/demangle.hpp"
......@@ -86,10 +87,9 @@ std::vector<std::string> split(std::string const& str, char delim)
return result;
}
std::map<std::string, std::string>
get_kv_pairs(int argc, char** argv, int begin = 1)
std::vector<string_pair> get_kv_pairs(int argc, char** argv, int begin = 1)
{
std::map<std::string, std::string> result;
std::vector<string_pair> result;
for (int i = begin; i < argc; ++i)
{
auto vec = split(argv[i], '=');
......@@ -97,60 +97,18 @@ get_kv_pairs(int argc, char** argv, int begin = 1)
{
cerr << "\"" << argv[i] << "\" is not a key-value pair" << endl;
}
else if (result.insert(std::make_pair(vec[0], vec[1])).second == false)
else if (std::any_of(result.begin(), result.end(),
[&](string_pair const& p) { return p.first == vec[0]; }))
{
cerr << "key \"" << vec[0] << "\" is already defined" << endl;
exit(1);
}
}
return result;
}
template<typename Iterator, class Container, typename Key>
inline bool found_key(Iterator& i, Container& cont, Key&& key)
{
return (i = cont.find(std::forward<Key>(key))) != cont.end();
}
template<typename F, typename S>
any_tuple to_tuple(std::pair<F, S> const& p)
{
return make_tuple(p.first, p.second);
}
struct match_helper
{
any_tuple tup;
template<class... Args>
void operator()(partial_function&& pf, Args&&... args)
{
partial_function tmp;
tmp.splice(std::move(pf), std::forward<Args>(args)...);
tmp(tup);
}
};
template<typename F, typename S>
match_helper match(std::pair<F, S> const& what)
{
return {to_tuple(what)};
}
template<class Container>
struct match_each_helper
{
Container const& args;
template<typename... Args>
void operator()(partial_function&& pf, Args&&... args)
{
partial_function tmp;
tmp.splice(std::move(pf), std::forward<Args>(args)...);
for (auto& arg : args)
else
{
tmp(to_tuple(arg));
result.emplace_back(vec[0], vec[1]);
}
}
};
return result;
}
void usage(char const* argv0)
{
......@@ -162,39 +120,67 @@ void usage(char const* argv0)
int main(int argc, char** argv)
{
/*
std::string abc = "abc";
cout << "is_iterable<string> = " << cppa::util::is_iterable<std::string>::value << endl;
match(abc)
(
on("abc") >> []()
{
cout << "ABC" << endl;
}
);
match_each(argv + 1, argv + argc)
(
on_arg_match >> [](std::string const& str)
{
cout << "matched \"" << str << "\"" << endl;
}
);
pmatch_each(argv + 1, argv + argc, [](char const* cstr) { return split(cstr, '='); })
(
on_arg_match >> [](std::string const& key, std::string const& value)
{
cout << "key = \"" << key << "\", value = \"" << value << "\""
<< endl;
}
);
return 0;
*/
auto args = get_kv_pairs(argc, argv);
for (auto& kvp : args)
{
match(kvp)
(
on("run", arg_match) >> [&](std::string const& what)
match_each(args)
(
on("run", arg_match) >> [&](std::string const& what)
{
if (what == "remote_actor")
{
if (what == "remote_actor")
{
test__remote_actor(argv[0], true, args);
exit(0);
}
},
on("scheduler", arg_match) >> [](std::string const& sched)
test__remote_actor(argv[0], true, args);
exit(0);
}
},
on("scheduler", arg_match) >> [](std::string const& sched)
{
if (sched == "thread_pool_scheduler")
{
if (sched == "thread_pool_scheduler")
{
cout << "using thread_pool_scheduler" << endl;
set_scheduler(new cppa::detail::thread_pool_scheduler);
}
else if (sched == "mock_scheduler")
{
cout << "using mock_scheduler" << endl;
set_scheduler(new cppa::detail::mock_scheduler);
}
else
{
cerr << "unknown scheduler: " << sched << endl;
exit(1);
}
cout << "using thread_pool_scheduler" << endl;
set_scheduler(new cppa::detail::thread_pool_scheduler);
}
);
}
else if (sched == "mock_scheduler")
{
cout << "using mock_scheduler" << endl;
set_scheduler(new cppa::detail::mock_scheduler);
}
else
{
cerr << "unknown scheduler: " << sched << endl;
exit(1);
}
}
);
//print_node_id();
std::cout << std::boolalpha;
size_t errors = 0;
......@@ -203,6 +189,7 @@ int main(int argc, char** argv)
RUN_TEST(test__intrusive_containers);
RUN_TEST(test__uniform_type);
RUN_TEST(test__pattern);
RUN_TEST(test__match);
RUN_TEST(test__intrusive_ptr);
RUN_TEST(test__type_list);
RUN_TEST(test__fixed_vector);
......
#ifndef TEST_HPP
#define TEST_HPP
#include <map>
#include <vector>
#include <string>
#include <cstddef>
#include <iostream>
......@@ -88,14 +88,17 @@ std::cerr << err_msg << std::endl; \
#define CPPA_CHECK_NOT_EQUAL(lhs_loc, rhs_loc) CPPA_CHECK(((lhs_loc) != (rhs_loc)))
typedef std::pair<std::string, std::string> string_pair;
size_t test__yield_interface();
size_t test__remote_actor(const char* app_path, bool is_client,
const std::map<std::string, std::string>& args);
size_t test__remote_actor(char const* app_path, bool is_client,
std::vector<string_pair> const& args);
size_t test__ripemd_160();
size_t test__uniform_type();
size_t test__type_list();
size_t test__atom();
size_t test__tuple();
size_t test__match();
size_t test__spawn();
size_t test__pattern();
size_t test__intrusive_ptr();
......
#include "test.hpp"
#include "cppa/match.hpp"
size_t test__match()
{
CPPA_TEST(test__match);
return CPPA_TEST_RESULT;
}
......@@ -16,9 +16,10 @@ using namespace cppa;
namespace {
void client_part(std::map<std::string, std::string> const& args)
void client_part(std::vector<string_pair> const& args)
{
auto i = args.find("port");
auto i = std::find_if(args.begin(), args.end(),
[](string_pair const& p) { return p.first == "port"; });
if (i == args.end())
{
throw std::runtime_error("no port specified");
......@@ -34,7 +35,7 @@ void client_part(std::map<std::string, std::string> const& args)
} // namespace <anonymous>
size_t test__remote_actor(char const* app_path, bool is_client,
std::map<std::string, std::string> const& args)
std::vector<string_pair> const& args)
{
if (is_client)
{
......
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