Commit d31dbe5d authored by Dominik Charousset's avatar Dominik Charousset

new iterator interface

parent b453aabb
......@@ -31,15 +31,16 @@
#ifndef ANY_TUPLE_HPP
#define ANY_TUPLE_HPP
#include "cppa/cow_ptr.hpp"
#include "cppa/tuple.hpp"
#include "cppa/config.hpp"
#include "cppa/cow_ptr.hpp"
#include "cppa/detail/abstract_tuple.hpp"
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
{
......@@ -61,6 +62,12 @@ class any_tuple
template<typename... Args>
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*);
/**
......@@ -83,45 +90,60 @@ class any_tuple
*/
any_tuple& operator=(any_tuple const&) = default;
/**
* @brief Gets the size of this tuple.
*/
size_t size() const;
/**
* @brief Gets a mutable pointer to the element at position @p 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;
/**
* @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;
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;
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>
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>
inline T& get_mutable_as(size_t p);
typedef type_value_pair const* const_iterator;
class const_iterator
{
any_tuple const& ref;
size_t p;
public:
inline const_iterator(any_tuple const& data, size_t pos = 0)
: ref(data), p(pos) { }
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 m_vals->begin(); }
inline const_iterator begin() const { return {*this}; }
inline const_iterator end() const { return m_vals->end(); }
std::type_info const& impl_type() const;
cow_ptr<detail::abstract_tuple> const& vals() const;
};
......@@ -135,18 +157,6 @@ inline bool operator!=(any_tuple const& lhs, any_tuple const& 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
#endif // ANY_TUPLE_HPP
......@@ -35,6 +35,8 @@
#include <list>
#include <vector>
#include <utility>
#include <iterator>
#include <algorithm>
#include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp"
......@@ -52,8 +54,7 @@ namespace cppa {
class any_tuple_view
{
typedef std::vector< std::pair<uniform_type_info const*, void*> >
vector_type;
typedef std::vector<type_value_pair> vector_type;
vector_type m_values;
......@@ -80,23 +81,15 @@ class any_tuple_view
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)));
// 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>
explicit any_tuple_view(tuple<T...> const& tup)
{
for (size_t i = 0; i < tup.size(); ++i)
{
m_values.push_back(std::make_pair(tup.type_at(i), tup.at(i)));
}
}
*/
template<typename... T>
any_tuple_view(tuple_view<T...> const& tup)
{
......@@ -137,7 +130,7 @@ class any_tuple_view
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
{
......@@ -159,21 +152,11 @@ class any_tuple_view
return typeid(detail::object_array);
}
class const_iterator
{
typedef typename vector_type::const_iterator vec_iterator;
vec_iterator pos;
vec_iterator end;
public:
inline const_iterator(any_tuple_view const& view)
: pos(view.m_values.begin()), end(view.m_values.end()) { }
inline void next() { ++pos; }
inline bool at_end() const { return pos == end; }
inline void const* value() const { return pos->second; }
inline uniform_type_info const* type() const { return pos->first; }
};
inline const_iterator begin() const { return {*this}; }
typedef type_value_pair const* const_iterator;
inline const_iterator begin() const { return m_values.data(); }
inline const_iterator end() const { return begin() + m_values.size(); }
};
......
......@@ -48,6 +48,8 @@ struct abstract_tuple : ref_counted
virtual void* mutable_at(size_t pos) = 0;
// accessors
virtual const_iterator begin() const = 0;
virtual const_iterator end() const = 0;
virtual size_t size() const = 0;
virtual abstract_tuple* copy() const = 0;
virtual void const* at(size_t pos) const = 0;
......
......@@ -51,30 +51,42 @@ template<typename... ElementTypes>
class decorated_tuple : public abstract_tuple
{
static_assert(sizeof...(ElementTypes) > 0,
"decorated_tuple is not allowed to be empty");
public:
typedef util::fixed_vector<size_t, sizeof...(ElementTypes)> vector_type;
typedef cow_ptr<abstract_tuple> ptr_type;
decorated_tuple(ptr_type&& d, vector_type const& v)
: m_decorated(std::move(d)), m_mappings(v)
using abstract_tuple::const_iterator;
decorated_tuple(ptr_type&& d, vector_type const& v) : m_decorated(std::move(d))
{
CPPA_REQUIRE(v.size() == sizeof...(ElementTypes));
CPPA_REQUIRE(std::max_element(v.begin(), v.end()) < m_decorated->size());
init(v);
}
decorated_tuple(ptr_type const& d, vector_type const& v)
: m_decorated(d), m_mappings(v)
decorated_tuple(ptr_type const& d, vector_type const& v) : m_decorated(d)
{
CPPA_REQUIRE(v.size() == sizeof...(ElementTypes));
CPPA_REQUIRE(v.empty() || *(std::max_element(v.begin(), v.end())) < m_decorated->size());
init(v);
}
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)
{
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
......@@ -90,18 +102,13 @@ class decorated_tuple : public abstract_tuple
virtual void const* at(size_t pos) const
{
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
{
CPPA_REQUIRE(pos < size());
return m_decorated->type_at(m_mappings[pos]);
}
virtual bool equals(abstract_tuple const&) const
{
return false;
return m_data[pos].first;
}
virtual std::type_info const& impl_type() const
......@@ -109,17 +116,29 @@ class decorated_tuple : public abstract_tuple
return typeid(decorated_tuple);
}
private:
ptr_type m_decorated;
vector_type m_mappings;
type_value_pair m_data[sizeof...(ElementTypes)];
decorated_tuple(decorated_tuple const& other)
: abstract_tuple()
, 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;
......
......@@ -35,9 +35,13 @@
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;
void* mutable_at(size_t);
abstract_tuple* copy() const;
......
This diff is collapsed.
......@@ -34,32 +34,37 @@
#include <vector>
#include "cppa/object.hpp"
#include "cppa/type_value_pair.hpp"
#include "cppa/detail/abstract_tuple.hpp"
namespace cppa { namespace detail {
class object_array : public detail::abstract_tuple
class object_array : public abstract_tuple
{
std::vector<object> m_elements;
std::vector<type_value_pair> m_data;
public:
using abstract_tuple::const_iterator;
object_array();
object_array(object_array&& other);
object_array(object_array const& other);
/**
* @pre
*/
void push_back(object&& what);
void push_back(object const& what);
void* mutable_at(size_t pos);
const_iterator begin() const;
const_iterator end() const;
size_t size() const;
abstract_tuple* copy() const;
......
......@@ -33,6 +33,8 @@
#include <stdexcept>
#include "cppa/type_value_pair.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/detail/tdata.hpp"
......@@ -46,6 +48,9 @@ template<typename... ElementTypes>
class tuple_vals : public abstract_tuple
{
static_assert(sizeof...(ElementTypes) > 0,
"tuple_vals is not allowed to be empty");
typedef abstract_tuple super;
typedef tdata<ElementTypes...> data_type;
......@@ -56,33 +61,45 @@ class tuple_vals : public abstract_tuple
static types_array<ElementTypes...> m_types;
template<typename... Types>
void* tdata_mutable_at(tdata<Types...>& d, size_t pos)
{
return (pos == 0) ? &(d.head) : tdata_mutable_at(d.tail(), pos - 1);
}
type_value_pair m_view[sizeof...(ElementTypes)];
template<typename... Types>
void const* tdata_at(tdata<Types...> const& d, size_t pos) const
void init_view()
{
for (size_t i = 0; i < sizeof...(ElementTypes); ++i)
{
return (pos == 0) ? &(d.head) : tdata_at(d.tail(), pos - 1);
m_view[i].first = m_types[i];
m_view[i].second = m_data.at(i);
}
}
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
......@@ -97,11 +114,20 @@ class tuple_vals : public abstract_tuple
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
{
CPPA_REQUIRE(pos < size());
return m_types[pos];
}
......
......@@ -73,6 +73,8 @@ class tuple
"illegal types in tuple definition: "
"pointers and references are prohibited");
friend class any_tuple;
typedef detail::tuple_vals<ElementTypes...> data_type;
cow_ptr<detail::abstract_tuple> m_vals;
......@@ -137,7 +139,6 @@ class tuple
/**
* @brief Gets the size of this tuple.
* @returns <tt>sizeof...(ElementTypes)</tt>.
*/
inline size_t size() const
{
......@@ -145,14 +146,16 @@ class tuple
}
/**
* @brief Gets a pointer to the internal data.
* @returns A const void pointer to the <tt>N</tt>th element.
* @brief Gets a const pointer to the element at position @p p.
*/
inline void const* at(size_t p) const
{
return m_vals->at(p);
}
/**
* @brief Gets a mutable pointer to the element at position @p p.
*/
inline void* mutable_at(size_t p)
{
return m_vals->mutable_at(p);
......@@ -160,26 +163,17 @@ class tuple
/**
* @brief Gets {@link uniform_type_info uniform type information}
* of an element.
* @returns The uniform type of the <tt>N</tt>th element.
* of the element at position @p p.
*/
inline uniform_type_info const* type_at(size_t p) const
{
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
{
return m_vals;
}
# endif
};
......
......@@ -70,24 +70,24 @@ class tuple_view
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;
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);
}
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)
{
tuple_view result;
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);
}
......
......@@ -34,6 +34,8 @@
#include <algorithm>
#include <stdexcept>
#include "cppa/config.hpp"
namespace cppa { namespace util {
// @warning does not perform any bound checks
......@@ -62,7 +64,22 @@ class fixed_vector
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
......@@ -117,12 +134,12 @@ class fixed_vector
inline iterator end()
{
return (static_cast<T*>(m_data) + m_size);
return (static_cast<iterator>(m_data) + m_size);
}
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>
......
......@@ -67,14 +67,14 @@ OUTPUT_LANGUAGE = English
# the file and class documentation (similar to JavaDoc).
# 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
# 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
# brief descriptions will be completely suppressed.
REPEAT_BRIEF = YES
REPEAT_BRIEF = NO
# This tag implements a quasi-intelligent brief description abbreviator
# that is used to form the text in various listings. Each string
......
......@@ -33,6 +33,16 @@
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
{
return 0;
......
......@@ -49,11 +49,15 @@ object_array::object_array(object_array const& other)
void object_array::push_back(object const& 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)
{
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)
......@@ -76,6 +80,16 @@ void const* object_array::at(size_t pos) const
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
{
if (size() == ut.size())
......
......@@ -69,6 +69,7 @@ size_t test__pattern()
pattern<int, anything, int> i3;
any_tuple i3_any_tup = make_tuple(1, 2, 3);
/*
auto opt = tuple_cast(i3_any_tup, i3);
CPPA_CHECK(opt.valid());
if (opt.valid())
......@@ -76,6 +77,7 @@ size_t test__pattern()
CPPA_CHECK_EQUAL(get<0>(*opt), 1);
CPPA_CHECK_EQUAL(get<1>(*opt), 3);
}
*/
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