Commit d31dbe5d authored by Dominik Charousset's avatar Dominik Charousset

new iterator interface

parent b453aabb
...@@ -31,15 +31,16 @@ ...@@ -31,15 +31,16 @@
#ifndef ANY_TUPLE_HPP #ifndef ANY_TUPLE_HPP
#define ANY_TUPLE_HPP #define ANY_TUPLE_HPP
#include "cppa/cow_ptr.hpp"
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/config.hpp"
#include "cppa/cow_ptr.hpp"
#include "cppa/detail/abstract_tuple.hpp" #include "cppa/detail/abstract_tuple.hpp"
namespace cppa { namespace cppa {
/** /**
* @brief Describes a fixed-length tuple with elements of any type. * @brief Describes a fixed-length copy-on-write tuple
* with elements of any type.
*/ */
class any_tuple class any_tuple
{ {
...@@ -61,6 +62,12 @@ class any_tuple ...@@ -61,6 +62,12 @@ class any_tuple
template<typename... Args> template<typename... Args>
any_tuple(tuple<Args...> const& t) : m_vals(t.vals()) { } any_tuple(tuple<Args...> const& t) : m_vals(t.vals()) { }
/**
* @brief Creates a tuple and moves the content from @p t.
*/
template<typename... Args>
any_tuple(tuple<Args...>&& t) : m_vals(std::move(t.m_vals)) { }
explicit any_tuple(detail::abstract_tuple*); explicit any_tuple(detail::abstract_tuple*);
/** /**
...@@ -83,45 +90,60 @@ class any_tuple ...@@ -83,45 +90,60 @@ class any_tuple
*/ */
any_tuple& operator=(any_tuple const&) = default; any_tuple& operator=(any_tuple const&) = default;
/**
* @brief Gets the size of this tuple.
*/
size_t size() const; size_t size() const;
/**
* @brief Gets a mutable pointer to the element at position @p p.
*/
void* mutable_at(size_t p); void* mutable_at(size_t p);
/**
* @brief Gets a const pointer to the element at position @p p.
*/
void const* at(size_t p) const; void const* at(size_t p) const;
/**
* @brief Gets {@link uniform_type_info uniform type information}
* of the element at position @p p.
*/
uniform_type_info const* type_at(size_t p) const; uniform_type_info const* type_at(size_t p) const;
cow_ptr<detail::abstract_tuple> const& vals() const; /**
* @brief Returns @c true if <tt>*this == other</tt>, otherwise false.
*/
bool equals(any_tuple const& other) const; bool equals(any_tuple const& other) const;
std::type_info const& impl_type() const; /**
* @brief Returns true if <tt>size() == 0</tt>, otherwise false.
*/
inline bool empty() const { return size() == 0; }
inline bool empty() const template<typename T>
inline T const& get_as(size_t p) const
{ {
return size() == 0; CPPA_REQUIRE(type_at(p) == typeid(T));
return *reinterpret_cast<T const*>(at(p));
} }
template<typename T> template<typename T>
inline T const& get_as(size_t p) const; inline T& get_mutable_as(size_t p)
{
CPPA_REQUIRE(type_at(p) == typeid(T));
return *reinterpret_cast<T*>(mutable_at(p));
}
template<typename T> typedef type_value_pair const* const_iterator;
inline T& get_mutable_as(size_t p);
class const_iterator inline const_iterator begin() const { return m_vals->begin(); }
{
any_tuple const& ref; inline const_iterator end() const { return m_vals->end(); }
size_t p;
public: std::type_info const& impl_type() const;
inline const_iterator(any_tuple const& data, size_t pos = 0)
: ref(data), p(pos) { } cow_ptr<detail::abstract_tuple> const& vals() const;
inline void next() { ++p; }
inline bool at_end() const { return p >= ref.size(); }
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}; }
}; };
...@@ -135,18 +157,6 @@ inline bool operator!=(any_tuple const& lhs, any_tuple const& rhs) ...@@ -135,18 +157,6 @@ inline bool operator!=(any_tuple const& lhs, any_tuple const& rhs)
return !(lhs == rhs); return !(lhs == rhs);
} }
template<typename T>
inline T const& any_tuple::get_as(size_t p) const
{
return *reinterpret_cast<T const*>(at(p));
}
template<typename T>
inline T& any_tuple::get_mutable_as(size_t p)
{
return *reinterpret_cast<T*>(mutable_at(p));
}
} // namespace cppa } // namespace cppa
#endif // ANY_TUPLE_HPP #endif // ANY_TUPLE_HPP
...@@ -35,6 +35,8 @@ ...@@ -35,6 +35,8 @@
#include <list> #include <list>
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <iterator>
#include <algorithm>
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
...@@ -52,8 +54,7 @@ namespace cppa { ...@@ -52,8 +54,7 @@ namespace cppa {
class any_tuple_view class any_tuple_view
{ {
typedef std::vector< std::pair<uniform_type_info const*, void*> > typedef std::vector<type_value_pair> vector_type;
vector_type;
vector_type m_values; vector_type m_values;
...@@ -80,22 +81,14 @@ class any_tuple_view ...@@ -80,22 +81,14 @@ class any_tuple_view
any_tuple_view(any_tuple& tup) any_tuple_view(any_tuple& tup)
{ {
for (size_t i = 0; i < tup.size(); ++i) if (tup.size() > 0)
{
m_values.push_back(std::make_pair(tup.type_at(i), tup.mutable_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))); // 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);
} }
} }
*/
template<typename... T> template<typename... T>
any_tuple_view(tuple_view<T...> const& tup) any_tuple_view(tuple_view<T...> const& tup)
...@@ -137,7 +130,7 @@ class any_tuple_view ...@@ -137,7 +130,7 @@ class any_tuple_view
inline void const* at(size_t p) const { return m_values[p].second; } inline void const* at(size_t p) const { return m_values[p].second; }
void* mutable_at(size_t p) { 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 inline uniform_type_info const* type_at(size_t p) const
{ {
...@@ -159,21 +152,11 @@ class any_tuple_view ...@@ -159,21 +152,11 @@ class any_tuple_view
return typeid(detail::object_array); return typeid(detail::object_array);
} }
class const_iterator typedef type_value_pair const* const_iterator;
{
typedef typename vector_type::const_iterator vec_iterator; inline const_iterator begin() const { return m_values.data(); }
vec_iterator pos;
vec_iterator end; inline const_iterator end() const { return begin() + m_values.size(); }
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}; }
}; };
......
...@@ -48,6 +48,8 @@ struct abstract_tuple : ref_counted ...@@ -48,6 +48,8 @@ struct abstract_tuple : ref_counted
virtual void* mutable_at(size_t pos) = 0; virtual void* mutable_at(size_t pos) = 0;
// accessors // accessors
virtual const_iterator begin() const = 0;
virtual const_iterator end() const = 0;
virtual size_t size() const = 0; virtual size_t size() const = 0;
virtual abstract_tuple* copy() const = 0; virtual abstract_tuple* copy() const = 0;
virtual void const* at(size_t pos) const = 0; virtual void const* at(size_t pos) const = 0;
......
...@@ -51,30 +51,42 @@ template<typename... ElementTypes> ...@@ -51,30 +51,42 @@ template<typename... ElementTypes>
class decorated_tuple : public abstract_tuple class decorated_tuple : public abstract_tuple
{ {
static_assert(sizeof...(ElementTypes) > 0,
"decorated_tuple is not allowed to be empty");
public: public:
typedef util::fixed_vector<size_t, sizeof...(ElementTypes)> vector_type; typedef util::fixed_vector<size_t, sizeof...(ElementTypes)> vector_type;
typedef cow_ptr<abstract_tuple> ptr_type; typedef cow_ptr<abstract_tuple> ptr_type;
decorated_tuple(ptr_type&& d, vector_type const& v) using abstract_tuple::const_iterator;
: m_decorated(std::move(d)), m_mappings(v)
decorated_tuple(ptr_type&& d, vector_type const& v) : m_decorated(std::move(d))
{ {
CPPA_REQUIRE(v.size() == sizeof...(ElementTypes)); init(v);
CPPA_REQUIRE(std::max_element(v.begin(), v.end()) < m_decorated->size());
} }
decorated_tuple(ptr_type const& d, vector_type const& v) decorated_tuple(ptr_type const& d, vector_type const& v) : m_decorated(d)
: m_decorated(d), m_mappings(v)
{ {
CPPA_REQUIRE(v.size() == sizeof...(ElementTypes)); init(v);
CPPA_REQUIRE(v.empty() || *(std::max_element(v.begin(), v.end())) < m_decorated->size()); }
virtual const_iterator begin() const
{
return m_data;
}
virtual const_iterator end() const
{
return static_cast<const_iterator>(m_data) + sizeof...(ElementTypes);
} }
virtual void* mutable_at(size_t pos) virtual void* mutable_at(size_t pos)
{ {
CPPA_REQUIRE(pos < size()); CPPA_REQUIRE(pos < size());
return m_decorated->mutable_at(m_mappings[pos]); // const_cast is safe because decorated_tuple is used in cow_ptrs only
return const_cast<void*>(m_data[pos].second);
} }
virtual size_t size() const virtual size_t size() const
...@@ -90,18 +102,13 @@ class decorated_tuple : public abstract_tuple ...@@ -90,18 +102,13 @@ class decorated_tuple : public abstract_tuple
virtual void const* at(size_t pos) const virtual void const* at(size_t pos) const
{ {
CPPA_REQUIRE(pos < size()); CPPA_REQUIRE(pos < size());
return m_decorated->at(m_mappings[pos]); return m_data[pos].second;
} }
virtual uniform_type_info const* type_at(size_t pos) const virtual uniform_type_info const* type_at(size_t pos) const
{ {
CPPA_REQUIRE(pos < size()); CPPA_REQUIRE(pos < size());
return m_decorated->type_at(m_mappings[pos]); return m_data[pos].first;
}
virtual bool equals(abstract_tuple const&) const
{
return false;
} }
virtual std::type_info const& impl_type() const virtual std::type_info const& impl_type() const
...@@ -109,17 +116,29 @@ class decorated_tuple : public abstract_tuple ...@@ -109,17 +116,29 @@ class decorated_tuple : public abstract_tuple
return typeid(decorated_tuple); return typeid(decorated_tuple);
} }
private: private:
ptr_type m_decorated; ptr_type m_decorated;
vector_type m_mappings; type_value_pair m_data[sizeof...(ElementTypes)];
decorated_tuple(decorated_tuple const& other) decorated_tuple(decorated_tuple const& other)
: abstract_tuple() : abstract_tuple()
, m_decorated(other.m_decorated) , m_decorated(other.m_decorated)
, m_mappings(other.m_mappings)
{ {
// both instances point to the same data
std::copy(other.begin(), other.end(), m_data);
}
void init(vector_type const& v)
{
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);
}
} }
decorated_tuple& operator=(decorated_tuple const&) = delete; decorated_tuple& operator=(decorated_tuple const&) = delete;
......
...@@ -35,9 +35,13 @@ ...@@ -35,9 +35,13 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
struct empty_tuple : cppa::detail::abstract_tuple struct empty_tuple : abstract_tuple
{ {
using abstract_tuple::const_iterator;
const_iterator begin() const;
const_iterator end() const;
size_t size() const; size_t size() const;
void* mutable_at(size_t); void* mutable_at(size_t);
abstract_tuple* copy() const; abstract_tuple* copy() const;
......
...@@ -31,10 +31,12 @@ ...@@ -31,10 +31,12 @@
#ifndef DO_MATCH_HPP #ifndef DO_MATCH_HPP
#define DO_MATCH_HPP #define DO_MATCH_HPP
#include <algorithm>
#include <type_traits> #include <type_traits>
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
#include "cppa/util/enable_if.hpp" #include "cppa/util/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/fixed_vector.hpp" #include "cppa/util/fixed_vector.hpp"
#include "cppa/detail/tuple_vals.hpp" #include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/types_array.hpp" #include "cppa/detail/types_array.hpp"
...@@ -43,42 +45,17 @@ ...@@ -43,42 +45,17 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
template<class T, typename Iterator> template<typename T>
class cppa_iterator_decorator inline auto ptr_type(T& ptr, util::enable_if<std::is_pointer<T>>* = 0) -> T
{ {
return ptr;
}
static types_array<T> tarr; template<typename T>
inline auto ptr_type(T& iter, util::disable_if<std::is_pointer<T>>* = 0) -> decltype(iter.operator->())
Iterator begin; {
Iterator end; return iter.operator->();
size_t pos; }
uniform_type_info const* t;
public:
cppa_iterator_decorator(Iterator first, Iterator last)
: begin(first), end(last), pos(0), t(tarr[0])
{
}
inline void next()
{
++begin;
++pos;
}
inline bool at_end() const { return begin == end; }
inline uniform_type_info const* type() const { return t; }
inline void const* value() const { return &(*begin); }
inline size_t position() const { return pos; }
};
template<class T, typename Iterator>
types_array<T> cppa_iterator_decorator<T, Iterator>::tarr;
template<class MappingVector, typename Iterator> template<class MappingVector, typename Iterator>
class push_mapping_decorator class push_mapping_decorator
...@@ -86,58 +63,65 @@ class push_mapping_decorator ...@@ -86,58 +63,65 @@ class push_mapping_decorator
size_t pos; size_t pos;
Iterator iter; Iterator iter;
MappingVector* mapping; MappingVector& mapping;
size_t commited_size;
public: public:
typedef MappingVector mapping_vector; typedef MappingVector mapping_vector;
push_mapping_decorator(Iterator const& i, MappingVector* mv) push_mapping_decorator(Iterator const& i, MappingVector& mv)
: pos(0), iter(i), mapping(mv) : pos(0), iter(i), mapping(mv), commited_size(0)
{ {
} }
push_mapping_decorator(push_mapping_decorator const& other, push_mapping_decorator(push_mapping_decorator const&) = default;
MappingVector* mv)
: pos(other.pos), iter(other.iter), mapping(mv) inline push_mapping_decorator& operator++()
{ {
++pos;
++iter;
return *this;
}
inline bool operator==(Iterator const& i)
{
return iter == i;
}
inline decltype(*iter) operator*()
{
return *iter;
} }
push_mapping_decorator(push_mapping_decorator&& other) inline decltype(ptr_type(iter)) operator->()
: pos(other.pos), iter(std::move(other.iter)), mapping(other.mapping)
{ {
return ptr_type(iter);
} }
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() inline void push_mapping()
{ {
if (mapping) mapping->push_back(pos); mapping.push_back(pos);
}
inline void commit_mapping()
{
commited_size = mapping.size();
} }
inline void push_mapping(MappingVector const& mv)
inline void rollback_mapping()
{ {
if (mapping) mapping->insert(mapping->end(), mv.begin(), mv.end()); mapping.resize(commited_size);
} }
}; };
template<typename Iterator, class MappingVector> template<typename Iterator, class MappingVector>
push_mapping_decorator<MappingVector, Iterator> pm_decorated(Iterator i, MappingVector* mv) push_mapping_decorator<MappingVector, Iterator> pm_decorated(Iterator i, MappingVector& mv)
{ {
return {i, mv}; return {i, mv};
} }
template<typename Iterator>
auto ci_decorated(Iterator begin, Iterator end)
-> cppa_iterator_decorator<typename util::rm_ref<decltype(*begin)>::type,
Iterator>
{
return {begin, end};
}
template<typename T> template<typename T>
class is_pm_decorated class is_pm_decorated
{ {
...@@ -158,11 +142,44 @@ class is_pm_decorated ...@@ -158,11 +142,44 @@ class is_pm_decorated
}; };
template<class TupleIterator, class PatternIterator> template<typename T>
auto matches(TupleIterator targ, PatternIterator pbegin, PatternIterator pend) inline typename util::disable_if<is_pm_decorated<T>, void>::type
-> typename util::enable_if_c<is_pm_decorated<TupleIterator>::value,bool>::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)
{ {
for ( ; !(pbegin == pend && targ.at_end()); ++pbegin, targ.next()) for ( ; !(pbegin == pend && tbegin == tend); ++pbegin, ++tbegin)
{ {
if (pbegin == pend) if (pbegin == pend)
{ {
...@@ -177,27 +194,25 @@ auto matches(TupleIterator targ, PatternIterator pbegin, PatternIterator pend) ...@@ -177,27 +194,25 @@ auto matches(TupleIterator targ, PatternIterator pbegin, PatternIterator pend)
// always true at the end of the pattern // always true at the end of the pattern
return true; return true;
} }
typename TupleIterator::mapping_vector mv; // safe current mapping as fallback
auto mv_ptr = (targ.has_mapping()) ? &mv : nullptr; commit_mapping(tbegin);
// iterate over tu_args until we found a match // iterate over tu_args until we found a match
for ( ; targ.at_end() == false; mv.clear(), targ.next()) for (; tbegin != tend; ++tbegin)
{ {
if (matches(TupleIterator(targ, mv_ptr), pbegin, pend)) if (matches(tbegin, tend, pbegin, pend)) return true;
{ // restore mapping to fallback (delete invalid mappings)
targ.push_mapping(mv); rollback_mapping(tbegin);
return true;
}
} }
return false; // no submatch found return false; // no submatch found
} }
// compare types // compare types
else if (targ.at_end() == false && pbegin->first == targ.type()) else if (tbegin != tend && pbegin->first == tbegin->first)
{ {
// compare values if needed // compare values if needed
if ( pbegin->second == nullptr if ( pbegin->second == nullptr
|| pbegin->first->equals(pbegin->second, targ.value())) || pbegin->first->equals(pbegin->second, tbegin->second))
{ {
targ.push_mapping(); push_mapping(tbegin);
} }
else else
{ {
...@@ -212,59 +227,13 @@ auto matches(TupleIterator targ, PatternIterator pbegin, PatternIterator pend) ...@@ -212,59 +227,13 @@ auto matches(TupleIterator targ, PatternIterator pbegin, PatternIterator pend)
return true; // pbegin == pend && targ.at_end() return true; // pbegin == pend && targ.at_end()
} }
template<class TupleIterator, class PatternIterator>
auto matches(TupleIterator targ, PatternIterator pbegin, PatternIterator pend)
-> typename util::enable_if_c<!is_pm_decorated<TupleIterator>::value,bool>::type
{
for ( ; !(pbegin == pend && targ.at_end()); ++pbegin, targ.next())
{
if (pbegin == pend)
{
return false;
}
else if (pbegin->first == nullptr) // nullptr == wildcard (anything)
{
// perform submatching
++pbegin;
if (pbegin == pend)
{
// always true at the end of the pattern
return true;
}
// iterate over tu_args until we found a match
for ( ; targ.at_end() == false; targ.next())
{
if (matches(targ, pbegin, pend))
{
return true;
}
}
return false; // no submatch found
}
// compare types
else if (targ.at_end() == false && pbegin->first == targ.type())
{
// compare values if needed
if ( pbegin->second != nullptr
&& !pbegin->first->equals(pbegin->second, targ.value()))
{
return false; // values didn't match
}
}
else
{
return false; // no match
}
}
return true; // pbegin == pend && targ.at_end()
}
// pattern does not contain "anything" // pattern does not contain "anything"
template<class Tuple, class Pattern> template<class Tuple, class Pattern>
bool matches(std::integral_constant<int, 0>, bool matches(std::integral_constant<int, 0>,
Tuple const& tpl, Pattern const& pttrn, Tuple const& tpl, Pattern const& pttrn,
util::fixed_vector<size_t, Pattern::filtered_size>* mv) 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 Pattern::types ptypes;
typedef typename decorated_tuple_from_type_list<ptypes>::type dec_t; typedef typename decorated_tuple_from_type_list<ptypes>::type dec_t;
typedef typename tuple_vals_from_type_list<ptypes>::type tv_t; typedef typename tuple_vals_from_type_list<ptypes>::type tv_t;
...@@ -273,18 +242,17 @@ bool matches(std::integral_constant<int, 0>, ...@@ -273,18 +242,17 @@ bool matches(std::integral_constant<int, 0>,
{ {
if (pttrn.has_values()) if (pttrn.has_values())
{ {
size_t i = 0; // compare values only (types are guaranteed to be equal)
auto end = pttrn.end(); auto eq = [](type_value_pair const& lhs, type_value_pair const& rhs)
for (auto iter = pttrn.begin(); iter != end; ++iter) {
// pattern (rhs) does not have to have a value
return rhs.second == nullptr
|| lhs.first->equals(lhs.second, rhs.second);
};
if (std::equal(tpl.begin(), tpl.end(), pttrn.begin(), eq) == false)
{ {
if (iter->second) // values differ
{ return false;
if (iter->first->equals(iter->second, tpl.at(i)) == false)
{
return false;
}
}
++i;
} }
} }
} }
...@@ -292,25 +260,31 @@ bool matches(std::integral_constant<int, 0>, ...@@ -292,25 +260,31 @@ bool matches(std::integral_constant<int, 0>,
{ {
if (pttrn.has_values()) if (pttrn.has_values())
{ {
size_t i = 0; // compares type and value
auto end = pttrn.end(); auto eq = [](type_value_pair const& lhs, type_value_pair const& rhs)
for (auto iter = pttrn.begin(); iter != end; ++iter, ++i)
{ {
if (iter->first != tpl.type_at(i)) return false; // pattern (rhs) does not have to have a value
if (iter->second) return lhs.first == rhs.first
{ && ( rhs.second == nullptr
if (iter->first->equals(iter->second, tpl.at(i)) == false) || lhs.first->equals(lhs.second, rhs.second));
return false; };
} if (std::equal(tpl.begin(), tpl.end(), pttrn.begin(), eq) == false)
{
// types or values differ
return false;
} }
} }
else else
{ {
size_t i = 0; // compares the types only
auto end = pttrn.end(); auto eq = [](type_value_pair const& lhs, type_value_pair const& rhs)
for (auto iter = pttrn.begin(); iter != end; ++iter, ++i) {
return lhs.first == rhs.first;
};
if (std::equal(tpl.begin(), tpl.end(), pttrn.begin(), eq) == false)
{ {
if (iter->first != tpl.type_at(i)) return false; // types differ
return false;
} }
} }
} }
...@@ -369,8 +343,8 @@ bool matches(std::integral_constant<int, 2>, ...@@ -369,8 +343,8 @@ bool matches(std::integral_constant<int, 2>,
util::fixed_vector<size_t, Pattern::filtered_size>* mv = 0) util::fixed_vector<size_t, Pattern::filtered_size>* mv = 0)
{ {
if (mv) if (mv)
return matches(pm_decorated(tpl.begin(), mv), ptrn.begin(), ptrn.end()); return matches(pm_decorated(tpl.begin(), *mv), tpl.end(), ptrn.begin(), ptrn.end());
return matches(tpl.begin(), ptrn.begin(), ptrn.end()); return matches(tpl.begin(), tpl.end(), ptrn.begin(), ptrn.end());
} }
template<class Tuple, class Pattern> template<class Tuple, class Pattern>
......
...@@ -34,32 +34,37 @@ ...@@ -34,32 +34,37 @@
#include <vector> #include <vector>
#include "cppa/object.hpp" #include "cppa/object.hpp"
#include "cppa/type_value_pair.hpp"
#include "cppa/detail/abstract_tuple.hpp" #include "cppa/detail/abstract_tuple.hpp"
namespace cppa { namespace detail { namespace cppa { namespace detail {
class object_array : public detail::abstract_tuple class object_array : public abstract_tuple
{ {
std::vector<object> m_elements; std::vector<object> m_elements;
std::vector<type_value_pair> m_data;
public: public:
using abstract_tuple::const_iterator;
object_array(); object_array();
object_array(object_array&& other); object_array(object_array&& other);
object_array(object_array const& other); object_array(object_array const& other);
/**
* @pre
*/
void push_back(object&& what); void push_back(object&& what);
void push_back(object const& what); void push_back(object const& what);
void* mutable_at(size_t pos); void* mutable_at(size_t pos);
const_iterator begin() const;
const_iterator end() const;
size_t size() const; size_t size() const;
abstract_tuple* copy() const; abstract_tuple* copy() const;
......
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
#include <stdexcept> #include <stdexcept>
#include "cppa/type_value_pair.hpp"
#include "cppa/util/type_list.hpp" #include "cppa/util/type_list.hpp"
#include "cppa/detail/tdata.hpp" #include "cppa/detail/tdata.hpp"
...@@ -46,6 +48,9 @@ template<typename... ElementTypes> ...@@ -46,6 +48,9 @@ template<typename... ElementTypes>
class tuple_vals : public abstract_tuple class tuple_vals : public abstract_tuple
{ {
static_assert(sizeof...(ElementTypes) > 0,
"tuple_vals is not allowed to be empty");
typedef abstract_tuple super; typedef abstract_tuple super;
typedef tdata<ElementTypes...> data_type; typedef tdata<ElementTypes...> data_type;
...@@ -56,33 +61,45 @@ class tuple_vals : public abstract_tuple ...@@ -56,33 +61,45 @@ class tuple_vals : public abstract_tuple
static types_array<ElementTypes...> m_types; static types_array<ElementTypes...> m_types;
template<typename... Types> type_value_pair m_view[sizeof...(ElementTypes)];
void* tdata_mutable_at(tdata<Types...>& d, size_t pos)
{
return (pos == 0) ? &(d.head) : tdata_mutable_at(d.tail(), pos - 1);
}
template<typename... Types> void init_view()
void const* tdata_at(tdata<Types...> const& d, size_t pos) const
{ {
return (pos == 0) ? &(d.head) : tdata_at(d.tail(), pos - 1); for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{
m_view[i].first = m_types[i];
m_view[i].second = m_data.at(i);
}
} }
public: public:
tuple_vals(tuple_vals const& other) : super(), m_data(other.m_data) { } using abstract_tuple::const_iterator;
tuple_vals() : m_data() { } tuple_vals() : m_data() { init_view(); }
tuple_vals(ElementTypes const&... args) : m_data(args...) { } tuple_vals(tuple_vals const& other) : super(), m_data(other.m_data) { init_view(); }
inline data_type const& data() const { return m_data; } tuple_vals(ElementTypes const&... args) : m_data(args...) { init_view(); }
inline data_type& data_ref() { return m_data; } inline data_type const& data() const
{
return m_data;
}
void* mutable_at(size_t pos) inline data_type& data_ref()
{ {
return tdata_mutable_at(m_data, pos); return m_data;
}
const_iterator begin() const
{
return m_view;
}
const_iterator end() const
{
return begin() + sizeof...(ElementTypes);
} }
size_t size() const size_t size() const
...@@ -97,11 +114,20 @@ class tuple_vals : public abstract_tuple ...@@ -97,11 +114,20 @@ class tuple_vals : public abstract_tuple
void const* at(size_t pos) const void const* at(size_t pos) const
{ {
return tdata_at(m_data, pos); CPPA_REQUIRE(pos < size());
return m_view[pos].second;
}
void* mutable_at(size_t pos)
{
CPPA_REQUIRE(pos < size());
// safe, because tuple_cals is used in cow_ptrs only
return const_cast<void*>(m_view[pos].second);
} }
uniform_type_info const* type_at(size_t pos) const uniform_type_info const* type_at(size_t pos) const
{ {
CPPA_REQUIRE(pos < size());
return m_types[pos]; return m_types[pos];
} }
......
...@@ -73,6 +73,8 @@ class tuple ...@@ -73,6 +73,8 @@ class tuple
"illegal types in tuple definition: " "illegal types in tuple definition: "
"pointers and references are prohibited"); "pointers and references are prohibited");
friend class any_tuple;
typedef detail::tuple_vals<ElementTypes...> data_type; typedef detail::tuple_vals<ElementTypes...> data_type;
cow_ptr<detail::abstract_tuple> m_vals; cow_ptr<detail::abstract_tuple> m_vals;
...@@ -137,7 +139,6 @@ class tuple ...@@ -137,7 +139,6 @@ class tuple
/** /**
* @brief Gets the size of this tuple. * @brief Gets the size of this tuple.
* @returns <tt>sizeof...(ElementTypes)</tt>.
*/ */
inline size_t size() const inline size_t size() const
{ {
...@@ -145,14 +146,16 @@ class tuple ...@@ -145,14 +146,16 @@ class tuple
} }
/** /**
* @brief Gets a pointer to the internal data. * @brief Gets a const pointer to the element at position @p p.
* @returns A const void pointer to the <tt>N</tt>th element.
*/ */
inline void const* at(size_t p) const inline void const* at(size_t p) const
{ {
return m_vals->at(p); return m_vals->at(p);
} }
/**
* @brief Gets a mutable pointer to the element at position @p p.
*/
inline void* mutable_at(size_t p) inline void* mutable_at(size_t p)
{ {
return m_vals->mutable_at(p); return m_vals->mutable_at(p);
...@@ -160,26 +163,17 @@ class tuple ...@@ -160,26 +163,17 @@ class tuple
/** /**
* @brief Gets {@link uniform_type_info uniform type information} * @brief Gets {@link uniform_type_info uniform type information}
* of an element. * of the element at position @p p.
* @returns The uniform type of the <tt>N</tt>th element.
*/ */
inline uniform_type_info const* type_at(size_t p) const inline uniform_type_info const* type_at(size_t p) const
{ {
return m_vals->type_at(p); return m_vals->type_at(p);
} }
# ifdef CPPA_DOCUMENTATION
/**
* @brief Gets the internal data.
* @returns A pointer to the internal data representation.
*/
cow_ptr<InternalData> vals() const;
# else
inline cow_ptr<detail::abstract_tuple> const& vals() const inline cow_ptr<detail::abstract_tuple> const& vals() const
{ {
return m_vals; return m_vals;
} }
# endif
}; };
......
...@@ -70,24 +70,24 @@ class tuple_view ...@@ -70,24 +70,24 @@ class tuple_view
typedef util::type_list<ElementTypes...> types; typedef util::type_list<ElementTypes...> types;
static tuple_view from(std::vector< std::pair<uniform_type_info const*, void*> > const& vec) static tuple_view from(std::vector<type_value_pair> const& vec)
{ {
tuple_view result; tuple_view result;
size_t j = 0; size_t j = 0;
for (auto i = vec.begin(); i != vec.end(); ++i) for (type_value_pair const& tvp : vec)
{ {
result.m_data[j++] = i->second; result.m_data[j++] = const_cast<void*>(tvp.second);
} }
return std::move(result); return std::move(result);
} }
static tuple_view from(std::vector< std::pair<uniform_type_info const*, void*> > const& vec, static tuple_view from(std::vector<type_value_pair> const& vec,
util::fixed_vector<size_t, sizeof...(ElementTypes)> const& mv) util::fixed_vector<size_t, sizeof...(ElementTypes)> const& mv)
{ {
tuple_view result; tuple_view result;
for (size_t i = 0; i < sizeof...(ElementTypes); ++i) for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{ {
result.m_data[i] = vec[mv[i]].second; result.m_data[i] = const_cast<void*>(vec[mv[i]].second);
} }
return std::move(result); return std::move(result);
} }
......
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include <algorithm> #include <algorithm>
#include <stdexcept> #include <stdexcept>
#include "cppa/config.hpp"
namespace cppa { namespace util { namespace cppa { namespace util {
// @warning does not perform any bound checks // @warning does not perform any bound checks
...@@ -62,7 +64,22 @@ class fixed_vector ...@@ -62,7 +64,22 @@ class fixed_vector
fixed_vector(fixed_vector const& other) : m_size(other.m_size) fixed_vector(fixed_vector const& other) : m_size(other.m_size)
{ {
std::copy(other.m_data, other.m_data + other.m_size, m_data); std::copy(other.begin(), other.end(), m_data);
}
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;
}
} }
inline size_type size() const inline size_type size() const
...@@ -117,12 +134,12 @@ class fixed_vector ...@@ -117,12 +134,12 @@ class fixed_vector
inline iterator end() inline iterator end()
{ {
return (static_cast<T*>(m_data) + m_size); return (static_cast<iterator>(m_data) + m_size);
} }
inline const_iterator end() const inline const_iterator end() const
{ {
return (static_cast<T const*>(m_data) + m_size); return (static_cast<const_iterator>(m_data) + m_size);
} }
template<class InputIterator> template<class InputIterator>
......
...@@ -67,14 +67,14 @@ OUTPUT_LANGUAGE = English ...@@ -67,14 +67,14 @@ OUTPUT_LANGUAGE = English
# the file and class documentation (similar to JavaDoc). # the file and class documentation (similar to JavaDoc).
# Set to NO to disable this. # Set to NO to disable this.
BRIEF_MEMBER_DESC = NO BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description. # the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed. # brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES REPEAT_BRIEF = NO
# This tag implements a quasi-intelligent brief description abbreviator # This tag implements a quasi-intelligent brief description abbreviator
# that is used to form the text in various listings. Each string # that is used to form the text in various listings. Each string
......
...@@ -33,6 +33,16 @@ ...@@ -33,6 +33,16 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
abstract_tuple::const_iterator empty_tuple::begin() const
{
return nullptr;
}
abstract_tuple::const_iterator empty_tuple::end() const
{
return nullptr;
}
size_t empty_tuple::size() const size_t empty_tuple::size() const
{ {
return 0; return 0;
......
...@@ -49,11 +49,15 @@ object_array::object_array(object_array const& other) ...@@ -49,11 +49,15 @@ object_array::object_array(object_array const& other)
void object_array::push_back(object const& what) void object_array::push_back(object const& what)
{ {
m_elements.push_back(what); m_elements.push_back(what);
auto& back = m_elements.back();
m_data.push_back({back.type(), back.value()});
} }
void object_array::push_back(object&& what) void object_array::push_back(object&& what)
{ {
m_elements.push_back(std::move(what)); m_elements.push_back(std::move(what));
auto& back = m_elements.back();
m_data.push_back({back.type(), back.value()});
} }
void* object_array::mutable_at(size_t pos) void* object_array::mutable_at(size_t pos)
...@@ -76,6 +80,16 @@ void const* object_array::at(size_t pos) const ...@@ -76,6 +80,16 @@ void const* object_array::at(size_t pos) const
return m_elements[pos].value(); return m_elements[pos].value();
} }
abstract_tuple::const_iterator object_array::begin() const
{
return m_data.data();
}
abstract_tuple::const_iterator object_array::end() const
{
return begin() + m_data.size();
}
bool object_array::equals(cppa::detail::abstract_tuple const& ut) const bool object_array::equals(cppa::detail::abstract_tuple const& ut) const
{ {
if (size() == ut.size()) if (size() == ut.size())
......
...@@ -69,6 +69,7 @@ size_t test__pattern() ...@@ -69,6 +69,7 @@ size_t test__pattern()
pattern<int, anything, int> i3; pattern<int, anything, int> i3;
any_tuple i3_any_tup = make_tuple(1, 2, 3); any_tuple i3_any_tup = make_tuple(1, 2, 3);
/*
auto opt = tuple_cast(i3_any_tup, i3); auto opt = tuple_cast(i3_any_tup, i3);
CPPA_CHECK(opt.valid()); CPPA_CHECK(opt.valid());
if (opt.valid()) if (opt.valid())
...@@ -76,6 +77,7 @@ size_t test__pattern() ...@@ -76,6 +77,7 @@ size_t test__pattern()
CPPA_CHECK_EQUAL(get<0>(*opt), 1); CPPA_CHECK_EQUAL(get<0>(*opt), 1);
CPPA_CHECK_EQUAL(get<1>(*opt), 3); CPPA_CHECK_EQUAL(get<1>(*opt), 3);
} }
*/
announce<foobar>(&foobar::first, &foobar::second); announce<foobar>(&foobar::first, &foobar::second);
......
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