Commit 3f194ef3 authored by neverlord's avatar neverlord

maintenance

parent f0cd281c
......@@ -136,6 +136,7 @@ nobase_library_include_HEADERS = \
cppa/detail/tdata.hpp \
cppa/detail/thread_pool_scheduler.hpp \
cppa/detail/to_uniform_name.hpp \
cppa/detail/tuple_cast_impl.hpp \
cppa/detail/tuple_vals.hpp \
cppa/detail/type_to_ptype.hpp \
cppa/detail/types_array.hpp \
......
......@@ -244,12 +244,10 @@ cppa/util/type_pair.hpp
cppa/util/tbind.hpp
cppa/option.hpp
cppa/tuple_cast.hpp
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
benchmarks/Matching.scala
benchmarks/matching.cpp
benchmarks/matching.erl
......@@ -262,3 +260,5 @@ cppa/type_value_pair.hpp
examples/dining_philosophers.cpp
cppa/detail/disablable_delete.hpp
unit_testing/test__fixed_vector.cpp
cppa/detail/tuple_cast_impl.hpp
cppa/match.hpp
......@@ -101,13 +101,34 @@ struct abstract_tuple : ref_counted
return {m_tuple, m_pos + offset};
}
inline const_iterator& operator+=(size_t offset)
{
m_pos += offset;
return *this;
}
inline const_iterator operator-(size_t offset)
{
CPPA_REQUIRE(m_pos >= offset);
return {m_tuple, m_pos - offset};
}
inline const_iterator& operator-=(size_t offset)
{
CPPA_REQUIRE(m_pos >= offset);
m_pos -= offset;
return *this;
}
inline size_t position() const { return m_pos; }
void const* value() const { return m_tuple.at(m_pos); }
uniform_type_info const* type() const { return m_tuple.type_at(m_pos); }
type_value_pair operator*() { return {type(), value()}; }
const_iterator& operator*() { return *this; }
operator type_value_pair() const { return {type(), value()}; }
};
......@@ -117,6 +138,27 @@ struct abstract_tuple : ref_counted
};
inline bool full_eq(abstract_tuple::const_iterator const& lhs,
type_value_pair const& rhs)
{
return lhs.type() == rhs.first
&& ( rhs.second == nullptr
|| lhs.type()->equals(lhs.value(), rhs.second));
}
inline bool values_only_eq(abstract_tuple::const_iterator const& lhs,
type_value_pair const& rhs)
{
return rhs.second == nullptr
|| lhs.type()->equals(lhs.value(), rhs.second);
}
inline bool types_only_eq(abstract_tuple::const_iterator const& lhs,
type_value_pair const& rhs)
{
return lhs.type() == rhs.first;
}
} } // namespace cppa::detail
#endif // ABSTRACT_TUPLE_HPP
......@@ -40,8 +40,10 @@
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/apply_tuple.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/serialize_tuple.hpp"
......@@ -71,11 +73,16 @@ class decorated_tuple : public abstract_tuple
return {(new decorated_tuple(std::move(d)))->init()};
}
// creates a subtuple form @p d with an offset
static cow_pointer_type create(cow_pointer_type d, size_t offset)
{
return {(new decorated_tuple(std::move(d)))->init(offset)};
}
virtual void* mutable_at(size_t pos)
{
CPPA_REQUIRE(pos < size());
// const_cast is safe because decorated_tuple is used in cow_ptrs only
return const_cast<void*>(m_data[pos].second);
return m_decorated->mutable_at(m_mapping[pos]);
}
virtual size_t size() const
......@@ -91,13 +98,13 @@ class decorated_tuple : public abstract_tuple
virtual void const* at(size_t pos) const
{
CPPA_REQUIRE(pos < size());
return m_data[pos].second;
return m_decorated->at(m_mapping[pos]);
}
virtual uniform_type_info const* type_at(size_t pos) const
{
CPPA_REQUIRE(pos < size());
return m_data[pos].first;
return m_decorated->type_at(m_mapping[pos]);
}
virtual std::type_info const& impl_type() const
......@@ -108,7 +115,7 @@ class decorated_tuple : public abstract_tuple
private:
cow_pointer_type m_decorated;
type_value_pair m_data[sizeof...(ElementTypes)];
vector_type m_mapping;
decorated_tuple(cow_pointer_type const& d) : m_decorated(d) { }
......@@ -117,9 +124,8 @@ class decorated_tuple : public abstract_tuple
decorated_tuple(decorated_tuple const& other)
: abstract_tuple()
, m_decorated(other.m_decorated)
, m_mapping(other.m_mapping)
{
// both instances point to the same data
std::copy(other.begin(), other.end(), m_data);
}
decorated_tuple* init(vector_type const& v)
......@@ -127,24 +133,26 @@ class decorated_tuple : public abstract_tuple
CPPA_REQUIRE(m_decorated->size() >= sizeof...(ElementTypes));
CPPA_REQUIRE(v.size() == sizeof...(ElementTypes));
CPPA_REQUIRE(*(std::max_element(v.begin(), v.end())) < m_decorated->size());
for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{
auto x = v[i];
m_data[i].first = m_decorated->type_at(x);
m_data[i].second = m_decorated->at(x);
}
m_mapping.resize(v.size());
std::copy(v.begin(), v.end(), m_mapping.begin());
return this;
}
decorated_tuple* init()
{
CPPA_REQUIRE(m_decorated->size() >= sizeof...(ElementTypes));
// copy first n elements
for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{
m_data[i].first = m_decorated->type_at(i);
m_data[i].second = m_decorated->at(i);
}
size_t i = 0;
m_mapping.resize(sizeof...(ElementTypes));
std::generate(m_mapping.begin(), m_mapping.end(), [&](){return i++;});
return this;
}
decorated_tuple* init(size_t offset)
{
CPPA_REQUIRE((m_decorated->size() - offset) == sizeof...(ElementTypes));
size_t i = offset;
m_mapping.resize(sizeof...(ElementTypes));
std::generate(m_mapping.begin(), m_mapping.end(), [&](){return i++;});
return this;
}
......
......@@ -35,6 +35,7 @@
#include <cstddef>
#include <cstdint>
#include "cppa/match.hpp"
#include "cppa/any_tuple.hpp"
#include "cppa/tuple_cast.hpp"
#include "cppa/util/duration.hpp"
......@@ -42,7 +43,6 @@
#include "cppa/util/fixed_vector.hpp"
#include "cppa/util/callable_trait.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/intermediate.hpp"
// forward declaration
......@@ -183,7 +183,7 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
template<typename T>
bool invoke_impl(T const& data) const
{
if (matches(data, *m_pattern))
if (match(data, *m_pattern))
{
m_iimpl.m_fun();
return true;
......@@ -206,7 +206,7 @@ class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
intermediate* get_intermediate(any_tuple const& data)
{
return matches(data, *m_pattern) ? &m_iimpl : nullptr;
return match(data, *m_pattern) ? &m_iimpl : nullptr;
}
};
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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 DO_MATCH_HPP
#define DO_MATCH_HPP
#include <algorithm>
#include <type_traits>
#include "cppa/pattern.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/fixed_vector.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/object_array.hpp"
#include "cppa/detail/decorated_tuple.hpp"
namespace cppa { namespace detail {
template<class MappingVector, typename Iterator>
class push_mapping_decorator
{
Iterator iter;
MappingVector& mapping;
size_t commited_size;
public:
typedef MappingVector mapping_vector;
push_mapping_decorator(Iterator const& i, MappingVector& mv)
: iter(i), mapping(mv), commited_size(0)
{
}
push_mapping_decorator(push_mapping_decorator const&) = default;
inline push_mapping_decorator& operator++()
{
++iter;
return *this;
}
inline push_mapping_decorator& operator--()
{
--iter;
return *this;
}
inline bool operator==(Iterator const& i) { return iter == i; }
inline bool operator!=(Iterator const& i) { return iter != i; }
inline decltype(iter.value()) value() const { return iter.value(); }
inline decltype(iter.type()) type() const { return iter.type(); }
inline size_t position() const { return iter.position(); }
inline void push_mapping()
{
mapping.push_back(position());
}
inline void commit_mapping()
{
commited_size = mapping.size();
}
inline void rollback_mapping()
{
mapping.resize(commited_size);
}
};
template<typename Iterator, class MappingVector>
push_mapping_decorator<MappingVector, Iterator> pm_decorated(Iterator i, MappingVector& mv)
{
return {i, mv};
}
template<typename T>
class is_pm_decorated
{
template<class C> static bool sfinae_fun(C* cptr,
decltype(cptr->has_mapping())* = 0)
{
return true;
}
static void sfinae_fun(void*) { }
typedef decltype(sfinae_fun(static_cast<T*>(nullptr))) result_type;
public:
static constexpr bool value = std::is_same<bool, result_type>::value;
};
template<typename T>
inline typename util::disable_if<is_pm_decorated<T>, void>::type
push_mapping(T&) { }
template<typename T>
inline typename util::enable_if<is_pm_decorated<T>, void>::type
push_mapping(T& iter)
{
iter.push_mapping();
}
template<typename T>
inline typename util::disable_if<is_pm_decorated<T>, void>::type
commit_mapping(T&) { }
template<typename T>
inline typename util::enable_if<is_pm_decorated<T>, void>::type
commit_mapping(T& iter)
{
iter.commit_mapping();
}
template<typename T>
inline typename util::disable_if<is_pm_decorated<T>, void>::type
rollback_mapping(T&) { }
template<typename T>
inline typename util::enable_if<is_pm_decorated<T>, void>::type
rollback_mapping(T& iter)
{
iter.rollback_mapping();
}
template<class TupleBeginIterator, class TupleEndIterator, class PatternIterator>
bool matches(TupleBeginIterator tbegin, TupleEndIterator tend,
PatternIterator pbegin, PatternIterator pend)
{
while (!(pbegin == pend && tbegin == tend))
{
if (pbegin == pend)
{
return false;
}
else if (pbegin.type() == nullptr) // nullptr == wildcard (anything)
{
// perform submatching
++pbegin;
if (pbegin == pend)
{
// always true at the end of the pattern
return true;
}
// safe current mapping as fallback
commit_mapping(tbegin);
// iterate over tu_args until we found a match
for (; tbegin != tend; ++tbegin)
{
if (matches(tbegin, tend, pbegin, pend)) return true;
// restore mapping to fallback (delete invalid mappings)
rollback_mapping(tbegin);
}
return false; // no submatch found
}
// compare types
else if (tbegin != tend && pbegin.type() == tbegin.type())
{
// compare values if needed
if ( pbegin.value() == nullptr
|| pbegin.type()->equals(pbegin.value(), tbegin.value()))
{
push_mapping(tbegin);
}
else
{
return false; // values didn't match
}
}
else
{
return false; // no match
}
}
return true; // pbegin == pend && targ.at_end()
}
// pattern does not contain "anything"
template<class Tuple, class Pattern>
bool matches(std::integral_constant<int, 0>,
Tuple const& tpl, Pattern const& pttrn,
util::fixed_vector<size_t, Pattern::filtered_size>* mv)
{
// assertion "tpl.size() == pttrn.size()" is guaranteed from caller
typedef typename Pattern::types ptypes;
typedef typename decorated_tuple_from_type_list<ptypes>::type dec_t;
typedef typename tuple_vals_from_type_list<ptypes>::type tv_t;
std::type_info const& tinfo = tpl.impl_type();
auto j = pttrn.begin();
auto end = tpl.end();
if (tinfo == typeid(dec_t) || tinfo == typeid(tv_t))
{
if (pttrn.has_values())
{
// compare values only (types are guaranteed to be equal)
for (auto i = tpl.begin(); i != end; ++i, ++j)
{
if ( j.value() != nullptr
&& i.type()->equals(i.value(), j.value()) == false)
{
return false;
}
}
}
}
else if (tinfo == typeid(object_array))
{
if (pttrn.has_values())
{
// compares type and value
for (auto i = tpl.begin(); i != end; ++i, ++j)
{
if ( i.type() != j.type()
|| ( j.value() != nullptr
&& i.type()->equals(i.value(), j.value()) == false))
{
return false;
}
}
}
else
{
// compares the types only
for (auto i = tpl.begin(); i != end; ++i, ++j)
{
if (i.type() != j.type()) return false;
}
}
}
else
{
return false;
}
// ok => match
if (mv) for (size_t i = 0; i < Pattern::size; ++i) mv->push_back(i);
return true;
}
// "anything" at end of pattern
template<class Tuple, class Pattern>
bool matches(std::integral_constant<int, 1>,
Tuple const& tpl, Pattern const& pttrn,
util::fixed_vector<size_t, Pattern::filtered_size>* mv)
{
static_assert(Pattern::size > 0, "empty pattern");
auto end = pttrn.end();
--end; // iterate until we reach "anything"
size_t i = 0;
if (pttrn.has_values())
{
for (auto iter = pttrn.begin(); iter != end; ++iter, ++i)
{
if (iter->first != tpl.type_at(i)) return false;
if (iter->second)
{
if (iter->first->equals(iter->second, tpl.at(i)) == false)
return false;
}
}
}
else
{
for (auto iter = pttrn.begin(); iter != end; ++iter, ++i)
{
if (iter->first != tpl.type_at(i)) return false;
}
}
// ok => match, fill vector if needed and pattern is != <anything>
if (mv)
{
// fill vector up to the position of 'anything'
size_t end = Pattern::size - 1;
for (size_t i = 0; i < end; ++i) mv->push_back(i);
}
return true;
}
// "anything" somewhere in between (ugh!)
template<class Tuple, class Pattern>
bool matches(std::integral_constant<int, 2>,
Tuple const& tpl, Pattern const& ptrn,
util::fixed_vector<size_t, Pattern::filtered_size>* mv = 0)
{
if (mv)
return matches(pm_decorated(tpl.begin(), *mv), tpl.end(), ptrn.begin(), ptrn.end());
return matches(tpl.begin(), tpl.end(), ptrn.begin(), ptrn.end());
}
template<class Tuple, class Pattern>
inline bool matches(Tuple const& tpl, Pattern const& pttrn,
util::fixed_vector<size_t, Pattern::filtered_size>* mv = 0)
{
typedef typename Pattern::types ptypes;
static constexpr int first_anything = util::tl_find<ptypes, anything>::value;
// impl0 = no anything
// impl1 = anything at end
// impl2 = anything somewhere in between
static constexpr int impl = (first_anything == -1)
? 0
: ((first_anything == ((int) Pattern::size) - 1) ? 1 : 2);
std::integral_constant<int, impl> token;
return matches(token, tpl, pttrn, mv);
}
} } // namespace cppa::detail
#endif // DO_MATCH_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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 TUPLE_CAST_IMPL_HPP
#define TUPLE_CAST_IMPL_HPP
#include "cppa/pattern.hpp"
#include "cppa/type_value_pair.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/object_array.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/decorated_tuple.hpp"
namespace cppa { namespace detail {
enum class tuple_cast_impl_id
{
no_wildcard,
trailing_wildcard,
leading_wildcard,
wildcard_in_between
};
template<tuple_cast_impl_id, class Result, typename... T>
struct tuple_cast_impl;
template<class Result, typename... T>
struct tuple_cast_impl<tuple_cast_impl_id::no_wildcard, Result, T...>
{
template<class Tuple>
inline static bool types_match(Tuple const& tup)
{
auto& impl_typeid = tup.impl_type();
if ( impl_typeid == typeid(tuple_vals<T...>)
|| impl_typeid == typeid(decorated_tuple<T...>))
{
return true;
}
else if (impl_typeid == typeid(object_array))
{
if (tup.size() == sizeof...(T))
{
auto& tarr = static_types_array<T...>::arr;
for (size_t i = 0; i < sizeof...(T); ++i)
{
if (tarr[i] != tup.type_at(i)) return false;
}
return true;
}
}
return false;
}
template<class Tuple>
static option<Result> _(Tuple const& tup, pattern<T...> const& p)
{
if (types_match(tup))
{
if ( p.has_values() == false
|| std::equal(tup.begin(), tup.end(), p.begin(),
values_only_eq))
{
return {Result::from(tup.vals())};
}
}
return {};
}
template<class Tuple>
static option<Result> _(Tuple const& tup)
{
if (types_match(tup))
{
return {Result::from(tup.vals())};
}
return {};
}
};
template<class Result, typename... T>
struct tuple_cast_impl<tuple_cast_impl_id::trailing_wildcard, Result, T...>
{
static_assert(sizeof...(T) > 1, "tuple_cast<anything> (empty result)");
template<class Tuple>
inline static option<Result> _(Tuple const& tup, pattern<T...> const& p)
{
if (tup.size() >= (sizeof...(T) - 1))
{
// skip last element (wildcard)
auto end = tup.end();
--end;
if (std::equal(tup.begin(), end, p.begin(),
(p.has_values() ? full_eq
: types_only_eq)))
{
return {Result::subtuple(tup.vals())};
}
}
return {};
}
template<class Tuple>
static option<Result> _(Tuple const& tup)
{
if (tup.size() >= (sizeof...(T) - 1))
{
auto& tarr = static_types_array<T...>::arr;
for (size_t i = 0; i < (sizeof...(T) - 1); ++i)
{
if (tarr[i] != tup.type_at(i)) return { };
}
return {Result::subtuple(tup.vals())};
}
return {};
}
};
template<class Result, typename... T>
struct tuple_cast_impl<tuple_cast_impl_id::leading_wildcard, Result, T...>
{
static_assert(sizeof...(T) > 1, "tuple_cast<anything> (empty result)");
template<class Tuple>
inline static option<Result> _(Tuple const& tup, pattern<T...> const& p)
{
if (tup.size() >= (sizeof...(T) - 1))
{
size_t offset = tup.size() - (sizeof...(T) - 1);
// skip first elements in tuple
auto begin = tup.begin();
begin += offset;
// skip first element (wildcard) of pattern
auto pbegin = p.begin();
++pbegin;
if (std::equal(begin, tup.end(), pbegin,
(p.has_values() ? full_eq
: types_only_eq)))
{
return {Result::offset_subtuple(tup.vals(), offset)};
}
}
return {};
}
template<class Tuple>
static option<Result> _(Tuple const& tup)
{
if (tup.size() >= (sizeof...(T) - 1))
{
size_t offset = tup.size() - (sizeof...(T) - 1);
auto& tarr = static_types_array<T...>::arr;
for (size_t i = offset, j = 1; i < tup.size(); ++i, ++j)
{
if (tarr[j] != tup.type_at(i)) return { };
}
return {Result::offset_subtuple(tup.vals(), offset)};
}
return {};
}
};
template<class Result, typename... T>
struct tuple_cast_impl<tuple_cast_impl_id::wildcard_in_between, Result, T...>
{
static_assert(sizeof...(T) > 1, "tuple_cast<anything> (empty result)");
typedef util::type_list<T...> types;
typedef typename util::tl_filter_not<types, util::tbind<std::is_same, anything>::type>::type
filtered_types;
// mapping vector type
static constexpr size_t filtered_size = filtered_types::size;
typedef util::fixed_vector<size_t, filtered_types::size> mapping_vector;
// iterator types
typedef type_value_pair_const_iterator pattern_iterator;
typedef abstract_tuple::const_iterator const_iterator;
inline static bool matches(mapping_vector& mv,
const_iterator tbegin,
const_iterator tend,
pattern_iterator pbegin,
pattern_iterator pend)
{
while (!(pbegin == pend && tbegin == tend))
{
if (pbegin == pend)
{
// reached end of pattern while some values remain unmatched
return false;
}
else if (pbegin.type() == nullptr) // nullptr == wildcard (anything)
{
// perform submatching
++pbegin;
if (pbegin == pend)
{
// always true at the end of the pattern
return true;
}
// safe current mapping as fallback
auto s = mv.size();
// iterate over tuple values until we found a match
for (; tbegin != tend; ++tbegin)
{
if (matches(mv, tbegin, tend, pbegin, pend)) return true;
// restore mapping to fallback (delete invalid mappings)
mv.resize(s);
}
return false; // no submatch found
}
else if (full_eq(tbegin, *pbegin))
{
mv.push_back(tbegin.position());
}
else
{
return false; // no match
}
// next iteration
++tbegin;
++pbegin;
}
return true; // pbegin == pend && tbegin == tend
}
template<class Tuple>
inline static option<Result> _(Tuple const& tup, pattern<T...> const& p)
{
util::fixed_vector<size_t, Result::num_elements> mv;
if (matches(mv, tup.begin(), tup.end(), p.begin(), p.end()))
{
return {Result::from(tup.vals(), mv)};
}
return {};
}
template<class Tuple>
static option<Result> _(Tuple const& tup)
{
util::fixed_vector<size_t, Result::num_elements> mv;
auto& tarr = static_types_array<T...>::arr;
if (matches(mv, tup.begin(), tup.end(), tarr.begin(), tarr.end()))
{
return {Result::from(tup.vals(), mv)};
}
return {};
}
};
template<typename... T>
struct select_tuple_cast_impl
{
typedef util::type_list<T...> types;
typedef util::tl_find<types, anything> result1;
typedef typename result1::rest_list rest_list;
static constexpr int wc1 = result1::value;
static constexpr int wc2 =
(wc1 < 0)
? -1
: (util::tl_find<rest_list, anything>::value + wc1 + 1);
static constexpr tuple_cast_impl_id value =
(wc1 == -1)
? tuple_cast_impl_id::no_wildcard
: ((wc1 == 0 && wc2 == -1)
? tuple_cast_impl_id::leading_wildcard
: ((wc1 == (sizeof...(T) - 1) && wc2 == -1)
? tuple_cast_impl_id::trailing_wildcard
: tuple_cast_impl_id::wildcard_in_between));
};
} }
#endif // TUPLE_CAST_IMPL_HPP
......@@ -74,11 +74,6 @@ class tuple_vals : public abstract_tuple
return m_data;
}
inline data_type& data_ref()
{
return m_data;
}
size_t size() const
{
return sizeof...(ElementTypes);
......
......@@ -28,68 +28,463 @@
\******************************************************************************/
#ifndef MATCH_HPP
#define MATCH_HPP
#ifndef MATCHES_HPP
#define MATCHES_HPP
#include <type_traits>
#include "cppa/tuple.hpp"
#include "cppa/invoke_rules.hpp"
#include "cppa/pattern.hpp"
#include "cppa/anything.hpp"
#include "cppa/any_tuple.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/implicit_conversions.hpp"
#include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/object_array.hpp"
#include "cppa/detail/decorated_tuple.hpp"
namespace cppa {
enum class pattern_characteristic
{
no_wildcard,
trailing_wildcard,
leading_wildcard,
wildcard_in_between,
multiple_wildcards
};
template<typename Types>
constexpr pattern_characteristic get_pattern_characteristic()
{
return util::tl_exists<Types, util::tbind<std::is_same, anything>::type>::value
? ((util::tl_count<Types, util::tbind<std::is_same, anything>::type>::value == 1)
? (std::is_same<typename Types::head, anything>::value
? pattern_characteristic::leading_wildcard
: (std::is_same<typename Types::back, anything>::value
? pattern_characteristic::trailing_wildcard
: pattern_characteristic::wildcard_in_between))
: pattern_characteristic::multiple_wildcards)
: pattern_characteristic::no_wildcard;
}
namespace detail {
template<pattern_characteristic, typename...> struct matcher;
} // namespace cppa
template<typename Tuple>
struct match_helper
template<pattern_characteristic PC, typename... Ts>
struct match_impl
{
//static constexpr bool is_view = std::is_same<Tuple, any_tuple_view>::value;
static constexpr bool is_view = false;
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)
{
(*this)(bhvr.splice(std::forward<Head>(head)),
std::forward<Tail>(tail)...);
static inline bool _(any_tuple const& tup)
{
return detail::matcher<PC, Ts...>::tmatch(tup);
}
template<size_t Size>
static inline bool _(any_tuple const& tup,
util::fixed_vector<size_t, Size>& mv)
{
return detail::matcher<PC, Ts...>::tmatch(tup, mv);
}
static inline bool _(any_tuple const& tup,
pattern<Ts...> const& p)
{
return detail::matcher<PC, Ts...>::tmatch(tup)
&& ( p.has_values() == false
|| detail::matcher<PC, Ts...>::vmatch(tup, p));
}
static inline bool _(any_tuple const& tup,
pattern<Ts...> const& p,
typename pattern<Ts...>::mapping_vector& mv)
{
return detail::matcher<PC, Ts...>::tmatch(tup, mv)
&& ( p.has_values() == false
|| detail::matcher<PC, Ts...>::vmatch(tup, p));
}
};
} // namespace detail
template<typename... Ts>
struct match_impl<pattern_characteristic::multiple_wildcards, Ts...>
{
static constexpr auto PC = pattern_characteristic::multiple_wildcards;
static inline bool _(any_tuple const& tup)
{
return detail::matcher<PC, Ts...>::tmatch(tup);
}
template<size_t Size>
static inline bool _(any_tuple const& tup,
util::fixed_vector<size_t, Size>& mv)
{
return detail::matcher<PC, Ts...>::tmatch(tup, mv);
}
static inline bool _(any_tuple const& tup, pattern<Ts...> const& p)
{
if (p.has_values())
{
typename pattern<Ts...>::mapping_vector mv;
return detail::matcher<PC, Ts...>::tmatch(tup, mv)
&& detail::matcher<PC, Ts...>::vmatch(tup, p, mv);
}
return detail::matcher<PC, Ts...>::tmatch(tup);
}
static inline bool _(any_tuple const& tup, pattern<Ts...> const& p,
typename pattern<Ts...>::mapping_vector& mv)
{
if (p.has_values())
{
typename pattern<Ts...>::mapping_vector mv;
return detail::matcher<PC, Ts...>::tmatch(tup, mv)
&& detail::matcher<PC, Ts...>::vmatch(tup, p, mv);
}
return detail::matcher<PC, Ts...>::tmatch(tup, mv);
}
};
/*
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>
template<typename... Ts>
inline bool match(any_tuple const& tup)
{
return {x};
typedef util::type_list<Ts...> tl;
return match_impl<get_pattern_characteristic<tl>(), Ts...>::_(tup);
}
*/
template<typename... Ts>
inline bool match(any_tuple const& tup,
util::fixed_vector<
size_t,
util::tl_count_not<
util::type_list<Ts...>,
util::tbind<std::is_same, anything>::type>::value>& mv)
{
typedef util::type_list<Ts...> tl;
return match_impl<get_pattern_characteristic<tl>(), Ts...>::_(tup, mv);
}
template<typename... Ts>
inline bool match(any_tuple const& tup, pattern<Ts...> const& ptrn)
{
typedef util::type_list<Ts...> tl;
return match_impl<get_pattern_characteristic<tl>(), Ts...>::_(tup, ptrn);
}
template<typename... Ts>
inline bool match(any_tuple const& tup,
pattern<Ts...> const& ptrn,
typename pattern<Ts...>::mapping_vector& mv)
{
typedef util::type_list<Ts...> tl;
return match_impl<get_pattern_characteristic<tl>(), Ts...>::_(tup,
ptrn,
mv);
}
/******************************************************************************\
** implementation details **
\******************************************************************************/
namespace detail {
template<typename... T>
struct matcher<pattern_characteristic::no_wildcard, T...>
{
static inline bool tmatch(any_tuple const& tup)
{
auto& impl_typeid = tup.impl_type();
if ( impl_typeid == typeid(tuple_vals<T...>)
|| impl_typeid == typeid(decorated_tuple<T...>))
{
return true;
}
else if ( impl_typeid == typeid(detail::object_array)
&& tup.size() == sizeof...(T))
{
auto& tarr = detail::static_types_array<T...>::arr;
return std::equal(tup.begin(), tup.end(), tarr.begin(),
detail::types_only_eq);
}
return false;
}
static inline bool tmatch(any_tuple const& tup,
util::fixed_vector<size_t, sizeof...(T)>& mv)
{
if (tmatch(tup))
{
size_t i = 0;
mv.resize(sizeof...(T));
std::generate(mv.begin(), mv.end(), [&]() { return i++; });
return true;
}
return false;
}
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{
return std::equal(tup.begin(), tup.end(), ptrn.begin(),
detail::values_only_eq);
}
};
template<typename... T>
struct matcher<pattern_characteristic::trailing_wildcard, T...>
{
static constexpr size_t size = sizeof...(T) - 1;
static inline bool tmatch(any_tuple const& tup)
{
if (tup.size() >= size)
{
auto& tarr = static_types_array<T...>::arr;
auto begin = tup.begin();
return std::equal(begin, begin + size, tarr.begin(),
detail::types_only_eq);
}
return false;
}
static inline bool tmatch(any_tuple const& tup,
util::fixed_vector<size_t, size>& mv)
{
if (tmatch(tup))
{
size_t i = 0;
mv.resize(size);
std::generate(mv.begin(), mv.end(), [&]() { return i++; });
return true;
}
return false;
}
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{
auto begin = tup.begin();
return std::equal(begin, begin + size, ptrn.begin(),
detail::values_only_eq);
}
};
template<>
struct matcher<pattern_characteristic::leading_wildcard, anything>
{
static inline bool tmatch(any_tuple const&)
{
return true;
}
static inline bool tmatch(any_tuple const&, util::fixed_vector<size_t, 0>&)
{
return true;
}
static inline bool vmatch(any_tuple const&, pattern<anything> const&)
{
return true;
}
};
template<typename... T>
struct matcher<pattern_characteristic::leading_wildcard, T...>
{
static constexpr size_t size = sizeof...(T) - 1;
static inline bool tmatch(any_tuple const& tup)
{
auto tup_size = tup.size();
if (tup_size >= size)
{
auto& tarr = static_types_array<T...>::arr;
auto begin = tup.begin();
begin += (tup_size - size);
return std::equal(begin, tup.end(), tarr.begin(),
detail::types_only_eq);
}
return false;
}
static inline bool tmatch(any_tuple const& tup,
util::fixed_vector<size_t, size>& mv)
{
if (tmatch(tup))
{
size_t i = tup.size() - size;
mv.resize(size);
std::generate(mv.begin(), mv.end(), [&]() { return i++; });
return true;
}
return false;
}
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{
auto begin = tup.begin();
begin += (tup.size() - size);
return std::equal(begin, tup.end(), ptrn.begin() + 1,
detail::values_only_eq);
}
};
template<typename... T>
struct matcher<pattern_characteristic::wildcard_in_between, T...>
{
static constexpr int signed_wc_pos =
util::tl_find<util::type_list<T...>, anything>::value;
static_assert( signed_wc_pos != -1
&& signed_wc_pos != 0
&& signed_wc_pos != (sizeof...(T) - 1),
"illegal wildcard position");
static constexpr size_t wc_pos = static_cast<size_t>(signed_wc_pos);
static constexpr size_t size = sizeof...(T) - 1;
static inline bool tmatch(any_tuple const& tup)
{
auto tup_size = tup.size();
if (tup_size >= size)
{
auto& tarr = static_types_array<T...>::arr;
// first range [0, X1)
auto begin = tup.begin();
auto end = begin + wc_pos;
if (std::equal(begin, end, tarr.begin(), detail::types_only_eq))
{
// second range [X2, N)
begin = end = tup.end();
begin -= (size - (wc_pos + 1));
auto arr_begin = tarr.begin() + wc_pos + 1;
return std::equal(begin, end, arr_begin, detail::types_only_eq);
}
}
return false;
}
static inline bool tmatch(any_tuple const& tup,
util::fixed_vector<size_t, size>& mv)
{
if (tmatch(tup))
{
// first range
size_t i = 0;
mv.resize(size);
auto begin = mv.begin();
std::generate(begin, begin + wc_pos, [&]() { return i++; });
// second range
i = tup.size() - (size - (wc_pos + 1));
begin = mv.begin() + wc_pos;
std::generate(begin, mv.end(), [&]() { return i++; });
return true;
}
return false;
}
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
{
// first range
auto tbegin = tup.begin();
auto tend = tbegin + wc_pos;
if (std::equal(tbegin, tend, ptrn.begin(), detail::values_only_eq))
{
// second range
tbegin = tend = tup.end();
tbegin -= (size - (wc_pos + 1));
auto pbegin = ptrn.begin();
pbegin += (wc_pos + 1);
return std::equal(tbegin, tend, pbegin, detail::values_only_eq);
}
return false;
}
};
template<typename... T>
struct matcher<pattern_characteristic::multiple_wildcards, T...>
{
static constexpr size_t wc_count =
util::tl_count<util::type_list<T...>,
util::tbind<std::is_same, anything>::type>::value;
static_assert(sizeof...(T) > wc_count, "only wildcards given");
template<class TupleIter, class PatternIter,
class Push, class Commit, class Rollback>
static bool match(TupleIter tbegin, TupleIter tend,
PatternIter pbegin, PatternIter pend,
Push&& push, Commit&& commit, Rollback&& rollback)
{
while (!(pbegin == pend && tbegin == tend))
{
if (pbegin == pend)
{
// reached end of pattern while some values remain unmatched
return false;
}
else if (pbegin.type() == nullptr) // nullptr == wildcard (anything)
{
// perform submatching
++pbegin;
// always true at the end of the pattern
if (pbegin == pend) return true;
// safe current mapping as fallback
commit();
// iterate over tuple values until we found a match
for (; tbegin != tend; ++tbegin)
{
if (match(tbegin, tend, pbegin, pend,
push, commit, rollback))
{
return true;
}
// restore mapping to fallback (delete invalid mappings)
rollback();
}
return false; // no submatch found
}
// compare types
else if (tbegin.type() == pbegin.type()) push(tbegin);
// no match
else return false;
// next iteration
++tbegin;
++pbegin;
}
return true; // pbegin == pend && tbegin == tend
}
static inline bool tmatch(any_tuple const& tup)
{
auto& tarr = static_types_array<T...>::arr;
if (tup.size() >= (sizeof...(T) - wc_count))
{
return match(tup.begin(), tup.end(), tarr.begin(), tarr.end(),
[](any_tuple::const_iterator const&) { },
[]() { },
[]() { });
}
return false;
}
template<class MappingVector>
static inline bool tmatch(any_tuple const& tup, MappingVector& mv)
{
auto& tarr = static_types_array<T...>::arr;
if (tup.size() >= (sizeof...(T) - wc_count))
{
size_t commited_size = 0;
return match(tup.begin(), tup.end(), tarr.begin(), tarr.end(),
[&](any_tuple::const_iterator const& iter)
{
mv.push_back(iter.position());
},
[&]() { commited_size = mv.size(); },
[&]() { mv.resize(commited_size); });
}
return false;
}
static inline bool vmatch(any_tuple const& tup,
pattern<T...> const& ptrn,
typename pattern<T...>::mapping_vector const& mv)
{
auto i = mv.begin();
for (auto j = ptrn.begin(); j != ptrn.end(); ++j)
{
if (j.type() != nullptr)
{
if ( j.value() != nullptr
&& j.type()->equals(tup.at(*i), j.value()) == false)
{
return false;
}
++i;
}
}
}
};
} // namespace detail
} // namespace cppa
#endif // MATCH_HPP
#endif // MATCHES_HPP
......@@ -119,26 +119,34 @@ class tuple
tuple& operator=(tuple&&) = default;
tuple& operator=(tuple const&) = default;
static tuple from(cow_ptr_type ptr)
inline static tuple from(cow_ptr_type ptr)
{
if (ptr->size() == sizeof...(ElementTypes))
{
// *this == *ptr
return {priv_ctor(), std::move(ptr)};
}
else
{
// *this is a subtuple of *ptr
return {priv_ctor(), decorated_type::create(std::move(ptr))};
}
return {priv_ctor(), std::move(ptr)};
}
static tuple from(cow_ptr_type ptr,
util::fixed_vector<size_t, num_elements> const& mv)
inline static tuple from(cow_ptr_type ptr,
util::fixed_vector<size_t, num_elements> const& mv)
{
return {priv_ctor(), decorated_type::create(std::move(ptr), mv)};
}
// *this is a [0, N) subtuple
inline static tuple subtuple(cow_ptr_type ptr)
{
// N == ptr->size() ?
if (ptr->size() == num_elements) return from(std::move(ptr));
// no, create subtuple
return {priv_ctor(), decorated_type::create(std::move(ptr))};
}
inline static tuple offset_subtuple(cow_ptr_type ptr, size_t offset)
{
// N == ptr->size() ?
if (ptr->size() == num_elements) return from(std::move(ptr));
// no, create subtuple
return {priv_ctor(), decorated_type::create(std::move(ptr), offset)};
}
/**
* @brief Gets the size of this tuple.
*/
......
......@@ -35,93 +35,23 @@
#include "cppa/option.hpp"
#include "cppa/pattern.hpp"
#include "cppa/any_tuple.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 {
#include "cppa/detail/tuple_cast_impl.hpp"
// cast using a pattern
template<class ResultTuple, class Tuple, typename... P>
option<ResultTuple> tuple_cast_impl(Tuple const& tup, pattern<P...> const& p)
{
typedef util::type_list<P...> types;
static constexpr int apos = util::tl_find<types, anything>::value;
// no anything in given template parameter pack
// or anything at end of template parameter pack
if (apos == -1 || apos == (sizeof...(P) - 1))
{
if (detail::matches(tup, p))
{
return {ResultTuple::from(tup.vals())};
}
}
else
{
typename pattern<P...>::mapping_vector mv;
if (detail::matches(tup, p, &mv))
{
if (mv.size() == tup.size()) // perfect match
{
return {ResultTuple::from(tup.vals())};
}
else
{
return {ResultTuple::from(tup.vals(), mv)};
}
}
}
return { };
}
// cast using types
template<class ResultTuple, class Tuple, typename... T>
option<ResultTuple> tuple_cast_impl(Tuple const& tup)
{
typedef util::type_list<T...> types;
static constexpr int apos = util::tl_find<types, anything>::value;
// no anything in given template parameter pack
// or anything at end of template parameter pack
if (apos == -1 || apos == (sizeof...(T) - 1))
{
if (tup.size() >= sizeof...(T))
{
auto& tarr = detail::static_types_array<T...>::arr;
static constexpr int end = (apos == -1) ? sizeof...(T) : apos;
for (int i = 0; i < end; ++i)
{
if (tarr[i] != tup.type_at(i)) return { };
}
// always a perfect match or subtuple
return {ResultTuple::from(tup.vals())};
}
}
else
{
util::fixed_vector<size_t, ResultTuple::num_elements> mv;
if (detail::matches(tup, detail::static_types_array<T...>::arr, &mv))
{
// never a perfect match
return {ResultTuple::from(tup.vals(), mv)};
}
}
return { };
}
namespace cppa {
// cast using a pattern
template<typename... P>
auto tuple_cast(any_tuple const& tup, pattern<P...> const& p)
template<typename... T>
auto tuple_cast(any_tuple const& tup, pattern<T...> const& p)
-> option<
typename tuple_from_type_list<
typename pattern<P...>::filtered_types
typename pattern<T...>::filtered_types
>::type>
{
typedef typename pattern<P...>::filtered_types filtered_types;
typedef typename pattern<T...>::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);
static constexpr auto impl = detail::select_tuple_cast_impl<T...>::value;
return detail::tuple_cast_impl<impl, tuple_type, T...>::_(tup, p);
}
// cast using types
......@@ -137,38 +67,9 @@ auto tuple_cast(any_tuple const& tup)
{
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);
static constexpr auto impl = detail::select_tuple_cast_impl<T...>::value;
return detail::tuple_cast_impl<impl, tuple_type, T...>::_(tup);
}
*/
} // namespace cppa
......
......@@ -84,17 +84,8 @@ class fixed_vector
void resize(size_type s)
{
CPPA_REQUIRE(s < MaxSize);
if (s > m_size)
{
auto x = T();
auto old_size = m_size;
for (auto i = old_size; i < s; ++i) push_back(x);
}
else
{
m_size = s;
}
CPPA_REQUIRE(s <= MaxSize);
m_size = s;
}
fixed_vector(std::initializer_list<T> init) : m_size(init.size())
......
......@@ -135,14 +135,21 @@ template<typename What, int Pos>
struct tl_find<type_list<>, What, Pos>
{
static constexpr int value = -1;
typedef type_list<> rest_list;
};
template<typename What, int Pos, typename... Tail>
struct tl_find<type_list<What, Tail...>, What, Pos>
{
static constexpr int value = Pos;
typedef type_list<Tail...> rest_list;
};
template<typename What, int Pos, typename Head, typename... Tail>
struct tl_find<type_list<Head, Tail...>, What, Pos>
{
static constexpr int value = std::is_same<Head, What>::value
? Pos
: tl_find<type_list<Tail...>, What, Pos+1>::value;
static constexpr int value = tl_find<type_list<Tail...>, What, Pos+1>::value;
typedef typename tl_find<type_list<Tail...>, What, Pos+1>::rest_list rest_list;
};
// list list::first_n(size_t)
......@@ -209,6 +216,45 @@ struct tl_exists<type_list<>, Predicate>
static constexpr bool value = false;
};
// size_t list::count(predicate)
/**
* @brief Counts the number of elements in the list which satisfy a predicate.
*/
template<class List, template <typename> class Predicate>
struct tl_count
{
static constexpr size_t value =
(Predicate<typename List::head>::value ? 1 : 0)
+ tl_count<typename List::tail, Predicate>::value;
};
template<template <typename> class Predicate>
struct tl_count<type_list<>, Predicate>
{
static constexpr size_t value = 0;
};
// size_t list::count_not(predicate)
/**
* @brief Counts the number of elements in the list which satisfy a predicate.
*/
template<class List, template <typename> class Predicate>
struct tl_count_not
{
static constexpr size_t value =
(Predicate<typename List::head>::value ? 0 : 1)
+ tl_count_not<typename List::tail, Predicate>::value;
};
template<template <typename> class Predicate>
struct tl_count_not<type_list<>, Predicate>
{
static constexpr size_t value = 0;
};
// bool list::zipped_forall(predicate)
/**
......
......@@ -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"
......@@ -100,10 +100,11 @@ void converted_thread_context::dequeue(timed_invoke_rules& rules) /*override*/
}
while (dq(node, rules, buffer) == false);
}
converted_thread_context::throw_on_exit_result
converted_thread_context::throw_on_exit(any_tuple const& msg)
{
if (matches(msg, m_exit_msg_pattern))
if (match(msg, m_exit_msg_pattern))
{
auto reason = msg.get_as<std::uint32_t>(1);
if (reason != exit_reason::normal)
......
......@@ -5,8 +5,8 @@
#include "cppa/on.hpp"
#include "cppa/atom.hpp"
#include "cppa/tuple.hpp"
#include "cppa/match.hpp"
#include "cppa/tuple.hpp"
#include "cppa/option.hpp"
#include "cppa/pattern.hpp"
#include "cppa/announce.hpp"
......
......@@ -39,30 +39,14 @@ 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);
// get a view of t0
any_tuple atup0(t0);
CPPA_CHECK(atup0.size() == 2 && atup0.at(0) == &get<0>(t0));
/*
auto v1opt = tuple_cast<std::string, anything>(any_tuple_view(atup0));
// the tuple_view forces atup0 to detach from t0
CPPA_CHECK(atup0.size() == 2 && atup0.at(0) != &get<0>(t0));
CPPA_CHECK((v1opt));
if (v1opt)
{
auto& v1 = *v1opt;
CPPA_CHECK((std::is_same<decltype(v1), tuple_view<std::string>&>::value));
CPPA_CHECK_EQUAL(v1.size(), 1);
auto& v1_0 = get<0>(v1);
CPPA_CHECK_EQUAL(v1_0, "1");
CPPA_CHECK_EQUAL(atup0.at(0), &(get<0>(v1))); // point to the same
}
*/
// use tuple cast to get a subtuple
any_tuple at0(t0);
auto v0opt = tuple_cast<std::string, anything>(at0);
CPPA_CHECK((std::is_same<decltype(v0opt), option<tuple<std::string>>>::value));
CPPA_CHECK((v0opt));
CPPA_CHECK(at0.size() == 2 && at0.at(0) == &get<0>(t0));
CPPA_CHECK( at0.size() == 2
&& at0.at(0) == &get<0>(t0)
&& at0.at(1) == &get<1>(t0));
if (v0opt)
{
auto& v0 = *v0opt;
......@@ -84,5 +68,24 @@ size_t test__tuple()
CPPA_CHECK_EQUAL(lhs, rhs);
CPPA_CHECK_EQUAL(rhs, lhs);
}
any_tuple at1 = make_tuple("one", 2, 3.f, 4.0);
{
// perfect match
auto opt0 = tuple_cast<std::string, int, float, double>(at1);
CPPA_CHECK(opt0);
if (opt0) { CPPA_CHECK_EQUAL(*opt0, make_tuple("one", 2, 3.f, 4.0)); }
// leading wildcard
auto opt1 = tuple_cast<anything, double>(at1);
CPPA_CHECK(opt1);
if (opt1) { CPPA_CHECK_EQUAL(get<0>(*opt1), 4.0); }
// trailing wildcard
auto opt2 = tuple_cast<std::string, anything>(at1);
CPPA_CHECK(opt2);
if (opt2) { CPPA_CHECK_EQUAL(get<0>(*opt2), "one"); }
// wildcard in between
auto opt3 = tuple_cast<std::string, anything, double>(at1);
CPPA_CHECK(opt3);
if (opt3) { CPPA_CHECK_EQUAL(*opt3, make_tuple("one", 4.0)); }
}
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