Commit d0c322ae authored by neverlord's avatar neverlord

binary_deserializer

parent 65a71be9
......@@ -135,7 +135,7 @@
</data>
<data>
<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>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
......
......@@ -140,3 +140,6 @@ cppa/util/rm_ref.hpp
cppa/util/is_iterable.hpp
cppa/binary_serializer.hpp
src/binary_serializer.cpp
cppa/binary_deserializer.hpp
src/binary_deserializer.cpp
src/actor.cpp
#ifndef ACTOR_HPP
#define ACTOR_HPP
#include <cstdint>
#include "cppa/group.hpp"
#include "cppa/channel.hpp"
......@@ -12,6 +14,12 @@ class deserializer;
class actor : public channel
{
std::uint32_t m_id;
protected:
actor();
public:
virtual void join(group_ptr& what) = 0;
......@@ -22,6 +30,13 @@ class actor : public channel
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; }
/**
* @brief
*/
static intrusive_ptr<actor> by_id(std::uint32_t actor_id);
};
typedef intrusive_ptr<actor> actor_ptr;
......
#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
|| is_stl_compliant_list<T>::value;
};
template<typename Struct>
class default_uniform_type_info_impl : public util::uniform_type_info_base<Struct>
template<typename T>
class default_uniform_type_info_impl : public util::uniform_type_info_base<T>
{
template<typename T>
template<typename X>
struct is_invalid
{
static const bool value = !util::is_primitive<T>::value
&& !is_stl_compliant_map<T>::value
&& !is_stl_compliant_list<T>::value;
static const bool value = !util::is_primitive<X>::value
&& !is_stl_compliant_map<X>::value
&& !is_stl_compliant_list<X>::value;
};
class member
......@@ -124,8 +124,8 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<Struc
public:
template<typename T, class C>
member(uniform_type_info* mtptr, T C::*mem_ptr) : m_meta(mtptr)
template<typename R, class C>
member(uniform_type_info* mtptr, R C::*mem_ptr) : m_meta(mtptr)
{
m_serialize = [mem_ptr] (const uniform_type_info* mt,
const void* obj,
......@@ -193,70 +193,70 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<Struc
// pr.first = member pointer
// pr.second = meta object to handle pr.first
template<typename T, class C, typename... Args>
void push_back(std::pair<T C::*, util::uniform_type_info_base<T>*> pr,
template<typename R, class C, typename... Args>
void push_back(std::pair<R C::*, util::uniform_type_info_base<R>*> pr,
const Args&... args)
{
m_members.push_back({ pr.second, pr.first });
push_back(args...);
}
template<class C, typename T, typename... Args>
typename util::enable_if<util::is_primitive<T> >::type
push_back(T C::*mem_ptr, const Args&... args)
template<typename R, class C, typename... Args>
typename util::enable_if<util::is_primitive<R> >::type
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...);
}
template<class C, typename T, typename... Args>
typename util::enable_if<is_stl_compliant_list<T> >::type
push_back(T C::*mem_ptr, const Args&... args)
template< typename R, class C,typename... Args>
typename util::enable_if<is_stl_compliant_list<R> >::type
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...);
}
template<class C, typename T, typename... Args>
typename util::enable_if<is_stl_compliant_map<T> >::type
push_back(T C::*mem_ptr, const Args&... args)
template<typename R, class C, typename... Args>
typename util::enable_if<is_stl_compliant_map<R> >::type
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...);
}
template<class C, typename T, typename... Args>
typename util::enable_if<is_invalid<T>>::type
push_back(T C::*mem_ptr, const Args&... args)
template<typename R, class C, typename... Args>
typename util::enable_if<is_invalid<R>>::type
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 "
"stl-compliant list/map");
}
template<typename T>
template<class C>
void init_(typename
util::enable_if<
util::disjunction<std::is_same<T,util::void_type>,
std::is_same<T,any_type>>>::type* = 0)
util::disjunction<std::is_same<C, util::void_type>,
std::is_same<C, any_type>>>::type* = 0)
{
// any_type doesn't have any fields (no serialization required)
}
template<typename T>
void init_(typename util::enable_if<util::is_primitive<T>>::type* = 0)
template<typename P>
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
util::disable_if<
util::disjunction<util::is_primitive<T>,
std::is_same<T,util::void_type>,
std::is_same<T,any_type>>>::type* = 0)
util::disjunction<util::is_primitive<X>,
std::is_same<X, util::void_type>,
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 "
"stl-compliant list/map");
}
......@@ -271,7 +271,7 @@ class default_uniform_type_info_impl : public util::uniform_type_info_base<Struc
default_uniform_type_info_impl()
{
init_<Struct>();
init_<T>();
}
void serialize(const void* obj, serializer* s) const
......
......@@ -67,6 +67,7 @@ public:
* @post {@code other.type() == nullptr}
*/
object& operator=(object&& other);
object& operator=(const object& other);
bool equal(const object& other) const;
......@@ -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>
struct object_caster<T&>
struct object_caster
{
static T& _(object& obj)
{
assert_type(obj, typeid(T));
return *reinterpret_cast<T*>(obj.m_value);
}
};
// 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)
static const T& _(const object& obj)
{
assert_type(obj, typeid(T));
return reinterpret_cast<T*>(obj.m_value);
return *reinterpret_cast<const T*>(obj.m_value);
}
};
template<typename T>
struct is_const_reference : std::false_type { };
template<typename T>
struct is_const_reference<const T&> : std::true_type { };
} // namespace detail
template<typename T>
struct is_const_pointer : std::false_type { };
template<typename T>
struct is_const_pointer<const T*> : std::true_type { };
}
template<typename T>
T object_cast(object& obj)
T& get(object& obj)
{
static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value,
"T is neither a reference nor a pointer type.");
std::is_reference<T>>::value == false,
"T is a reference or a pointer type.");
return detail::object_caster<T>::_(obj);
}
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>,
detail::is_const_reference<T>>::value,
"T is neither a const reference nor a const pointer type.");
static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value,
"T is a reference a pointer type.");
return detail::object_caster<T>::_(obj);
}
......
......@@ -21,17 +21,21 @@
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)
* reflection in combination with {@link cppa::object object}.
* @brief Provides a platform independent type name and a (very primitive)
* kind of reflection in combination with {@link cppa::object object}.
*
* The platform dependent type name (from GCC or Microsofts VC++ Compiler) is
* translated to a (usually) shorter and platform independent name.
*
* This name is usually equal to the "in-sourcecode-name",
* with a few exceptions:
* This name is equal to the "in-sourcecode-name" but with a few exceptions:
* - @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
* e.g.: @c \@i32 is a 32 bit signed integer; @c \@u16
* is a 16 bit unsigned integer
......@@ -46,10 +50,7 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
friend class object;
// needs access to by_type_info()
template<typename T>
friend uniform_type_info* uniform_typeid();
friend uniform_type_info* uniform_typeid(const std::type_info&);
friend const uniform_type_info* uniform_typeid(const std::type_info&);
public:
......@@ -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=(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:
explicit uniform_type_info(const std::string& uniform_name);
uniform_type_info(const std::string& uniform_name);
public:
......@@ -134,6 +135,7 @@ class uniform_type_info : cppa::util::comparable<uniform_type_info>
{
return id().compare(other.id());
}
/**
* @brief Add a new type mapping to the libCPPA internal type system.
* @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>
// const ToStringFun& ts, const FromStringFun& fs);
/**
* @brief Create an object of this type.
* @brief Creates an object of this type.
*/
object create() const;
object deserialize(deserializer* from) const;
/**
* @brief Deserializes an object of this type from @p source.
*/
object deserialize(deserializer* source) const;
protected:
......@@ -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>
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);
......
......@@ -12,7 +12,7 @@ namespace cppa {
// forward declarations
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
......
......@@ -6,6 +6,9 @@ INCLUDES = -I./
HEADERS = cppa/actor.hpp \
cppa/any_type.hpp \
cppa/binary_deserializer.hpp \
cppa/binary_serializer.hpp \
cppa/channel.hpp \
cppa/config.hpp \
cppa/context.hpp \
cppa/cow_ptr.hpp \
......@@ -65,7 +68,9 @@ HEADERS = cppa/actor.hpp \
cppa/util/type_list_pop_back.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/blocking_message_queue.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
}
template<typename T>
void operator()(const T& value,
void operator()(const T&,
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)
......
......@@ -47,6 +47,12 @@ inline const char* raw_name(const std::type_info& tinfo)
#endif
}
template<typename T>
struct is_signed : std::integral_constant<bool,
std::numeric_limits<T>::is_signed>
{
};
template<typename T>
inline const char* raw_name()
{
......@@ -72,13 +78,13 @@ void push(std::map<int, std::pair<string_set, string_set>>& ints,
template<typename Int>
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>
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);
}
......@@ -86,6 +92,33 @@ void push(std::map<int, std::pair<string_set, string_set>>& ints)
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
{
......@@ -127,8 +160,9 @@ class uniform_type_info_map
uniform_type_info_map()
{
insert<std::string>();
//insert<wstring_obj>({std::string(raw_name<std::wstring>())});
//insert(new wstring_utype, { std::string(raw_name<std::wstring>()) });
insert<std::u16string>();
insert<std::u32string>();
insert(new actor_ptr_type_info_impl, { raw_name<actor_ptr>() });
insert<float>();
insert<cppa::util::void_type>();
if (sizeof(double) == sizeof(long double))
......@@ -213,7 +247,9 @@ class uniform_type_info_map
{
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;
......@@ -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));
if (!result)
......@@ -281,20 +323,6 @@ uniform_type_info* uniform_type_info::by_uniform_name(const std::string& name)
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
{
auto ptr = new_instance();
......@@ -307,7 +335,7 @@ std::vector<uniform_type_info*> uniform_type_info::instances()
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);
}
......
......@@ -55,7 +55,7 @@ int main(int argc, char** c_argv)
std::cout << std::boolalpha;
std::size_t errors = 0;
RUN_TEST(test__primitive_variant);
// RUN_TEST(test__uniform_type);
RUN_TEST(test__uniform_type);
RUN_TEST(test__intrusive_ptr);
RUN_TEST(test__a_matches_b);
RUN_TEST(test__type_list);
......
......@@ -30,6 +30,7 @@
#include "cppa/primitive_type.hpp"
#include "cppa/primitive_variant.hpp"
#include "cppa/binary_serializer.hpp"
#include "cppa/binary_deserializer.hpp"
#include "cppa/util/apply.hpp"
#include "cppa/util/pt_token.hpp"
......@@ -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
{
......@@ -713,6 +491,12 @@ compound_member(C Parent::*c_ptr, const Args&... 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()
{
CPPA_TEST(test__serialization);
......@@ -740,11 +524,11 @@ std::size_t test__serialization()
// test serializers / deserializers with 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::y),
&struct_b::z,
&struct_b::ints));
&struct_b::ints);
// testees
struct_b b1 = { { 1, 2 }, 3, { 4, 5, 6, 7, 8, 9, 10 } };
struct_b b2;
......@@ -764,7 +548,7 @@ std::size_t test__serialization()
binary_deserializer bd(bs.data(), bs.size());
object res = root_object.deserialize(&bd);
CPPA_CHECK_EQUAL(res.type().name(), "struct_b");
b2 = object_cast<const struct_b&>(res);
b2 = get<struct_b>(res);
}
// cleanup
delete buf.second;
......@@ -776,33 +560,27 @@ std::size_t test__serialization()
string_deserializer strd(b1str);
auto res = root_object.deserialize(&strd);
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);
}
// test serializers / deserializers with struct_c
{
// 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
struct_c c1 = { { { "abc", u"cba" }, { "x", u"y" } }, { 9, 4, 5 } };
struct_c c2;
// binary buffer
std::pair<size_t, char*> buf;
// serialize c1 to buf
{
// serialize c1 to buf
binary_serializer bs;
root_object.serialize(c1, &bs);
buf = bs.take_buffer();
}
// serialize c2 from buf
{
binary_deserializer bd(buf.second, buf.first);
binary_deserializer bd(bs.data(), bs.size());
auto res = root_object.deserialize(&bd);
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
CPPA_CHECK_EQUAL(c1, c2);
}
......
......@@ -83,21 +83,12 @@ std::size_t test__uniform_type()
object obj1 = uniform_typeid<foo>()->create();
object obj2(obj1);
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)
+ (unused2 ? 1 : 0)
......@@ -110,10 +101,10 @@ std::size_t test__uniform_type()
// the uniform_type_info implementation is correct
std::set<std::string> expected =
{
"@_::foo", // name of <anonymous namespace>::foo
// "@_::foo", // name of <anonymous namespace>::foo
"@i8", "@i16", "@i32", "@i64", // signed integer names
"@u8", "@u16", "@u32", "@u64", // unsigned integer names
"@str", "@wstr", // strings
"@str", "@u16str", "@u32str", // strings
"float", "double", // floating points
"@0", // util::void_type
// default announced cppa types
......@@ -140,12 +131,15 @@ std::size_t test__uniform_type()
// compare the two sets
CPPA_CHECK_EQUAL(expected.size(), found.size());
bool expected_equals_found = false;
if (expected.size() == found.size())
{
bool expected_equals_found = std::equal(found.begin(),
expected_equals_found = std::equal(found.begin(),
found.end(),
expected.begin());
CPPA_CHECK(expected_equals_found);
}
if (!expected_equals_found)
{
cout << "found:" << endl;
......@@ -159,8 +153,5 @@ std::size_t test__uniform_type()
cout << " - " << tname << endl;
}
}
}
*/
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