Commit d0c322ae authored by neverlord's avatar neverlord

binary_deserializer

parent 65a71be9
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
</data> </data>
<data> <data>
<variable>ProjectExplorer.Project.Updater.EnvironmentId</variable> <variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
<value type="QString">{07fcd197-092d-45a0-8500-3be614e6ae31}</value> <value type="QString">{23902c37-f07e-47cd-bb19-c366b9f708db}</value>
</data> </data>
<data> <data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable> <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
......
...@@ -140,3 +140,6 @@ cppa/util/rm_ref.hpp ...@@ -140,3 +140,6 @@ cppa/util/rm_ref.hpp
cppa/util/is_iterable.hpp cppa/util/is_iterable.hpp
cppa/binary_serializer.hpp cppa/binary_serializer.hpp
src/binary_serializer.cpp src/binary_serializer.cpp
cppa/binary_deserializer.hpp
src/binary_deserializer.cpp
src/actor.cpp
#ifndef ACTOR_HPP #ifndef ACTOR_HPP
#define ACTOR_HPP #define ACTOR_HPP
#include <cstdint>
#include "cppa/group.hpp" #include "cppa/group.hpp"
#include "cppa/channel.hpp" #include "cppa/channel.hpp"
...@@ -12,15 +14,28 @@ class deserializer; ...@@ -12,15 +14,28 @@ class deserializer;
class actor : public channel class actor : public channel
{ {
std::uint32_t m_id;
protected:
actor();
public: public:
virtual void join(group_ptr& what) = 0; virtual void join(group_ptr& what) = 0;
virtual void leave(const group_ptr& what) = 0; virtual void leave(const group_ptr& what) = 0;
virtual void link(intrusive_ptr<actor>& other) = 0; virtual void link(intrusive_ptr<actor>& other) = 0;
virtual void unlink(intrusive_ptr<actor>& other) = 0; virtual void unlink(intrusive_ptr<actor>& other) = 0;
virtual bool remove_backlink(const intrusive_ptr<actor>& to) = 0;
virtual bool establish_backlink(const intrusive_ptr<actor>& to) = 0;
inline std::uint32_t id() const { return m_id; }
virtual bool remove_backlink(const intrusive_ptr<actor>& to) = 0; /**
virtual bool establish_backlink(const intrusive_ptr<actor>& to) = 0; * @brief
*/
static intrusive_ptr<actor> by_id(std::uint32_t actor_id);
}; };
......
#ifndef BINARY_DESERIALIZER_HPP
#define BINARY_DESERIALIZER_HPP
#include "cppa/deserializer.hpp"
namespace cppa {
class binary_deserializer : public deserializer
{
const char* pos;
const char* end;
void range_check(size_t read_size);
public:
binary_deserializer(const char* buf, size_t buf_size);
binary_deserializer(const char* begin, const char* end);
std::string seek_object();
std::string peek_object();
void begin_object(const std::string& type_name);
void end_object();
size_t begin_sequence();
void end_sequence();
primitive_variant read_value(primitive_type ptype);
void read_tuple(size_t size,
const primitive_type* ptypes,
primitive_variant* storage);
};
} // namespace cppa
#endif // BINARY_DESERIALIZER_HPP
...@@ -79,16 +79,16 @@ struct has_default_uniform_type_info_impl ...@@ -79,16 +79,16 @@ struct has_default_uniform_type_info_impl
|| is_stl_compliant_list<T>::value; || is_stl_compliant_list<T>::value;
}; };
template<typename Struct> template<typename T>
class default_uniform_type_info_impl : public util::uniform_type_info_base<Struct> class default_uniform_type_info_impl : public util::uniform_type_info_base<T>
{ {
template<typename T> template<typename X>
struct is_invalid struct is_invalid
{ {
static const bool value = !util::is_primitive<T>::value static const bool value = !util::is_primitive<X>::value
&& !is_stl_compliant_map<T>::value && !is_stl_compliant_map<X>::value
&& !is_stl_compliant_list<T>::value; && !is_stl_compliant_list<X>::value;
}; };
class member class member
...@@ -124,8 +124,8 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<Struc ...@@ -124,8 +124,8 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<Struc
public: public:
template<typename T, class C> template<typename R, class C>
member(uniform_type_info* mtptr, T C::*mem_ptr) : m_meta(mtptr) member(uniform_type_info* mtptr, R C::*mem_ptr) : m_meta(mtptr)
{ {
m_serialize = [mem_ptr] (const uniform_type_info* mt, m_serialize = [mem_ptr] (const uniform_type_info* mt,
const void* obj, const void* obj,
...@@ -193,70 +193,70 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<Struc ...@@ -193,70 +193,70 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<Struc
// pr.first = member pointer // pr.first = member pointer
// pr.second = meta object to handle pr.first // pr.second = meta object to handle pr.first
template<typename T, class C, typename... Args> template<typename R, class C, typename... Args>
void push_back(std::pair<T C::*, util::uniform_type_info_base<T>*> pr, void push_back(std::pair<R C::*, util::uniform_type_info_base<R>*> pr,
const Args&... args) const Args&... args)
{ {
m_members.push_back({ pr.second, pr.first }); m_members.push_back({ pr.second, pr.first });
push_back(args...); push_back(args...);
} }
template<class C, typename T, typename... Args> template<typename R, class C, typename... Args>
typename util::enable_if<util::is_primitive<T> >::type typename util::enable_if<util::is_primitive<R> >::type
push_back(T C::*mem_ptr, const Args&... args) push_back(R C::*mem_ptr, const Args&... args)
{ {
m_members.push_back({ new primitive_member<T>(), mem_ptr }); m_members.push_back({ new primitive_member<R>(), mem_ptr });
push_back(args...); push_back(args...);
} }
template<class C, typename T, typename... Args> template< typename R, class C,typename... Args>
typename util::enable_if<is_stl_compliant_list<T> >::type typename util::enable_if<is_stl_compliant_list<R> >::type
push_back(T C::*mem_ptr, const Args&... args) push_back(R C::*mem_ptr, const Args&... args)
{ {
m_members.push_back({ new list_member<T>(), mem_ptr }); m_members.push_back({ new list_member<R>(), mem_ptr });
push_back(args...); push_back(args...);
} }
template<class C, typename T, typename... Args> template<typename R, class C, typename... Args>
typename util::enable_if<is_stl_compliant_map<T> >::type typename util::enable_if<is_stl_compliant_map<R> >::type
push_back(T C::*mem_ptr, const Args&... args) push_back(R C::*mem_ptr, const Args&... args)
{ {
m_members.push_back({ new map_member<T>(), mem_ptr }); m_members.push_back({ new map_member<R>(), mem_ptr });
push_back(args...); push_back(args...);
} }
template<class C, typename T, typename... Args> template<typename R, class C, typename... Args>
typename util::enable_if<is_invalid<T>>::type typename util::enable_if<is_invalid<R>>::type
push_back(T C::*mem_ptr, const Args&... args) push_back(R C::*mem_ptr, const Args&... args)
{ {
static_assert(util::is_primitive<T>::value, static_assert(util::is_primitive<R>::value,
"T is neither a primitive type nor a " "T is neither a primitive type nor a "
"stl-compliant list/map"); "stl-compliant list/map");
} }
template<typename T> template<class C>
void init_(typename void init_(typename
util::enable_if< util::enable_if<
util::disjunction<std::is_same<T,util::void_type>, util::disjunction<std::is_same<C, util::void_type>,
std::is_same<T,any_type>>>::type* = 0) std::is_same<C, any_type>>>::type* = 0)
{ {
// any_type doesn't have any fields (no serialization required) // any_type doesn't have any fields (no serialization required)
} }
template<typename T> template<typename P>
void init_(typename util::enable_if<util::is_primitive<T>>::type* = 0) void init_(typename util::enable_if<util::is_primitive<P>>::type* = 0)
{ {
m_members.push_back(member::fake_member(new primitive_member<T>())); m_members.push_back(member::fake_member(new primitive_member<P>()));
} }
template<typename T> template<typename X>
void init_(typename void init_(typename
util::disable_if< util::disable_if<
util::disjunction<util::is_primitive<T>, util::disjunction<util::is_primitive<X>,
std::is_same<T,util::void_type>, std::is_same<X, util::void_type>,
std::is_same<T,any_type>>>::type* = 0) std::is_same<X, any_type>>>::type* = 0)
{ {
static_assert(util::is_primitive<T>::value, static_assert(util::is_primitive<X>::value,
"T is neither a primitive type nor a " "T is neither a primitive type nor a "
"stl-compliant list/map"); "stl-compliant list/map");
} }
...@@ -271,7 +271,7 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<Struc ...@@ -271,7 +271,7 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<Struc
default_uniform_type_info_impl() default_uniform_type_info_impl()
{ {
init_<Struct>(); init_<T>();
} }
void serialize(const void* obj, serializer* s) const void serialize(const void* obj, serializer* s) const
......
...@@ -67,6 +67,7 @@ public: ...@@ -67,6 +67,7 @@ public:
* @post {@code other.type() == nullptr} * @post {@code other.type() == nullptr}
*/ */
object& operator=(object&& other); object& operator=(object&& other);
object& operator=(const object& other); object& operator=(const object& other);
bool equal(const object& other) const; bool equal(const object& other) const;
...@@ -97,79 +98,38 @@ inline void assert_type(const object& obj, const std::type_info& tinfo) ...@@ -97,79 +98,38 @@ inline void assert_type(const object& obj, const std::type_info& tinfo)
} }
} }
// get a const reference
template<typename T>
struct object_caster<const T&>
{
static const T& _(const object& obj)
{
assert_type(obj, typeid(T));
return *reinterpret_cast<const T*>(obj.m_value);
}
};
// get a mutable reference
template<typename T> template<typename T>
struct object_caster<T&> struct object_caster
{ {
static T& _(object& obj) static T& _(object& obj)
{ {
assert_type(obj, typeid(T)); assert_type(obj, typeid(T));
return *reinterpret_cast<T*>(obj.m_value); return *reinterpret_cast<T*>(obj.m_value);
} }
}; static const T& _(const object& obj)
// get a const pointer
template<typename T>
struct object_caster<const T*>
{
static const T* _(const object& obj)
{
assert_type(obj, typeid(T));
return reinterpret_cast<const T*>(obj.m_value);
}
};
// get a mutable pointer
template<typename T>
struct object_caster<T*>
{
static T* _(object& obj)
{ {
assert_type(obj, typeid(T)); assert_type(obj, typeid(T));
return reinterpret_cast<T*>(obj.m_value); return *reinterpret_cast<const T*>(obj.m_value);
} }
}; };
template<typename T> } // namespace detail
struct is_const_reference : std::false_type { };
template<typename T>
struct is_const_reference<const T&> : std::true_type { };
template<typename T> template<typename T>
struct is_const_pointer : std::false_type { }; T& get(object& obj)
template<typename T>
struct is_const_pointer<const T*> : std::true_type { };
}
template<typename T>
T object_cast(object& obj)
{ {
static_assert(util::disjunction<std::is_pointer<T>, static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value, std::is_reference<T>>::value == false,
"T is neither a reference nor a pointer type."); "T is a reference or a pointer type.");
return detail::object_caster<T>::_(obj); return detail::object_caster<T>::_(obj);
} }
template<typename T> template<typename T>
const T& object_cast(const object& obj) const T& get(const object& obj)
{ {
static_assert(util::disjunction<detail::is_const_pointer<T>, static_assert(util::disjunction<std::is_pointer<T>,
detail::is_const_reference<T>>::value, std::is_reference<T>>::value,
"T is neither a const reference nor a const pointer type."); "T is a reference a pointer type.");
return detail::object_caster<T>::_(obj); return detail::object_caster<T>::_(obj);
} }
......
...@@ -21,17 +21,21 @@ ...@@ -21,17 +21,21 @@
namespace cppa { namespace cppa {
class uniform_type_info;
const uniform_type_info* uniform_typeid(const std::type_info&);
/** /**
* @brief Provides a platform independent type name and (very primitive) * @brief Provides a platform independent type name and a (very primitive)
* reflection in combination with {@link cppa::object object}. * kind of reflection in combination with {@link cppa::object object}.
* *
* The platform dependent type name (from GCC or Microsofts VC++ Compiler) is * The platform dependent type name (from GCC or Microsofts VC++ Compiler) is
* translated to a (usually) shorter and platform independent name. * translated to a (usually) shorter and platform independent name.
* *
* This name is usually equal to the "in-sourcecode-name", * This name is equal to the "in-sourcecode-name" but with a few exceptions:
* with a few exceptions:
* - @c std::string is named @c \@str * - @c std::string is named @c \@str
* - @c std::wstring is named @c \@wstr * - @c std::u16string is named @c \@u16str
* - @c std::u32string is named @c \@u32str
* - @c integers are named <tt>\@(i|u)$size</tt>\n * - @c integers are named <tt>\@(i|u)$size</tt>\n
* e.g.: @c \@i32 is a 32 bit signed integer; @c \@u16 * e.g.: @c \@i32 is a 32 bit signed integer; @c \@u16
* is a 16 bit unsigned integer * is a 16 bit unsigned integer
...@@ -46,10 +50,7 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info> ...@@ -46,10 +50,7 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
friend class object; friend class object;
// needs access to by_type_info() // needs access to by_type_info()
template<typename T> friend const uniform_type_info* uniform_typeid(const std::type_info&);
friend uniform_type_info* uniform_typeid();
friend uniform_type_info* uniform_typeid(const std::type_info&);
public: public:
...@@ -94,11 +95,11 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info> ...@@ -94,11 +95,11 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
uniform_type_info& operator=(uniform_type_info&&) = delete; uniform_type_info& operator=(uniform_type_info&&) = delete;
uniform_type_info& operator=(const uniform_type_info&) = delete; uniform_type_info& operator=(const uniform_type_info&) = delete;
static uniform_type_info* by_type_info(const std::type_info& tinfo); static const uniform_type_info* by_type_info(const std::type_info& tinfo);
protected: protected:
explicit uniform_type_info(const std::string& uniform_name); uniform_type_info(const std::string& uniform_name);
public: public:
...@@ -134,6 +135,7 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info> ...@@ -134,6 +135,7 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
{ {
return id().compare(other.id()); return id().compare(other.id());
} }
/** /**
* @brief Add a new type mapping to the libCPPA internal type system. * @brief Add a new type mapping to the libCPPA internal type system.
* @return <code>true</code> if @p uniform_type was added as known * @return <code>true</code> if @p uniform_type was added as known
...@@ -158,11 +160,14 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info> ...@@ -158,11 +160,14 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
// const ToStringFun& ts, const FromStringFun& fs); // const ToStringFun& ts, const FromStringFun& fs);
/** /**
* @brief Create an object of this type. * @brief Creates an object of this type.
*/ */
object create() const; object create() const;
object deserialize(deserializer* from) const; /**
* @brief Deserializes an object of this type from @p source.
*/
object deserialize(deserializer* source) const;
protected: protected:
...@@ -203,12 +208,10 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info> ...@@ -203,12 +208,10 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
}; };
uniform_type_info* uniform_typeid(const std::type_info& tinfo);
template<typename T> template<typename T>
uniform_type_info* uniform_typeid() inline const uniform_type_info* uniform_typeid()
{ {
return uniform_type_info::by_type_info(typeid(T)); return uniform_typeid(typeid(T));
} }
bool operator==(const uniform_type_info& lhs, const std::type_info& rhs); bool operator==(const uniform_type_info& lhs, const std::type_info& rhs);
......
...@@ -12,7 +12,7 @@ namespace cppa { ...@@ -12,7 +12,7 @@ namespace cppa {
// forward declarations // forward declarations
class uniform_type_info; class uniform_type_info;
uniform_type_info* uniform_typeid(const std::type_info& tinfo); const uniform_type_info* uniform_typeid(const std::type_info&);
} // namespace cppa } // namespace cppa
...@@ -23,65 +23,65 @@ template<typename... Types> struct type_list; ...@@ -23,65 +23,65 @@ template<typename... Types> struct type_list;
template<> template<>
struct type_list<> struct type_list<>
{ {
typedef void_type head_type; typedef void_type head_type;
typedef type_list<> tail_type; typedef type_list<> tail_type;
static const std::size_t type_list_size = 0; static const std::size_t type_list_size = 0;
}; };
template<typename Head, typename... Tail> template<typename Head, typename... Tail>
struct type_list<Head, Tail...> : abstract_type_list struct type_list<Head, Tail...> : abstract_type_list
{ {
typedef Head head_type; typedef Head head_type;
typedef type_list<Tail...> tail_type; typedef type_list<Tail...> tail_type;
static const std::size_t type_list_size = tail_type::type_list_size + 1; static const std::size_t type_list_size = tail_type::type_list_size + 1;
type_list() { init<type_list>(m_arr); } type_list() { init<type_list>(m_arr); }
virtual const_iterator begin() const virtual const_iterator begin() const
{ {
return m_arr; return m_arr;
} }
virtual const_iterator end() const virtual const_iterator end() const
{ {
return m_arr + type_list_size; return m_arr + type_list_size;
} }
virtual const uniform_type_info* at(std::size_t pos) const virtual const uniform_type_info* at(std::size_t pos) const
{ {
return m_arr[pos]; return m_arr[pos];
} }
virtual type_list* copy() const virtual type_list* copy() const
{ {
return new type_list; return new type_list;
} }
template<typename TypeList> template<typename TypeList>
static void init(const uniform_type_info** what) static void init(const uniform_type_info** what)
{ {
what[0] = uniform_typeid(typeid(typename TypeList::head_type)); what[0] = uniform_typeid(typeid(typename TypeList::head_type));
if (TypeList::type_list_size > 1) if (TypeList::type_list_size > 1)
{ {
++what; ++what;
init<typename TypeList::tail_type>(what); init<typename TypeList::tail_type>(what);
} }
/* /*
what[0] = &uniform_type_info<typename TypeList::head_type>(); what[0] = &uniform_type_info<typename TypeList::head_type>();
if (TypeList::type_list_size > 1) if (TypeList::type_list_size > 1)
{ {
++what; ++what;
init<typename TypeList::tail_type>(what); init<typename TypeList::tail_type>(what);
} }
*/ */
} }
private: private:
const uniform_type_info* m_arr[type_list_size]; const uniform_type_info* m_arr[type_list_size];
}; };
......
...@@ -6,6 +6,9 @@ INCLUDES = -I./ ...@@ -6,6 +6,9 @@ INCLUDES = -I./
HEADERS = cppa/actor.hpp \ HEADERS = cppa/actor.hpp \
cppa/any_type.hpp \ cppa/any_type.hpp \
cppa/binary_deserializer.hpp \
cppa/binary_serializer.hpp \
cppa/channel.hpp \
cppa/config.hpp \ cppa/config.hpp \
cppa/context.hpp \ cppa/context.hpp \
cppa/cow_ptr.hpp \ cppa/cow_ptr.hpp \
...@@ -65,7 +68,9 @@ HEADERS = cppa/actor.hpp \ ...@@ -65,7 +68,9 @@ HEADERS = cppa/actor.hpp \
cppa/util/type_list_pop_back.hpp \ cppa/util/type_list_pop_back.hpp \
cppa/util/void_type.hpp cppa/util/void_type.hpp
SOURCES = src/actor_behavior.cpp \ SOURCES = src/actor.cpp \
src/actor_behavior.cpp \
src/binary_deserializer.cpp \
src/binary_serializer.cpp \ src/binary_serializer.cpp \
src/blocking_message_queue.cpp \ src/blocking_message_queue.cpp \
src/channel.cpp \ src/channel.cpp \
......
#include "cppa/actor.hpp"
namespace cppa {
actor::actor() : m_id(0)
{
}
intrusive_ptr<actor> actor::by_id(std::uint32_t)
{
return nullptr;
}
} // namespace cppa
#include <cstdint>
#include <cstring>
#include <iterator>
#include <exception>
#include <stdexcept>
#include <type_traits>
#include "cppa/util/enable_if.hpp"
#include "cppa/binary_deserializer.hpp"
using cppa::util::enable_if;
namespace cppa {
namespace {
typedef const char* iterator;
inline void range_check(iterator begin, iterator end, size_t read_size)
{
if ((begin + read_size) > end)
{
throw std::out_of_range("binary_deserializer::read()");
}
}
// @return the next iterator position
template<typename T>
iterator read(iterator, iterator, T&,
typename enable_if< std::is_floating_point<T> >::type* = 0)
{
throw std::logic_error("read floating point not implemented yet");
}
template<typename T>
iterator read(iterator begin, iterator end, T& storage,
typename enable_if< std::is_integral<T> >::type* = 0)
{
range_check(begin, end, sizeof(T));
memcpy(&storage, begin, sizeof(T));
return begin + sizeof(T);
}
iterator read(iterator begin, iterator end, std::string& storage)
{
std::uint32_t str_size;
begin = read(begin, end, str_size);
range_check(begin, end, str_size);
storage.clear();
storage.reserve(str_size);
iterator cpy_end = begin + str_size;
std::copy(begin, cpy_end, std::back_inserter(storage));
return begin + str_size;
}
template<typename CharType, typename StringType>
iterator read_unicode_string(iterator begin, iterator end, StringType& str)
{
std::uint32_t str_size;
begin = read(begin, end, str_size);
str.reserve(str_size);
for (size_t i = 0; i < str_size; ++i)
{
CharType c;
begin = read(begin, end, c);
str += static_cast<typename StringType::value_type>(c);
}
return begin;
}
iterator read(iterator begin, iterator end, std::u16string& storage)
{
// char16_t is guaranteed to has *at least* 16 bytes,
// but not to have *exactly* 16 bytes; thus use uint16_t
return read_unicode_string<std::uint16_t>(begin, end, storage);
}
iterator read(iterator begin, iterator end, std::u32string& storage)
{
// char32_t is guaranteed to has *at least* 32 bytes,
// but not to have *exactly* 32 bytes; thus use uint32_t
return read_unicode_string<std::uint32_t>(begin, end, storage);
}
struct pt_reader
{
iterator begin;
iterator end;
pt_reader(iterator bbegin, iterator bend) : begin(bbegin), end(bend) { }
template<typename T>
inline void operator()(T& value)
{
begin = read(begin, end, value);
}
};
} // namespace <anonmyous>
binary_deserializer::binary_deserializer(const char* buf, size_t buf_size)
: pos(buf), end(buf + buf_size)
{
}
binary_deserializer::binary_deserializer(const char* bbegin, const char* bend)
: pos(bbegin), end(bend)
{
}
std::string binary_deserializer::seek_object()
{
std::string result;
pos = read(pos, end, result);
return result;
}
std::string binary_deserializer::peek_object()
{
std::string result;
read(pos, end, result);
return result;
}
void binary_deserializer::begin_object(const std::string&)
{
}
void binary_deserializer::end_object()
{
}
size_t binary_deserializer::begin_sequence()
{
static_assert(sizeof(size_t) >= sizeof(std::uint32_t),
"sizeof(size_t) < sizeof(uint32_t)");
std::uint32_t result;
pos = read(pos, end, result);
return static_cast<size_t>(result);
}
void binary_deserializer::end_sequence()
{
}
primitive_variant binary_deserializer::read_value(primitive_type ptype)
{
primitive_variant val(ptype);
pt_reader ptr(pos, end);
val.apply(ptr);
pos = ptr.begin;
return val;
}
void binary_deserializer::read_tuple(size_t size,
const primitive_type* ptypes,
primitive_variant* storage)
{
for (auto end = ptypes + size; ptypes != end; ++ptypes)
{
*storage = std::move(read_value(*ptypes));
++storage;
}
}
} // namespace cppa
...@@ -52,9 +52,11 @@ class binary_writer ...@@ -52,9 +52,11 @@ class binary_writer
} }
template<typename T> template<typename T>
void operator()(const T& value, void operator()(const T&,
typename enable_if< std::is_floating_point<T> >::type* = 0) typename enable_if< std::is_floating_point<T> >::type* = 0)
{ {
throw std::logic_error("binary_serializer::write_floating_point "
"not implemented yet");
} }
void operator()(const std::string& str) void operator()(const std::string& str)
......
...@@ -47,6 +47,12 @@ inline const char* raw_name(const std::type_info& tinfo) ...@@ -47,6 +47,12 @@ inline const char* raw_name(const std::type_info& tinfo)
#endif #endif
} }
template<typename T>
struct is_signed : std::integral_constant<bool,
std::numeric_limits<T>::is_signed>
{
};
template<typename T> template<typename T>
inline const char* raw_name() inline const char* raw_name()
{ {
...@@ -72,13 +78,13 @@ void push(std::map<int, std::pair<string_set, string_set>>& ints, ...@@ -72,13 +78,13 @@ void push(std::map<int, std::pair<string_set, string_set>>& ints,
template<typename Int> template<typename Int>
void push(std::map<int, std::pair<string_set, string_set>>& ints) void push(std::map<int, std::pair<string_set, string_set>>& ints)
{ {
push<Int>(ints, std::integral_constant<bool, std::numeric_limits<Int>::is_signed>()); push<Int>(ints, is_signed<Int>());
} }
template<typename Int0, typename Int1, typename... Ints> template<typename Int0, typename Int1, typename... Ints>
void push(std::map<int, std::pair<string_set, string_set>>& ints) void push(std::map<int, std::pair<string_set, string_set>>& ints)
{ {
push<Int0>(ints, std::integral_constant<bool, std::numeric_limits<Int0>::is_signed>()); push<Int0>(ints, is_signed<Int0>());
push<Int1, Ints...>(ints); push<Int1, Ints...>(ints);
} }
...@@ -86,6 +92,33 @@ void push(std::map<int, std::pair<string_set, string_set>>& ints) ...@@ -86,6 +92,33 @@ void push(std::map<int, std::pair<string_set, string_set>>& ints)
namespace cppa { namespace detail { namespace { namespace cppa { namespace detail { namespace {
class actor_ptr_type_info_impl : public util::uniform_type_info_base<actor_ptr>
{
protected:
void serialize(const void* ptr, serializer* sink) const
{
sink->begin_object(name());
sink->write_value((*reinterpret_cast<const actor_ptr*>(ptr))->id());
sink->end_object();
}
void deserialize(void* ptr, deserializer* source) const
{
std::string cname = source->seek_object();
if (cname != name())
{
throw std::logic_error("wrong type name found");
}
source->begin_object(cname);
auto id = get<std::uint32_t>(source->read_value(pt_uint32));
*reinterpret_cast<actor_ptr*>(ptr) = actor::by_id(id);
source->end_object();
}
};
class uniform_type_info_map class uniform_type_info_map
{ {
...@@ -127,8 +160,9 @@ class uniform_type_info_map ...@@ -127,8 +160,9 @@ class uniform_type_info_map
uniform_type_info_map() uniform_type_info_map()
{ {
insert<std::string>(); insert<std::string>();
//insert<wstring_obj>({std::string(raw_name<std::wstring>())}); insert<std::u16string>();
//insert(new wstring_utype, { std::string(raw_name<std::wstring>()) }); insert<std::u32string>();
insert(new actor_ptr_type_info_impl, { raw_name<actor_ptr>() });
insert<float>(); insert<float>();
insert<cppa::util::void_type>(); insert<cppa::util::void_type>();
if (sizeof(double) == sizeof(long double)) if (sizeof(double) == sizeof(long double))
...@@ -213,7 +247,9 @@ class uniform_type_info_map ...@@ -213,7 +247,9 @@ class uniform_type_info_map
{ {
if (!m_by_rname.insert(std::make_pair(plain_name, what)).second) if (!m_by_rname.insert(std::make_pair(plain_name, what)).second)
{ {
throw std::runtime_error(plain_name + " already mapped to an uniform_type_info"); std::string error_str = plain_name;
error_str += " already mapped to an uniform_type_info";
throw std::runtime_error(error_str);
} }
} }
return true; return true;
...@@ -260,7 +296,13 @@ uniform_type_info::~uniform_type_info() ...@@ -260,7 +296,13 @@ uniform_type_info::~uniform_type_info()
{ {
} }
uniform_type_info* uniform_type_info::by_type_info(const std::type_info& tinf) object uniform_type_info::create() const
{
return { new_instance(), this };
}
const uniform_type_info*
uniform_type_info::by_type_info(const std::type_info& tinf)
{ {
auto result = detail::s_uniform_type_info_map().by_raw_name(raw_name(tinf)); auto result = detail::s_uniform_type_info_map().by_raw_name(raw_name(tinf));
if (!result) if (!result)
...@@ -281,20 +323,6 @@ uniform_type_info* uniform_type_info::by_uniform_name(const std::string& name) ...@@ -281,20 +323,6 @@ uniform_type_info* uniform_type_info::by_uniform_name(const std::string& name)
return result; return result;
} }
/*
bool uniform_type_info::announce(const std::type_info& plain_type,
uniform_type_info* uniform_type)
{
string_set tmp = { std::string(raw_name(plain_type)) };
if (!detail::s_uniform_type_info_map().insert(tmp, uniform_type))
{
delete uniform_type;
return false;
}
return true;
}
*/
object uniform_type_info::deserialize(deserializer* from) const object uniform_type_info::deserialize(deserializer* from) const
{ {
auto ptr = new_instance(); auto ptr = new_instance();
...@@ -307,7 +335,7 @@ std::vector<uniform_type_info*> uniform_type_info::instances() ...@@ -307,7 +335,7 @@ std::vector<uniform_type_info*> uniform_type_info::instances()
return detail::s_uniform_type_info_map().get_all(); return detail::s_uniform_type_info_map().get_all();
} }
uniform_type_info* uniform_typeid(const std::type_info& tinfo) const uniform_type_info* uniform_typeid(const std::type_info& tinfo)
{ {
return uniform_type_info::by_type_info(tinfo); return uniform_type_info::by_type_info(tinfo);
} }
......
...@@ -55,7 +55,7 @@ int main(int argc, char** c_argv) ...@@ -55,7 +55,7 @@ int main(int argc, char** c_argv)
std::cout << std::boolalpha; std::cout << std::boolalpha;
std::size_t errors = 0; std::size_t errors = 0;
RUN_TEST(test__primitive_variant); RUN_TEST(test__primitive_variant);
// RUN_TEST(test__uniform_type); RUN_TEST(test__uniform_type);
RUN_TEST(test__intrusive_ptr); RUN_TEST(test__intrusive_ptr);
RUN_TEST(test__a_matches_b); RUN_TEST(test__a_matches_b);
RUN_TEST(test__type_list); RUN_TEST(test__type_list);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "cppa/primitive_type.hpp" #include "cppa/primitive_type.hpp"
#include "cppa/primitive_variant.hpp" #include "cppa/primitive_variant.hpp"
#include "cppa/binary_serializer.hpp" #include "cppa/binary_serializer.hpp"
#include "cppa/binary_deserializer.hpp"
#include "cppa/util/apply.hpp" #include "cppa/util/apply.hpp"
#include "cppa/util/pt_token.hpp" #include "cppa/util/pt_token.hpp"
...@@ -192,229 +193,6 @@ class string_serializer : public serializer ...@@ -192,229 +193,6 @@ class string_serializer : public serializer
}; };
/*
class xml_serializer : public serializer
{
std::ostream& out;
std::string indentation;
inline void inc_indentation()
{
indentation.resize(indentation.size() + 4, ' ');
}
inline void dec_indentation()
{
auto isize = indentation.size();
indentation.resize((isize > 4) ? (isize - 4) : 0);
}
struct pt_writer
{
std::ostream& out;
const std::string& indentation;
pt_writer(std::ostream& ostr, const std::string& indent)
: out(ostr), indentation(indent)
{
}
template<typename T>
void operator()(const T& value)
{
out << indentation << "<value type=\""
<< primitive_type_name(type_to_ptype<T>::ptype)
<< "\">" << value << "</value>\n";
}
void operator()(const std::u16string&) { }
void operator()(const std::u32string&) { }
};
public:
xml_serializer(std::ostream& ostr) : out(ostr), indentation("") { }
void begin_object(const std::string& type_name)
{
out << indentation << "<object type=\"" << type_name << "\">\n";
inc_indentation();
}
void end_object()
{
dec_indentation();
out << indentation << "</object>\n";
}
void begin_list(size_t)
{
out << indentation << "<list>\n";
inc_indentation();
}
void end_list()
{
dec_indentation();
out << indentation << "</list>\n";
}
void write_value(const pt_value& value)
{
value.apply(pt_writer(out, indentation));
}
};
*/
class binary_deserializer : public deserializer
{
const char* m_buf;
size_t m_rd_pos;
size_t m_buf_size;
void range_check(size_t read_size)
{
if (m_rd_pos + read_size >= m_buf_size)
{
std::out_of_range("binary_deserializer::read()");
}
}
template<typename T>
void read(T& storage, bool modify_rd_pos = true)
{
range_check(sizeof(T));
memcpy(&storage, m_buf + m_rd_pos, sizeof(T));
if (modify_rd_pos) m_rd_pos += sizeof(T);
}
void read(std::string& str, bool modify_rd_pos = true)
{
std::uint32_t str_size;
read(str_size, modify_rd_pos);
const char* cpy_begin;
if (modify_rd_pos)
{
range_check(str_size);
cpy_begin = m_buf + m_rd_pos;
}
else
{
range_check(sizeof(std::uint32_t) + str_size);
cpy_begin = m_buf + m_rd_pos + sizeof(std::uint32_t);
}
str.clear();
str.reserve(str_size);
const char* cpy_end = cpy_begin + str_size;
std::copy(cpy_begin, cpy_end, std::back_inserter(str));
if (modify_rd_pos) m_rd_pos += str_size;
}
template<typename CharType, typename StringType>
void read_unicode_string(StringType& str)
{
std::uint32_t str_size;
read(str_size);
str.reserve(str_size);
for (size_t i = 0; i < str_size; ++i)
{
CharType c;
read(c);
str += static_cast<typename StringType::value_type>(c);
}
}
void read(std::u16string& str)
{
// char16_t is guaranteed to has *at least* 16 bytes,
// but not to have *exactly* 16 bytes; thus use uint16_t
read_unicode_string<std::uint16_t>(str);
}
void read(std::u32string& str)
{
// char32_t is guaranteed to has *at least* 32 bytes,
// but not to have *exactly* 32 bytes; thus use uint32_t
read_unicode_string<std::uint32_t>(str);
}
struct pt_reader
{
binary_deserializer* self;
inline pt_reader(binary_deserializer* mself) : self(mself) { }
template<typename T>
inline void operator()(T& value)
{
self->read(value);
}
};
public:
binary_deserializer(const char* buf, size_t buf_size)
: m_buf(buf), m_rd_pos(0), m_buf_size(buf_size)
{
}
std::string seek_object()
{
std::string result;
read(result);
return result;
}
std::string peek_object()
{
std::string result;
read(result, false);
return result;
}
void begin_object(const std::string&)
{
}
void end_object()
{
}
size_t begin_sequence()
{
std::uint32_t size;
read(size);
return size;
}
void end_sequence()
{
}
primitive_variant read_value(primitive_type ptype)
{
primitive_variant val(ptype);
val.apply(pt_reader(this));
return val;
}
void read_tuple(size_t size,
const primitive_type* ptypes,
primitive_variant* storage)
{
const primitive_type* end = ptypes + size;
for ( ; ptypes != end; ++ptypes)
{
*storage = std::move(read_value(*ptypes));
++storage;
}
}
};
class string_deserializer : public deserializer class string_deserializer : public deserializer
{ {
...@@ -713,6 +491,12 @@ compound_member(C Parent::*c_ptr, const Args&... args) ...@@ -713,6 +491,12 @@ compound_member(C Parent::*c_ptr, const Args&... args)
return std::make_pair(c_ptr, meta_object<C>(args...)); return std::make_pair(c_ptr, meta_object<C>(args...));
} }
template<typename T, typename... Args>
void announce(const Args&... args)
{
announce(meta_object<T>(args...));
}
std::size_t test__serialization() std::size_t test__serialization()
{ {
CPPA_TEST(test__serialization); CPPA_TEST(test__serialization);
...@@ -740,11 +524,11 @@ std::size_t test__serialization() ...@@ -740,11 +524,11 @@ std::size_t test__serialization()
// test serializers / deserializers with struct_b // test serializers / deserializers with struct_b
{ {
// get meta object for struct_b // get meta object for struct_b
announce(meta_object<struct_b>(compound_member(&struct_b::a, announce<struct_b>(compound_member(&struct_b::a,
&struct_a::x, &struct_a::x,
&struct_a::y), &struct_a::y),
&struct_b::z, &struct_b::z,
&struct_b::ints)); &struct_b::ints);
// testees // testees
struct_b b1 = { { 1, 2 }, 3, { 4, 5, 6, 7, 8, 9, 10 } }; struct_b b1 = { { 1, 2 }, 3, { 4, 5, 6, 7, 8, 9, 10 } };
struct_b b2; struct_b b2;
...@@ -764,7 +548,7 @@ std::size_t test__serialization() ...@@ -764,7 +548,7 @@ std::size_t test__serialization()
binary_deserializer bd(bs.data(), bs.size()); binary_deserializer bd(bs.data(), bs.size());
object res = root_object.deserialize(&bd); object res = root_object.deserialize(&bd);
CPPA_CHECK_EQUAL(res.type().name(), "struct_b"); CPPA_CHECK_EQUAL(res.type().name(), "struct_b");
b2 = object_cast<const struct_b&>(res); b2 = get<struct_b>(res);
} }
// cleanup // cleanup
delete buf.second; delete buf.second;
...@@ -776,33 +560,27 @@ std::size_t test__serialization() ...@@ -776,33 +560,27 @@ std::size_t test__serialization()
string_deserializer strd(b1str); string_deserializer strd(b1str);
auto res = root_object.deserialize(&strd); auto res = root_object.deserialize(&strd);
CPPA_CHECK_EQUAL(res.type().name(), "struct_b"); CPPA_CHECK_EQUAL(res.type().name(), "struct_b");
b3 = object_cast<const struct_b&>(res); b3 = get<struct_b>(res);
} }
CPPA_CHECK_EQUAL(b1, b3); CPPA_CHECK_EQUAL(b1, b3);
} }
// test serializers / deserializers with struct_c // test serializers / deserializers with struct_c
{ {
// get meta type of struct_c and "announce" // get meta type of struct_c and "announce"
announce(meta_object<struct_c>(&struct_c::strings,&struct_c::ints)); announce<struct_c>(&struct_c::strings, &struct_c::ints);
// testees // testees
struct_c c1 = { { { "abc", u"cba" }, { "x", u"y" } }, { 9, 4, 5 } }; struct_c c1 = { { { "abc", u"cba" }, { "x", u"y" } }, { 9, 4, 5 } };
struct_c c2; struct_c c2;
// binary buffer
std::pair<size_t, char*> buf;
// serialize c1 to buf
{ {
// serialize c1 to buf
binary_serializer bs; binary_serializer bs;
root_object.serialize(c1, &bs); root_object.serialize(c1, &bs);
buf = bs.take_buffer(); // serialize c2 from buf
} binary_deserializer bd(bs.data(), bs.size());
// serialize c2 from buf
{
binary_deserializer bd(buf.second, buf.first);
auto res = root_object.deserialize(&bd); auto res = root_object.deserialize(&bd);
CPPA_CHECK_EQUAL(res.type().name(), "struct_c"); CPPA_CHECK_EQUAL(res.type().name(), "struct_c");
c2 = object_cast<const struct_c&>(res); c2 = get<struct_c>(res);
} }
delete buf.second;
// verify result of serialization / deserialization // verify result of serialization / deserialization
CPPA_CHECK_EQUAL(c1, c2); CPPA_CHECK_EQUAL(c1, c2);
} }
......
...@@ -83,21 +83,12 @@ std::size_t test__uniform_type() ...@@ -83,21 +83,12 @@ std::size_t test__uniform_type()
object obj1 = uniform_typeid<foo>()->create(); object obj1 = uniform_typeid<foo>()->create();
object obj2(obj1); object obj2(obj1);
CPPA_CHECK_EQUAL(obj1, obj2); CPPA_CHECK_EQUAL(obj1, obj2);
get<foo>(obj1).value = 42;
CPPA_CHECK(obj1 != obj2);
CPPA_CHECK_EQUAL(get<foo>(obj1).value, 42);
CPPA_CHECK_EQUAL(get<foo>(obj2).value, 0);
} }
*/
{
object wstr_obj1 = uniform_typeid<std::wstring>()->create();
object_cast<std::wstring&>(wstr_obj1) = L"hello wstring!";
object wstr_obj2 = uniform_typeid<std::wstring>()->from_string("hello wstring!");
CPPA_CHECK_EQUAL(wstr_obj1, wstr_obj2);
const object& obj2_ref = wstr_obj2;
CPPA_CHECK_EQUAL(object_cast<std::wstring&>(wstr_obj1),
object_cast<const std::wstring&>(obj2_ref));
// couldn't be converted to ASCII
object_cast<std::wstring&>(wstr_obj1) = L"hello wstring\x05D4";
std::string narrowed = wstr_obj1.to_string();
CPPA_CHECK_EQUAL(narrowed, "hello wstring?");
}
int successful_announces = (unused1 ? 1 : 0) int successful_announces = (unused1 ? 1 : 0)
+ (unused2 ? 1 : 0) + (unused2 ? 1 : 0)
...@@ -110,12 +101,12 @@ std::size_t test__uniform_type() ...@@ -110,12 +101,12 @@ std::size_t test__uniform_type()
// the uniform_type_info implementation is correct // the uniform_type_info implementation is correct
std::set<std::string> expected = std::set<std::string> expected =
{ {
"@_::foo", // name of <anonymous namespace>::foo // "@_::foo", // name of <anonymous namespace>::foo
"@i8", "@i16", "@i32", "@i64", // signed integer names "@i8", "@i16", "@i32", "@i64", // signed integer names
"@u8", "@u16", "@u32", "@u64", // unsigned integer names "@u8", "@u16", "@u32", "@u64", // unsigned integer names
"@str", "@wstr", // strings "@str", "@u16str", "@u32str", // strings
"float", "double", // floating points "float", "double", // floating points
"@0", // util::void_type "@0", // util::void_type
// default announced cppa types // default announced cppa types
"cppa::any_type", "cppa::any_type",
"cppa::intrusive_ptr<cppa::actor>" "cppa::intrusive_ptr<cppa::actor>"
...@@ -140,27 +131,27 @@ std::size_t test__uniform_type() ...@@ -140,27 +131,27 @@ std::size_t test__uniform_type()
// compare the two sets // compare the two sets
CPPA_CHECK_EQUAL(expected.size(), found.size()); CPPA_CHECK_EQUAL(expected.size(), found.size());
bool expected_equals_found = false;
if (expected.size() == found.size()) if (expected.size() == found.size())
{ {
bool expected_equals_found = std::equal(found.begin(), expected_equals_found = std::equal(found.begin(),
found.end(), found.end(),
expected.begin()); expected.begin());
CPPA_CHECK(expected_equals_found); CPPA_CHECK(expected_equals_found);
if (!expected_equals_found) }
if (!expected_equals_found)
{
cout << "found:" << endl;
for (const std::string& tname : found)
{ {
cout << "found:" << endl; cout << " - " << tname << endl;
for (const std::string& tname : found) }
{ cout << "expected: " << endl;
cout << " - " << tname << endl; for (const std::string& tname : expected)
} {
cout << "expected: " << endl; cout << " - " << tname << endl;
for (const std::string& tname : expected)
{
cout << " - " << tname << endl;
}
} }
} }
*/
return CPPA_TEST_RESULT; 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