Commit cc1a1fc6 authored by neverlord's avatar neverlord

serialization testing

parent 97aff6bf
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<qtcreator> <qtcreator>
<data> <data>
<variable>RunConfiguration0-Arguments</variable> <variable>GenericProjectManager.GenericProject.Toolchain</variable>
<valuelist type="QVariantList"/> <value type="QString"></value>
</data> </data>
<data> <data>
<variable>RunConfiguration0-BaseEnvironmentBase</variable> <variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">2</value>
</data>
<data>
<variable>RunConfiguration0-Executable</variable>
<value type="QString">/Users/neverlord/libcppa/test</value>
</data>
<data>
<variable>RunConfiguration0-RunConfiguration.name</variable>
<value type="QString">test</value>
</data>
<data>
<variable>RunConfiguration0-UseTerminal</variable>
<value type="bool">false</value>
</data>
<data>
<variable>RunConfiguration0-UserEnvironmentChanges</variable>
<valuelist type="QVariantList"/>
</data>
<data>
<variable>RunConfiguration0-UserName</variable>
<value type="QString">test</value>
</data>
<data>
<variable>RunConfiguration0-UserSetName</variable>
<value type="bool">true</value>
</data>
<data>
<variable>RunConfiguration0-WorkingDirectory</variable>
<value type="QString">$BUILDDIR</value>
</data>
<data>
<variable>RunConfiguration0-type</variable>
<value type="QString">ProjectExplorer.CustomExecutableRunConfiguration</value>
</data>
<data>
<variable>activeRunConfiguration</variable>
<value type="int">0</value> <value type="int">0</value>
</data> </data>
<data> <data>
<variable>activebuildconfiguration</variable> <variable>ProjectExplorer.Project.EditorSettings</variable>
<value type="QString">all</value>
</data>
<data>
<variable>buildConfiguration-all</variable>
<valuemap type="QVariantMap">
<value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">all</value>
<value key="buildDirectory" type="QString">/Users/neverlord/libcppa</value>
</valuemap>
</data>
<data>
<variable>buildconfiguration-all-buildstep0</variable>
<valuemap type="QVariantMap"> <valuemap type="QVariantMap">
<value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString">all</value> <value key="EditorConfiguration.AutoIndent" type="bool">true</value>
<valuelist key="abstractProcess.Environment" type="QVariantList"> <value key="EditorConfiguration.AutoSpacesForTabs" type="bool">false</value>
<value type="QString">Apple_PubSub_Socket_Render=/tmp/launch-m6Qmev/Render</value> <value key="EditorConfiguration.Codec" type="QByteArray">System</value>
<value type="QString">COMMAND_MODE=unix2003</value> <value key="EditorConfiguration.DoubleIndentBlocks" type="bool">false</value>
<value type="QString">DISPLAY=/tmp/launch-Yl5R56/org.x:0</value> <value key="EditorConfiguration.IndentBraces" type="bool">false</value>
<value type="QString">HOME=/Users/neverlord</value> <value key="EditorConfiguration.IndentSize" type="int">4</value>
<value type="QString">LOGNAME=neverlord</value> <value key="EditorConfiguration.MouseNavigation" type="bool">true</value>
<value type="QString">PATH=/usr/bin:/bin:/usr/sbin:/sbin</value> <value key="EditorConfiguration.PaddingMode" type="int">1</value>
<value type="QString">SHELL=/bin/bash</value> <value key="EditorConfiguration.ScrollWheelZooming" type="bool">true</value>
<value type="QString">SSH_AUTH_SOCK=/tmp/launch-3kvI77/Listeners</value> <value key="EditorConfiguration.SmartBackspace" type="bool">false</value>
<value type="QString">TMPDIR=/var/folders/SE/SEReyCW0H-yDPCnNCe8mN++++TI/-Tmp-/</value> <value key="EditorConfiguration.SpacesForTabs" type="bool">false</value>
<value type="QString">USER=neverlord</value> <value key="EditorConfiguration.TabKeyBehavior" type="int">0</value>
<value type="QString">__CF_USER_TEXT_ENCODING=0x1F5:0:3</value> <value key="EditorConfiguration.TabSize" type="int">4</value>
</valuelist> <value key="EditorConfiguration.UseGlobal" type="bool">true</value>
<valuelist key="abstractProcess.arguments" type="QVariantList"> <value key="EditorConfiguration.Utf8BomBehavior" type="int">1</value>
<value type="QString">all</value> <value key="EditorConfiguration.addFinalNewLine" type="bool">true</value>
</valuelist> <value key="EditorConfiguration.cleanIndentation" type="bool">true</value>
<value key="abstractProcess.command" type="QString">make</value> <value key="EditorConfiguration.cleanWhitespace" type="bool">true</value>
<value key="abstractProcess.enabled" type="bool">true</value> <value key="EditorConfiguration.inEntireDocument" type="bool">false</value>
<value key="abstractProcess.workingDirectory" type="QString">/Users/neverlord/libcppa</value>
<valuelist key="buildTargets" type="QVariantList">
<value type="QString">all</value>
</valuelist>
</valuemap> </valuemap>
</data> </data>
<data> <data>
<variable>buildconfigurations</variable> <variable>ProjectExplorer.Project.Target.0</variable>
<valuelist type="QVariantList">
<value type="QString">all</value>
</valuelist>
</data>
<data>
<variable>buildstep0</variable>
<valuemap type="QVariantMap"> <valuemap type="QVariantMap">
<value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString"></value> <value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Desktop</value>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">GenericProjectManager.GenericTarget</value>
<value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
<value key="ProjectExplorer.Target.ActiveDeployConfiguration" type="int">0</value>
<value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
<valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
<value key="GenericProjectManager.GenericBuildConfiguration.BuildDirectory" type="QString">/Users/neverlord/libcppa</value>
<value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">INVALID</value>
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap">
<valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap">
<valuelist key="GenericProjectManager.GenericMakeStep.BuildTargets" type="QVariantList">
<value type="QString">all</value>
</valuelist>
<value key="GenericProjectManager.GenericMakeStep.MakeArguments" type="QString"></value>
<value key="GenericProjectManager.GenericMakeStep.MakeCommand" type="QString"></value>
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">GenericProjectManager.GenericMakeStep</value>
</valuemap>
<value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value>
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Build</value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap">
<value key="ProjectExplorer.BuildStepList.StepsCount" type="int">0</value>
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Clean</value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value>
<value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
<valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">all</value>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">all</value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">GenericProjectManager.GenericBuildConfiguration</value>
</valuemap>
<value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">1</value>
<valuemap key="ProjectExplorer.Target.DeployConfiguration.0" type="QVariantMap">
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap">
<value key="ProjectExplorer.BuildStepList.StepsCount" type="int">0</value>
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Deployment</value>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Deploy</value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">1</value>
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Kein Deployment</value>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Kein Deployment</value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value key="ProjectExplorer.Target.DeployConfigurationCount" type="int">1</value>
<valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
<valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/>
<value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value>
<value key="Analyzer.Valgrind.NumCallers" type="int">25</value>
<valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/>
<value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value>
<value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value>
<valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments" type="QString"></value>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.BaseEnvironmentBase" type="int">2</value>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.Executable" type="QString">/Users/neverlord/libcppa/test</value>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal" type="bool">false</value>
<valuelist key="ProjectExplorer.CustomExecutableRunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
<value key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory" type="QString">%{buildDir}</value>
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Führe /Users/neverlord/libcppa/test aus</value>
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">test</value>
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.CustomExecutableRunConfiguration</value>
<value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value>
<value key="RunConfiguration.UseCppDebugger" type="bool">true</value>
<value key="RunConfiguration.UseQmlDebugger" type="bool">false</value>
</valuemap>
<value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
</valuemap> </valuemap>
</data> </data>
<data> <data>
<variable>buildsteps</variable> <variable>ProjectExplorer.Project.TargetCount</variable>
<valuelist type="QVariantList"> <value type="int">1</value>
<value type="QString">GenericProjectManager.MakeStep</value>
</valuelist>
</data>
<data>
<variable>cleansteps</variable>
<valuelist type="QVariantList"/>
</data>
<data>
<variable>defaultFileEncoding</variable>
<value type="QByteArray">System</value>
</data>
<data>
<variable>includePaths</variable>
<valuelist type="QVariantList"/>
</data> </data>
<data> <data>
<variable>project</variable> <variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
<valuemap type="QVariantMap"/> <value type="QString">{349f52bc-ac64-4a14-898f-d44d989b22a2}</value>
</data> </data>
<data> <data>
<variable>toolChain</variable> <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">0</value> <value type="int">9</value>
</data> </data>
</qtcreator> </qtcreator>
...@@ -72,7 +72,7 @@ class default_uniform_type_info_impl : public uniform_type_info ...@@ -72,7 +72,7 @@ class default_uniform_type_info_impl : public uniform_type_info
object create() const object create() const
{ {
return { new T, this }; return { new T(), this };
} }
}; };
......
...@@ -4,17 +4,17 @@ ...@@ -4,17 +4,17 @@
#include <string> #include <string>
#include <typeinfo> #include <typeinfo>
#include <stdexcept> #include <stdexcept>
#include <type_traits>
#include "cppa/util/disjunction.hpp"
namespace cppa { namespace cppa {
// forward declarations
class object; class object;
class uniform_type_info; class uniform_type_info;
namespace detail { template<typename T> struct object_caster; }
template<typename T> bool operator==(const uniform_type_info& lhs, const std::type_info& rhs);
T& object_cast(object& obj);
template<typename T>
const T& object_cast(const object& obj);
/** /**
* @brief foobar. * @brief foobar.
...@@ -25,10 +25,7 @@ class object ...@@ -25,10 +25,7 @@ class object
friend class uniform_type_info; friend class uniform_type_info;
template<typename T> template<typename T>
friend T& object_cast(object& obj); friend struct detail::object_caster;
template<typename T>
friend const T& object_cast(const object& obj);
void* m_value; void* m_value;
const uniform_type_info* m_type; const uniform_type_info* m_type;
...@@ -80,40 +77,102 @@ public: ...@@ -80,40 +77,102 @@ public:
}; };
// forward declaration of the == operator inline bool operator==(const object& lhs, const object& rhs)
bool operator==(const uniform_type_info& lhs, const std::type_info& rhs); {
return lhs.equal(rhs);
}
template<typename T> inline bool operator!=(const object& lhs, const object& rhs)
T& object_cast(object& obj)
{ {
// if (!(obj.type() == typeid(T))) return !(lhs == rhs);
if (!operator==(obj.type(), typeid(T))) }
namespace detail {
inline void assert_type(const object& obj, const std::type_info& tinfo)
{
if (!(obj.type() == tinfo))
{ {
throw std::logic_error("object type doesnt match T"); throw std::logic_error("object type doesnt match T");
} }
return *reinterpret_cast<T*>(obj.m_value);
} }
// get a const reference
template<typename T> template<typename T>
const T& object_cast(const object& obj) struct object_caster<const T&>
{ {
if (!(obj.type() == typeid(T))) static const T& _(const object& obj)
{ {
throw std::logic_error("object type doesnt match T"); assert_type(obj, typeid(T));
return *reinterpret_cast<const T*>(obj.m_value);
} }
return *reinterpret_cast<const T*>(obj.m_value); };
}
} // namespace cppa // get a mutable reference
template<typename T>
struct object_caster<T&>
{
static T& _(object& obj)
{
assert_type(obj, typeid(T));
return *reinterpret_cast<T*>(obj.m_value);
}
};
inline bool operator==(const cppa::object& lhs, const cppa::object& rhs) // get a const pointer
template<typename T>
struct object_caster<const T*>
{ {
return lhs.equal(rhs); 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));
return reinterpret_cast<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 { };
template<typename T>
struct is_const_pointer : std::false_type { };
template<typename T>
struct is_const_pointer<const T*> : std::true_type { };
} }
inline bool operator!=(const cppa::object& lhs, const cppa::object& rhs) template<typename T>
T object_cast(object& obj)
{ {
return !(lhs == rhs); static_assert(util::disjunction<std::is_pointer<T>,
std::is_reference<T>>::value,
"T is neither a reference nor a pointer type.");
return detail::object_caster<T>::_(obj);
} }
template<typename T>
const T& object_cast(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.");
return detail::object_caster<T>::_(obj);
}
} // namespace cppa
#endif // OBJECT_HPP #endif // OBJECT_HPP
...@@ -8,32 +8,32 @@ namespace cppa { namespace util { ...@@ -8,32 +8,32 @@ namespace cppa { namespace util {
template<typename Signature> template<typename Signature>
struct callable_trait; struct callable_trait;
template<class C, typename Result, typename... Args> template<class C, typename ResultType, typename... Args>
struct callable_trait<Result (C::*)(Args...) const> struct callable_trait<ResultType (C::*)(Args...) const>
{ {
typedef Result result_type; typedef ResultType result_type;
typedef type_list<Args...> arg_types; typedef type_list<Args...> arg_types;
}; };
template<class C, typename Result, typename... Args> template<class C, typename ResultType, typename... Args>
struct callable_trait<Result (C::*)(Args...)> struct callable_trait<ResultType (C::*)(Args...)>
{ {
typedef Result result_type; typedef ResultType result_type;
typedef type_list<Args...> arg_types; typedef type_list<Args...> arg_types;
}; };
template<typename Result, typename... Args> template<typename ResultType, typename... Args>
struct callable_trait<Result (Args...)> struct callable_trait<ResultType (Args...)>
{ {
typedef Result result_type; typedef ResultType result_type;
typedef type_list<Args...> arg_types; typedef type_list<Args...> arg_types;
}; };
template<typename Result, typename... Args> template<typename ResultType, typename... Args>
struct callable_trait<Result (*)(Args...)> struct callable_trait<ResultType (*)(Args...)>
{ {
typedef Result result_type; typedef ResultType result_type;
typedef type_list<Args...> arg_types; typedef type_list<Args...> arg_types;
}; };
} } // namespace cppa::util } } // namespace cppa::util
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace cppa { namespace util { namespace cppa { namespace util {
template<bool Stmt, typename T> template<bool Stmt, typename T = void>
struct enable_if_c { }; struct enable_if_c { };
template<typename T> template<typename T>
...@@ -12,7 +12,7 @@ struct enable_if_c<true, T> ...@@ -12,7 +12,7 @@ struct enable_if_c<true, T>
typedef T type; typedef T type;
}; };
template<class Trait, typename T> template<class Trait, typename T = void>
struct enable_if : enable_if_c<Trait::value, T> struct enable_if : enable_if_c<Trait::value, T>
{ {
}; };
......
...@@ -314,7 +314,7 @@ uniform_type_info_map& s_uniform_type_info_map() ...@@ -314,7 +314,7 @@ uniform_type_info_map& s_uniform_type_info_map()
return s_utimap; return s_utimap;
} }
} } } // namespace detail::<anonymous> } } } // namespace cppa::detail::<anonymous>
namespace { namespace {
......
#include <new>
#include <locale>
#include <memory>
#include <string> #include <string>
#include <limits> #include <limits>
#include <vector> #include <vector>
...@@ -6,7 +9,9 @@ ...@@ -6,7 +9,9 @@
#include <cstdint> #include <cstdint>
#include <typeinfo> #include <typeinfo>
#include <iostream> #include <iostream>
#include <algorithm>
#include <type_traits> #include <type_traits>
#include <cassert>
#include "test.hpp" #include "test.hpp"
...@@ -17,6 +22,7 @@ ...@@ -17,6 +22,7 @@
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
#include "cppa/deserializer.hpp" #include "cppa/deserializer.hpp"
#include "cppa/untyped_tuple.hpp" #include "cppa/untyped_tuple.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util.hpp" #include "cppa/util.hpp"
...@@ -24,522 +30,1258 @@ using std::cout; ...@@ -24,522 +30,1258 @@ using std::cout;
using std::cerr; using std::cerr;
using std::endl; using std::endl;
/* /**
* @brief Integers, floating points and strings.
*/
enum fundamental_type
{
ft_int8, ft_int16, ft_int32, ft_int64,
ft_uint8, ft_uint16, ft_uint32, ft_uint64,
ft_float, ft_double, ft_long_double,
ft_u8string, ft_u16string, ft_u32string,
ft_null
};
using namespace cppa; constexpr const char* fundamental_type_names[] =
using namespace cppa::util; {
"ft_int8", "ft_int16", "ft_int32", "ft_int64",
"ft_uint8", "ft_uint16", "ft_uint32", "ft_uint64",
"ft_float", "ft_double", "ft_long_double",
"ft_u8string", "ft_u16string", "ft_u32string",
"ft_null"
};
class format_error : public std::runtime_error constexpr const char* fundamental_type_name(fundamental_type ftype)
{ {
return fundamental_type_names[static_cast<int>(ftype)];
}
typedef std::runtime_error super; // achieves static call dispatch (Int-To-Type idiom)
template<fundamental_type FT>
struct ft_token { static const fundamental_type value = FT; };
public: // if (IfStmt == true) type = T; else type = Else::type;
template<bool IfStmt, typename T, class Else>
struct if_else_type_c
{
typedef T type;
};
format_error(const std::string& what_str) : super(what_str) { } template<typename T, class Else>
struct if_else_type_c<false, T, Else>
{
typedef typename Else::type type;
};
// if (Stmt::value == true) type = T; else type = Else::type;
template<class Stmt, typename T, class Else>
struct if_else_type : if_else_type_c<Stmt::value, T, Else> { };
template<typename T>
struct wrapped_type { typedef T type; };
// maps the fundamental_type FT to the corresponding type
template<fundamental_type FT>
struct ftype_to_type
: if_else_type_c<FT == ft_int8, std::int8_t,
if_else_type_c<FT == ft_int16, std::int16_t,
if_else_type_c<FT == ft_int32, std::int32_t,
if_else_type_c<FT == ft_int64, std::int64_t,
if_else_type_c<FT == ft_uint8, std::uint8_t,
if_else_type_c<FT == ft_uint16, std::uint16_t,
if_else_type_c<FT == ft_uint32, std::uint32_t,
if_else_type_c<FT == ft_uint64, std::uint64_t,
if_else_type_c<FT == ft_float, float,
if_else_type_c<FT == ft_double, double,
if_else_type_c<FT == ft_long_double, long double,
if_else_type_c<FT == ft_u8string, std::string,
if_else_type_c<FT == ft_u16string, std::u16string,
if_else_type_c<FT == ft_u32string, std::u32string,
wrapped_type<void> > > > > > > > > > > > > > >
{
};
// if (IfStmt == true) ftype = FT; else ftype = Else::ftype;
template<bool IfStmt, fundamental_type FT, class Else>
struct if_else_ftype_c
{
static const fundamental_type ftype = FT;
}; };
template<bool Streamable, typename T> template<fundamental_type FT, class Else>
struct to_string_ struct if_else_ftype_c<false, FT, Else>
{ {
inline static std::string _(const T&) { return "-?-"; } static const fundamental_type ftype = Else::ftype;
}; };
// if (Stmt::value == true) ftype = FT; else ftype = Else::ftype;
template<class Stmt, fundamental_type FT, class Else>
struct if_else_ftype : if_else_ftype_c<Stmt::value, FT, Else> { };
template<fundamental_type FT>
struct wrapped_ftype { static const fundamental_type ftype = FT; };
// maps type T the the corresponding fundamental_type
template<typename T> template<typename T>
struct to_string_<true, T> struct type_to_ftype
{ // signed integers
inline static std::string _(const T& what) : if_else_ftype<std::is_same<T, std::int8_t>, ft_int8,
{ if_else_ftype<std::is_same<T, std::int16_t>, ft_int16,
std::ostringstream oss; if_else_ftype<std::is_same<T, std::int32_t>, ft_int32,
oss << what; if_else_ftype<std::is_same<T, std::int64_t>, ft_int64,
return oss.str(); if_else_ftype<std::is_same<T, std::uint8_t>, ft_uint8,
} // unsigned integers
if_else_ftype<std::is_same<T, std::uint16_t>, ft_uint16,
if_else_ftype<std::is_same<T, std::uint32_t>, ft_uint32,
if_else_ftype<std::is_same<T, std::uint64_t>, ft_uint64,
// float / double
if_else_ftype<std::is_same<T, float>, ft_float,
if_else_ftype<std::is_same<T, double>, ft_double,
if_else_ftype<std::is_same<T, long double>, ft_long_double,
// strings
if_else_ftype<std::is_convertible<T, std::string>, ft_u8string,
if_else_ftype<std::is_convertible<T, std::u16string>, ft_u16string,
if_else_ftype<std::is_convertible<T, std::u32string>, ft_u32string,
wrapped_ftype<ft_null> > > > > > > > > > > > > > >
{
}; };
template<typename T> template<typename T>
class has_to_string struct type_to_ftype<T&> : type_to_ftype<T> { };
template<typename T>
struct type_to_ftype<T&&> : type_to_ftype<T> { };
template<typename T>
struct type_to_ftype<const T&> : type_to_ftype<T> { };
template<typename T>
struct type_to_ftype<const T> : type_to_ftype<T> { };
struct value
{ {
fundamental_type type;
inline value(const fundamental_type& ftype) : type(ftype) { }
};
template<typename A> struct list
static auto cmp_help_fun(std::ostream& o, A* arg) -> decltype(o << *arg) {
{ fundamental_type value_type;
return true; inline list(const fundamental_type& ftype) : value_type(ftype) { }
} };
struct map
{
fundamental_type key_type;
fundamental_type value_type;
inline map(const fundamental_type& key_ft, const fundamental_type& value_ft)
: key_type(key_ft), value_type(value_ft)
{
}
};
using cppa::util::enable_if;
template<bool Stmt, typename T>
struct disable_if_c { };
template<typename T>
struct disable_if_c<false, T>
{
typedef T type;
};
template<class Trait, typename T = void>
struct disable_if : disable_if_c<Trait::value, T> { };
template<fundamental_type FT, class T, class V>
void set_fun(fundamental_type& lhs_type, T& lhs, V&& rhs,
typename disable_if<std::is_arithmetic<T>>::type* = nullptr)
{
if (FT == lhs_type)
{
lhs = std::forward<V>(rhs);
}
else
{
new (&lhs) T(std::forward<V>(rhs));
lhs_type = FT;
}
}
template<fundamental_type FT, class T, class V>
void set_fun(fundamental_type& lhs_type, T& lhs, V&& rhs,
typename enable_if<std::is_arithmetic<T>>::type* = nullptr)
{
lhs = rhs;
lhs_type = FT;
}
template<class T>
void destroy_fun(T& what,
typename disable_if<std::is_arithmetic<T>>::type* = nullptr)
{
what.~T();
}
template<class T>
void destroy_fun(T&, typename enable_if<std::is_arithmetic<T>>::type* = nullptr)
{
// arithmetic types don't need destruction
}
class ft_value;
template<typename T>
T ft_value_cast(ft_value&);
template<typename T>
T ft_value_cast(const ft_value&);
template<fundamental_type FT>
typename ftype_to_type<FT>::type& ft_value_cast(ft_value&);
template<fundamental_type FT>
const typename ftype_to_type<FT>::type& ft_value_cast(const ft_value&);
template<typename Fun>
void ft_invoke(fundamental_type ftype, Fun&& f)
{
switch (ftype)
{
case ft_int8: f(ft_token<ft_int8>()); break;
case ft_int16: f(ft_token<ft_int16>()); break;
case ft_int32: f(ft_token<ft_int32>()); break;
case ft_int64: f(ft_token<ft_int64>()); break;
case ft_uint8: f(ft_token<ft_uint8>()); break;
case ft_uint16: f(ft_token<ft_uint16>()); break;
case ft_uint32: f(ft_token<ft_uint32>()); break;
case ft_uint64: f(ft_token<ft_uint64>()); break;
case ft_float: f(ft_token<ft_float>()); break;
case ft_double: f(ft_token<ft_double>()); break;
case ft_long_double: f(ft_token<ft_long_double>()); break;
case ft_u8string: f(ft_token<ft_u8string>()); break;
case ft_u16string: f(ft_token<ft_u16string>()); break;
case ft_u32string: f(ft_token<ft_u32string>()); break;
default: break;
}
}
static void cmp_help_fun(std::ostream&, void*) { } /**
* @brief Describes a value of a {@link fundamental_type}.
*/
class ft_value
{
typedef decltype(cmp_help_fun(*((std::ostream*) 0), (T*) 0)) result_type; template<typename T>
friend T ft_value_cast(ft_value&);
template<typename T>
friend T ft_value_cast(const ft_value&);
template<fundamental_type FT>
friend typename ftype_to_type<FT>::type& ft_value_cast(ft_value&);
template<fundamental_type FT>
friend const typename ftype_to_type<FT>::type& ft_value_cast(const ft_value&);
fundamental_type m_ftype;
union
{
std::int8_t i8;
std::int16_t i16;
std::int32_t i32;
std::int64_t i64;
std::uint8_t u8;
std::uint16_t u16;
std::uint32_t u32;
std::uint64_t u64;
float fl;
double dbl;
long double ldbl;
std::string str8;
std::u16string str16;
std::u32string str32;
};
// use static call dispatching to select member variable
inline decltype(i8)& get(ft_token<ft_int8>) { return i8; }
inline decltype(i16)& get(ft_token<ft_int16>) { return i16; }
inline decltype(i32)& get(ft_token<ft_int32>) { return i32; }
inline decltype(i64)& get(ft_token<ft_int64>) { return i64; }
inline decltype(u8)& get(ft_token<ft_uint8>) { return u8; }
inline decltype(u16)& get(ft_token<ft_uint16>) { return u16; }
inline decltype(u32)& get(ft_token<ft_uint32>) { return u32; }
inline decltype(u64)& get(ft_token<ft_uint64>) { return u64; }
inline decltype(fl)& get(ft_token<ft_float>) { return fl; }
inline decltype(dbl)& get(ft_token<ft_double>) { return dbl; }
inline decltype(ldbl)& get(ft_token<ft_long_double>) { return ldbl; }
inline decltype(str8)& get(ft_token<ft_u8string>) { return str8; }
inline decltype(str16)& get(ft_token<ft_u16string>) { return str16; }
inline decltype(str32)& get(ft_token<ft_u32string>) { return str32; }
// get(...) const overload
template<fundamental_type FT>
const typename ftype_to_type<FT>::type& get(ft_token<FT> token) const
{
return const_cast<ft_value*>(this)->get(token);
}
struct destroyer
{
ft_value* m_self;
inline destroyer(ft_value* self) : m_self(self) { }
template<fundamental_type FT>
inline void operator()(ft_token<FT> token) const
{
destroy_fun(m_self->get(token));
}
};
struct initializer
{
ft_value* m_self;
inline initializer(ft_value* self) : m_self(self) { }
template<fundamental_type FT>
inline void operator()(ft_token<FT> token) const
{
set_fun<FT>(m_self->m_ftype,
m_self->get(token),
typename ftype_to_type<FT>::type());
}
};
struct setter
{
ft_value* m_self;
const ft_value& m_other;
inline setter(ft_value* self, const ft_value& other)
: m_self(self), m_other(other) { }
template<fundamental_type FT>
inline void operator()(ft_token<FT> token) const
{
set_fun<FT>(m_self->m_ftype,
m_self->get(token),
m_other.get(token));
}
};
struct mover
{
ft_value* m_self;
const ft_value& m_other;
inline mover(ft_value* self, const ft_value& other)
: m_self(self), m_other(other) { }
template<fundamental_type FT>
inline void operator()(ft_token<FT> token) const
{
set_fun<FT>(m_self->m_ftype,
m_self->get(token),
std::move(m_other.get(token)));
}
};
struct comparator
{
bool m_result;
const ft_value* m_self;
const ft_value& m_other;
inline comparator(const ft_value* self, const ft_value& other)
: m_result(false), m_self(self), m_other(other) { }
template<fundamental_type FT>
inline void operator()(ft_token<FT> token)
{
if (m_other.m_ftype == FT)
{
m_result = (m_self->get(token) == m_other.get(token));
}
}
inline bool result() const { return m_result; }
};
void destroy()
{
ft_invoke(m_ftype, destroyer(this));
m_ftype = ft_null;
}
template<class Self, typename Fun>
struct forwarder
{
Self* m_self;
Fun& m_f;
forwarder(Self* self, Fun& f) : m_self(self), m_f(f) { }
template<fundamental_type FT>
inline void operator()(ft_token<FT> token)
{
m_f(m_self->get(token));
}
};
public: public:
static const bool value = std::is_same<std::ostream&, result_type>::value; template<typename Fun>
void apply(Fun&& f)
{
ft_invoke(m_ftype, forwarder<ft_value, Fun>(this, f));
}
template<typename Fun>
void apply(Fun&& f) const
{
ft_invoke(m_ftype, forwarder<const ft_value, Fun>(this, f));
}
ft_value() : m_ftype(ft_null) { }
template<typename V>
ft_value(V&& value) : m_ftype(ft_null)
{
static_assert(type_to_ftype<V>::ftype != ft_null,
"T is not a valid value for ft_value");
set_fun<type_to_ftype<V>::ftype>(m_ftype,
get(ft_token<type_to_ftype<V>::ftype>()),
std::forward<V>(value));
}
ft_value(fundamental_type ftype) : m_ftype(ft_null)
{
ft_invoke(ftype, initializer(this));
}
ft_value(const ft_value& other) : m_ftype(ft_null)
{
//invoke(setter(other));
ft_invoke(other.m_ftype, setter(this, other));
}
ft_value(ft_value&& other) : m_ftype(ft_null)
{
//invoke(mover(other));
ft_invoke(other.m_ftype, mover(this, other));
}
ft_value& operator=(const ft_value& other)
{
//invoke(setter(other));
ft_invoke(other.m_ftype, setter(this, other));
return *this;
}
ft_value& operator=(ft_value&& other)
{
//invoke(mover(other));
ft_invoke(other.m_ftype, mover(this, other));
return *this;
}
bool operator==(const ft_value& other) const
{
comparator cmp(this, other);
ft_invoke(m_ftype, cmp);
return cmp.result();
}
bool operator!=(const ft_value& other) const
{
return !(*this == other);
}
inline fundamental_type type() const { return m_ftype; }
~ft_value() { destroy(); }
}; };
template<typename T> template<typename T>
struct meta_type typename cppa::util::enable_if<std::is_arithmetic<T>, bool>::type
{ operator==(const T& lhs, const ft_value& rhs)
static std::string to_string(const T& what) {
{ return (rhs.type() == type_to_ftype<T>::ftype)
return to_string_<has_to_string<T>::value, T>::_(what); ? lhs == ft_value_cast<const T&>(rhs)
} : false;
static T from_string(const std::string&) }
{
throw format_error(""); template<typename T>
} typename cppa::util::enable_if<std::is_arithmetic<T>, bool>::type
operator==(const ft_value& lhs, const T& rhs)
{
return (lhs.type() == type_to_ftype<T>::ftype)
? ft_value_cast<const T&>(lhs) == rhs
: false;
}
template<typename T>
typename cppa::util::enable_if<std::is_arithmetic<T>, bool>::type
operator!=(const T& lhs, const ft_value& rhs)
{
return !(lhs == rhs);
}
template<typename T>
typename cppa::util::enable_if<std::is_arithmetic<T>, bool>::type
operator!=(const ft_value& lhs, const T& rhs)
{
return !(lhs == rhs);
}
template<fundamental_type FT>
typename ftype_to_type<FT>::type& ft_value_cast(ft_value& v)
{
if (v.type() != FT) throw std::bad_cast();
return v.get(ft_token<FT>());
}
template<fundamental_type FT>
const typename ftype_to_type<FT>::type& ft_value_cast(const ft_value& v)
{
if (v.type() != FT) throw std::bad_cast();
return v.get(ft_token<FT>());
}
template<typename T>
T ft_value_cast(ft_value& v)
{
static const fundamental_type ftype = type_to_ftype<T>::ftype;
if (v.type() != ftype) throw std::bad_cast();
return v.get(ft_token<ftype>());
}
template<typename T>
T ft_value_cast(const ft_value& v)
{
typedef typename std::remove_reference<T>::type plain_t;
static_assert(!std::is_reference<T>::value || std::is_const<plain_t>::value,
"Could not get a non-const reference from const ft_value&");
static const fundamental_type ftype = type_to_ftype<T>::ftype;
if (v.type() != ftype) throw std::bad_cast();
return v.get(ft_token<ftype>());
}
class value_property
{
public:
virtual ~value_property() { }
virtual void set(ft_value&& what) = 0;
virtual void get(ft_value& storage) const = 0;
virtual fundamental_type type() const = 0;
}; };
template<> class list_property
struct meta_type<std::string> {
{
static std::string to_string(const std::string& what) public:
{
std::string result; class iterator
result.reserve(what.size() + 2); {
result = "\"";
result += what; public:
result += "\"";
return result; virtual ~iterator() { }
} virtual void next() = 0;
static std::string from_string(const std::string& str) virtual bool at_end() const = 0;
{ virtual ft_value get() const = 0;
return str;
} };
virtual ~list_property() { }
virtual size_t size() const = 0;
virtual iterator* begin() const = 0;
virtual fundamental_type value_type() const = 0;
virtual void push_back(ft_value&& what) = 0;
}; };
template<int N, typename Tuple> class map_property
struct mt_helper
{ {
typedef typename util::type_at<N, Tuple>::type element_type;
inline static void to_string(std::ostringstream& oss, const Tuple& t) public:
{
mt_helper<N - 1, Tuple>::to_string(oss, t); class iterator
oss << meta_type<element_type>::to_string(t.get<N>()); {
if (N < (Tuple::type_list_size - 1)) oss << ", ";
} public:
virtual ~iterator() { }
virtual void next() = 0;
virtual bool at_end() const = 0;
virtual ft_value key() const = 0;
virtual ft_value value() const = 0;
};
virtual ~map_property() { }
virtual size_t size() const = 0;
virtual iterator* begin() const = 0;
virtual fundamental_type key_type() const = 0;
virtual fundamental_type value_type() const = 0;
virtual void insert(ft_value&& key, ft_value&& val) = 0;
}; };
template<typename Tuple> template<typename Getter, typename Setter, fundamental_type FT>
struct mt_helper<0, Tuple> class value_property_impl : public value_property
{ {
typedef typename util::type_at<0, Tuple>::type element_type;
inline static void to_string(std::ostringstream& oss, const Tuple& t) Getter m_get;
{ Setter m_set;
oss << meta_type<element_type>::to_string(t.get<0>()); // T* m_ptr;
if (Tuple::type_list_size > 1) oss << ", ";
} public:
// value_property_impl(T* ptr) : m_ptr(ptr) { }
value_property_impl(Getter g, Setter s) : m_get(g), m_set(s) { }
void set(ft_value&& what)
{
// *m_ptr = std::move(ft_value_cast<FT>(what));
m_set(std::move(ft_value_cast<FT>(what)));
}
void get(ft_value& storage) const
{
// ft_value_cast<FT>(storage) = *m_ptr;
ft_value_cast<FT>(storage) = m_get();
}
fundamental_type type() const
{
return FT;
}
}; };
template<typename... Types> template<class List, fundamental_type FT>
struct meta_type<tuple<Types...>> class list_property_impl : public list_property
{ {
typedef tuple<Types...> tuple_type;
static void serialize(const tuple_type& what, serializer& data_sink) class iterator : public list_property::iterator
{ {
}
static tuple_type deserialize(deserializer& data_source) typedef typename List::const_iterator native_iterator;
{
return ""; native_iterator pos;
} native_iterator end;
static std::string to_string(const tuple_type& what)
{ public:
std::ostringstream oss;
oss << "{ "; iterator(native_iterator bg, native_iterator nd) : pos(bg), end(nd) { }
mt_helper<tuple_type::type_list_size - 1, tuple_type>::to_string(oss, what);
oss << " }"; bool at_end() const { return pos == end; }
return oss.str();
} void next() { ++pos; }
static tuple_type from_string(const std::string& str)
{ ft_value get() const { return *pos; }
return str;
} };
List* m_list;
public:
list_property_impl(List* native_list) : m_list(native_list) { }
size_t size() const { return m_list->size(); }
list_property::iterator* begin() const
{
return new iterator(m_list->begin(), m_list->end());
}
void push_back(ft_value&& what)
{
m_list->push_back(std::move(ft_value_cast<FT>(what)));
}
fundamental_type value_type() const
{
return FT;
}
}; };
template<typename... Types> template<class Map, fundamental_type KeyType, fundamental_type ValueType>
std::string to_string(const tuple<Types...>& what) class map_property_impl : public map_property
{ {
return meta_type<tuple<Types...>>::to_string(what);
class iterator : public map_property::iterator
{
typedef typename Map::const_iterator native_iterator;
native_iterator pos;
native_iterator end;
public:
iterator(native_iterator bg, native_iterator nd) : pos(bg), end(nd) { }
void next() { ++pos; }
bool at_end() const { return pos == end; }
ft_value key() const { return pos->first; }
ft_value value() const { return pos->second; }
};
Map* m_map;
public:
map_property_impl(Map* ptr) : m_map(ptr) { }
size_t size() const
{
return m_map->size();
}
iterator* begin() const
{
return new iterator(m_map->begin(), m_map->end());
}
void insert(ft_value&& k, ft_value&& v)
{
m_map->insert(std::make_pair(
std::move(ft_value_cast<KeyType>(k)),
std::move(ft_value_cast<ValueType>(v))));
}
fundamental_type key_type() const
{
return KeyType;
}
fundamental_type value_type() const
{
return ValueType;
}
};
template<fundamental_type FT, typename Getter, typename Setter>
value_property* as_value_property(Getter getter, Setter setter)
{
return new value_property_impl<Getter, Setter, FT>(getter, setter);
}
using cppa::util::enable_if;
using cppa::util::conjunction;
template<fundamental_type FT, class C, typename Getter, typename Setter>
typename enable_if<conjunction<std::is_member_function_pointer<Getter>,
std::is_member_function_pointer<Setter>>,
value_property*>::type
as_value_property(C* self, Getter getter, Setter setter)
{
typedef cppa::util::callable_trait<Getter> getter_trait;
typedef cppa::util::callable_trait<Setter> setter_trait;
typedef typename getter_trait::result_type getter_result;
typedef typename ftype_to_type<FT>::type setter_arg;
return as_value_property<FT>(
[=]() -> getter_result { return (*self.*getter)(); },
[=](setter_arg&& val) { (*self.*setter)(std::move(val)); });
} }
struct obj_types : util::abstract_type_list template<typename T, fundamental_type FT = type_to_ftype<T>::ftype>
value_property* as_value_property(T* ptr)
{ {
return as_value_property<FT>([ptr]() -> const T& { return *ptr; },
[ptr](T&& val) { *ptr = std::move(val); });
}
template<typename List,
fundamental_type FT = type_to_ftype<typename List::value_type>::ftype>
list_property* as_list_property(List* ptr)
{
return new list_property_impl<List, FT>(ptr);
}
std::size_t m_size; template<typename Map,
const uniform_type_info** m_arr; fundamental_type KT = type_to_ftype<typename Map::key_type>::ftype,
fundamental_type VT = type_to_ftype<typename Map::mapped_type>::ftype>
map_property* as_map_property(Map* ptr)
{
return new map_property_impl<Map, KT, VT>(ptr);
}
struct property_ptr
{
enum flag_type { is_null, is_vp, is_lp, is_mp } m_flag;
union
{
value_property* m_vp;
list_property* m_lp;
map_property* m_mp;
};
void set(value_property* vp)
{
m_flag = is_vp;
m_vp = vp;
}
void set(list_property* lp)
{
m_flag = is_lp;
m_lp = lp;
}
void set(map_property* mp)
{
m_flag = is_mp;
m_mp = mp;
}
void destroy()
{
switch (m_flag)
{
case is_vp: delete m_vp; break;
case is_lp: delete m_lp; break;
case is_mp: delete m_mp; break;
default: break;
}
m_flag = is_null;
}
void move_from(property_ptr& other)
{
m_flag = other.m_flag;
switch (other.m_flag)
{
case is_vp: m_vp = other.m_vp; break;
case is_lp: m_lp = other.m_lp; break;
case is_mp: m_mp = other.m_mp; break;
default: break;
}
other.m_flag = is_null;
}
value_property* get(std::true_type, std::false_type, std::false_type)
{
if (m_flag != is_vp) throw std::bad_cast();
return m_vp;
}
list_property* get(std::false_type, std::true_type, std::false_type)
{
if (m_flag != is_lp) throw std::bad_cast();
return m_lp;
}
map_property* get(std::false_type, std::false_type, std::true_type)
{
if (m_flag != is_mp) throw std::bad_cast();
return m_mp;
}
public: public:
obj_types(const std::vector<intrusive_ptr<object>>& objs) : m_size(objs.size()) property_ptr(value_property* ptr) { set(ptr); }
{
m_arr = new const uniform_type_info*[m_size]; property_ptr(list_property* ptr) { set(ptr); }
for (std::size_t i = 0; i != m_size; ++i)
{ property_ptr(map_property* ptr) { set(ptr); }
m_arr[i] = objs[i]->type();
} property_ptr() : m_flag(is_null) { }
}
property_ptr(property_ptr&& other)
obj_types(const obj_types& other) : m_size(other.size()) {
{ move_from(other);
m_arr = new const uniform_type_info*[m_size]; }
for (std::size_t i = 0; i != m_size; ++i)
{ property_ptr& operator=(property_ptr&& other)
m_arr[i] = other.m_arr[i]; {
} destroy();
} move_from(other);
return *this;
~obj_types() }
{
delete[] m_arr; ~property_ptr()
} {
destroy();
virtual std::size_t size() const { return m_size; } }
virtual abstract_type_list* copy() const property_ptr(const property_ptr&) = delete;
{
return new obj_types(*this); property_ptr& operator=(const property_ptr&) = delete;
}
inline bool is_value_property() const { return m_flag == is_vp; }
virtual const_iterator begin() const
{ inline bool is_list_property() const { return m_flag == is_lp; }
return m_arr;
} inline bool is_map_property() const { return m_flag == is_mp; }
virtual const_iterator end() const inline explicit operator bool() const { return m_flag != is_null; }
{
return m_arr + m_size; inline bool operator==(const std::nullptr_t&)
} {
return m_flag == is_null;
virtual const uniform_type_info* at(std::size_t pos) const }
{
return m_arr[pos]; inline bool operator!=(const std::nullptr_t&)
} {
return m_flag != is_null;
}
template<typename T>
T* as()
{
return get(std::is_same<T, value_property>(),
std::is_same<T, list_property>(),
std::is_same<T, map_property>());
}
}; };
class obj_tuple : public detail::abstract_tuple /**
* @brief
*/
class abstract_object
{ {
obj_types m_types; inline void push_back() { }
std::vector<intrusive_ptr<object>> m_obj;
template<typename T0, typename... Tn>
void push_back(T0* ptr0, Tn*... ptrs)
{
static_assert( std::is_same<T0, value_property>::value
|| std::is_same<T0, list_property>::value
|| std::is_same<T0, map_property>::value,
"invalid type");
m_properties.push_back(property_ptr(ptr0));
push_back(ptrs...);
}
public: public:
obj_tuple(const std::vector<intrusive_ptr<object>>& objs) : m_types(objs) typedef std::vector<property_ptr> pptr_vector;
{
for (std::size_t i = 0; i != objs.size(); ++i)
{
m_obj.push_back(objs[i]->copy());
}
}
virtual void* mutable_at(std::size_t pos)
{
return m_obj[pos]->mutable_value();
}
virtual std::size_t size() const
{
return m_obj.size();
}
virtual abstract_tuple* copy() const
{
return new obj_tuple(m_obj);
}
virtual const void* at(std::size_t pos) const
{
return m_obj[pos]->value();
}
virtual const uniform_type_info* utype_at(std::size_t pos) const
{
return m_obj[pos]->type();
}
virtual const util::abstract_type_list& types() const
{
return m_types;
}
virtual bool equal_to(const abstract_tuple&) const
{
return false;
}
virtual void serialize(serializer& s) const
{
s << static_cast<std::uint8_t>(m_obj.size());
for (std::size_t i = 0; i < m_obj.size(); ++i)
{
decltype(m_obj[i]) o = m_obj[i];
s << o->type()->name();
o->serialize(s);
}
}
}; abstract_object(pptr_vector&& pvec) : m_properties(std::move(pvec)) { }
template<typename T0, typename... Tn>
abstract_object(T0* ptr0, Tn*... ptrs)
{
push_back(ptr0, ptrs...);
}
abstract_object() = default;
abstract_object(abstract_object&&) = default;
abstract_object& operator=(abstract_object&&) = default;
abstract_object(const abstract_object&) = delete;
abstract_object& operator=(const abstract_object&) = delete;
size_t properties()
{
return m_properties.size();
}
struct io_buf : sink, source property_ptr& property(size_t pos)
{ {
return m_properties[pos];
char* m_buf; }
std::size_t m_size;
std::size_t m_rd_pos; private:
std::size_t m_wr_pos;
pptr_vector m_properties;
io_buf() : m_buf(new char[2048]), m_size(2048), m_rd_pos(0), m_wr_pos(0) { }
~io_buf() { delete[] m_buf; }
virtual std::size_t read_some(std::size_t buf_size, void* buf)
{
if ((m_rd_pos + buf_size) <= m_size)
{
memcpy(buf, m_buf + m_rd_pos, buf_size);
m_rd_pos += buf_size;
return buf_size;
}
else
{
auto left = m_size - m_rd_pos;
return (left > 0) ? read_some(left, buf) : 0;
}
}
virtual void read(std::size_t buf_size, void* buf)
{
if (read_some(buf_size, buf) < buf_size)
{
throw std::ios_base::failure("Not enough bytes available");
}
}
virtual void write(std::size_t buf_size, const void* buf)
{
if (m_wr_pos + buf_size > m_size)
{
throw std::ios_base::failure("Buffer full");
}
memcpy(m_buf + m_wr_pos, buf, buf_size);
m_wr_pos += buf_size;
}
virtual void flush()
{
}
}; };
template<std::size_t Pos, std::size_t Size, typename Tuple> class sink
struct serialize_tuple_at
{ {
inline static void _(serializer& s, const Tuple& t)
{ public:
s << uniform_typeid<typename type_at<Pos, Tuple>::type>()->name()
<< t.get<Pos>(); virtual void write(abstract_object&) = 0;
serialize_tuple_at<Pos + 1, Size, Tuple>::_(s, t);
}
}; };
template<std::size_t Size, typename Tuple> struct xml_sink_helper
struct serialize_tuple_at<Size, Size, Tuple>
{ {
inline static void _(serializer&, const Tuple&) { } std::ostringstream& ostr;
const std::string& indent;
xml_sink_helper(std::ostringstream& mostr, const std::string& idn) : ostr(mostr), indent(idn) { }
template<typename T>
void operator()(const T& what)
{
static const fundamental_type ftype = type_to_ftype<T>::ftype;
ostr << indent
<< "<" << fundamental_type_name(ftype) << ">"
<< what
<< "</" << fundamental_type_name(ftype) << ">\n";
}
void operator()(const std::u16string&) { }
void operator()(const std::u32string&) { }
}; };
template<typename... Types> class xml_sink
serializer& operator<<(serializer& s, const tuple<Types...>& t)
{ {
auto tsize = static_cast<std::uint8_t>(tuple<Types...>::type_list_size);
s << tsize;
serialize_tuple_at<0, tuple<Types...>::type_list_size, tuple<Types...>>::_(s, t);
return s;
}
serializer& operator<<(serializer& s, const untyped_tuple& ut) static const char br = '\n';
std::ostringstream ostr;
void append(const std::string& indentation, const ft_value& what)
{
what.apply(xml_sink_helper(ostr, indentation));
}
public:
void write(abstract_object& obj)
{
ostr << "<object>" << br;
for (size_t i = 0; i < obj.properties(); ++i)
{
property_ptr& pptr = obj.property(i);
if (pptr.is_value_property())
{
auto vp = pptr.as<value_property>();
ft_value val(vp->type());
vp->get(val);
append(" ", val);
}
}
ostr << "</object>";
}
std::string str() const { return ostr.str(); }
};
class source
{ {
ut.vals()->serialize(s);
return s;
}
deserializer& operator>>(deserializer& d, untyped_tuple& ut) public:
{
std::uint8_t tsize;
d >> tsize;
std::vector<intrusive_ptr<object>> obj_vec;
for (auto i = 0; i < tsize; ++i)
{
std::string type_name;
d >> type_name;
object* obj = uniform_type_info::by_uniform_name(type_name)->create();
obj->deserialize(d);
obj_vec.push_back(obj);
}
cow_ptr<detail::abstract_tuple> vals(new obj_tuple(obj_vec));
ut = untyped_tuple(vals);
return d;
}
std::size_t test__serialization() virtual void read(abstract_object&) = 0;
};
struct point_struct
{ {
std::uint32_t x, y, z;
};
CPPA_TEST(test__serialization); class point_class
{
std::string str = "Hello World";
// CPPA_CHECK_EQUAL(to_string(make_tuple(str)),
// "{ \"Hello World\" }");
// CPPA_CHECK_EQUAL(to_string(make_tuple(str, 42)),
// "{ \"Hello World\", 42 }");
char v0 = 0x11;
short v1 = 0x1122;
int v2 = 0x11223344;
long v3 = 0x1122334455667788;
CPPA_CHECK_EQUAL(detail::swap_bytes(v0), 0x11);
CPPA_CHECK_EQUAL(detail::swap_bytes(v1), 0x2211);
CPPA_CHECK_EQUAL(detail::swap_bytes(v2), 0x44332211);
CPPA_CHECK_EQUAL(detail::swap_bytes(v3), 0x8877665544332211);
std::vector<intrusive_ptr<object>> obj_vec;
obj_vec.reserve(2);
obj_vec.push_back(uniform_typeid<std::string>()->create());
obj_vec.push_back(uniform_typeid<int>()->create());
cow_ptr<detail::abstract_tuple> vals(new obj_tuple(obj_vec));
untyped_tuple ut0(vals);
intrusive_ptr<io_buf> io0(new io_buf);
auto t0 = make_tuple(42, "Hello World");
{
serializer s(io0);
s << t0;
}
{
deserializer d(io0);
untyped_tuple ut1;
d >> ut1;
std::vector<std::size_t> mappings;
bool does_match = match<int, any_type*, std::string>(ut1, mappings);
CPPA_CHECK_EQUAL(does_match, true);
if (does_match)
{
tuple_view<int, std::string> tv(ut1.vals(), std::move(mappings));
CPPA_CHECK_EQUAL(tv.get<0>(), 42);
CPPA_CHECK_EQUAL(tv.get<1>(), "Hello World");
}
}
untyped_tuple ut2 = make_tuple("a", "b", 1, 2, 3);
intrusive_ptr<io_buf> io1(new io_buf);
{
serializer s(io1);
s << ut2;
}
{
deserializer d(io1);
untyped_tuple ut3;
d >> ut3;
std::vector<std::size_t> mappings;
bool does_match = match<std::string, std::string, int, int, int>(ut3, mappings);
CPPA_CHECK_EQUAL(does_match, true);
if (does_match)
{
tuple_view<std::string, std::string, int, int, int> tv(ut3.vals(), std::move(mappings));
CPPA_CHECK_EQUAL(tv.get<0>(), "a");
CPPA_CHECK_EQUAL(tv.get<1>(), "b");
CPPA_CHECK_EQUAL(tv.get<2>(), 1);
CPPA_CHECK_EQUAL(tv.get<3>(), 2);
CPPA_CHECK_EQUAL(tv.get<4>(), 3);
}
}
{
std::vector<std::size_t> mappings;
bool does_match = match<std::string, int>(ut0, mappings);
CPPA_CHECK_EQUAL(does_match, true);
if (does_match)
{
tuple_view<std::string, int> tv0(ut0.vals(), std::move(mappings));
CPPA_CHECK_EQUAL(tv0.get<0>(), "");
CPPA_CHECK_EQUAL(tv0.get<1>(), 0);
tv0.get_ref<0>() = "Hello World";
tv0.get_ref<1>() = 42;
CPPA_CHECK_EQUAL(tv0.get<0>(), "Hello World");
CPPA_CHECK_EQUAL(tv0.get<1>(), 42);
}
}
auto t1 = make_tuple("a", "b", 1, 2, 3);
auto t2 = make_tuple("a", "b", "c", 23.f, 1, 11, 2, 3);
std::vector<intrusive_ptr<io_buf>> io_bufs = {
new io_buf, new io_buf, new io_buf, new io_buf
};
{
serializer s(io_bufs[0]);
s << t1;
}
{
serializer s1(io_bufs[1]);
auto tmp1 = get_view<std::string, std::string, any_type*, int, any_type, int, int>(t2);
s1 << tmp1;
untyped_tuple tmp2 = tmp1;
serializer s2(io_bufs[2]);
s2 << tmp2;
}
{
serializer s(io_bufs[3]);
untyped_tuple tmp = t1;
s << tmp;
}
for (auto i = 0; i < 4; ++i)
{
deserializer d(io_bufs[i]);
untyped_tuple x;
d >> x;
std::vector<std::size_t> mappings;
bool does_match = match<std::string, std::string, int, int, int>(x, mappings);
CPPA_CHECK_EQUAL(does_match, true);
if (does_match)
{
tuple_view<std::string, std::string, int, int, int> tv(x.vals(), std::move(mappings));
CPPA_CHECK_EQUAL(tv.get<0>(), "a");
CPPA_CHECK_EQUAL(tv.get<1>(), "b");
CPPA_CHECK_EQUAL(tv.get<2>(), 1);
CPPA_CHECK_EQUAL(tv.get<3>(), 2);
CPPA_CHECK_EQUAL(tv.get<4>(), 3);
}
}
return CPPA_TEST_RESULT;
} std::uint32_t m_x, m_y, m_z;
*/ public:
std::size_t test__serialization() point_class() : m_x(0), m_y(0), m_z(0) { }
point_class(std::uint32_t mx, std::uint32_t my, std::uint32_t mz)
: m_x(mx), m_y(my), m_z(mz)
{
}
std::uint32_t x() const { return m_x; }
std::uint32_t y() const { return m_y; }
std::uint32_t z() const { return m_z; }
void set_x(std::uint32_t value) { m_x = value; }
void set_y(std::uint32_t value) { m_y = value; }
void set_z(std::uint32_t value) { m_z = value; }
};
void plot(value_property* vp)
{ {
ft_value v(vp->type());
vp->get(v);
switch (v.type())
{
case ft_uint32: cout << ft_value_cast<ft_uint32>(v) << " "; break;
default: break;
}
}
CPPA_TEST(test__serialization); void plot(property_ptr& pptr)
{
if (pptr.is_value_property())
{
plot(pptr.as<value_property>());
}
}
CPPA_CHECK_EQUAL(true, true); void plot(abstract_object& what, const std::string& what_name)
{
cout << what_name << " (" << what.properties() << " properties): ";
for (size_t i = 0; i < what.properties(); ++i)
{
plot(what.property(i));
}
cout << endl;
}
std::size_t test__serialization()
{
return CPPA_TEST_RESULT; CPPA_TEST(test__serialization);
{
ft_value v1(42);
ft_value v2(42);
CPPA_CHECK_EQUAL(v1, v2);
CPPA_CHECK_EQUAL(v1, 42);
CPPA_CHECK_EQUAL(42, v2);
CPPA_CHECK(v2 != static_cast<std::int8_t>(42));
}
auto manipulate_point = [&](abstract_object& pt) {
CPPA_CHECK_EQUAL(pt.properties(), 3);
if (pt.properties() == 3)
{
for (size_t i = 0; i < 3; ++i)
{
property_ptr& pptr = pt.property(i);
bool is_value_property = pptr.is_value_property();
CPPA_CHECK(is_value_property);
if (is_value_property)
{
CPPA_CHECK_EQUAL(pptr.as<value_property>()->type(),
ft_uint32);
if (i == 1)
{
auto vptr = pptr.as<value_property>();
// value must be 2
ft_value val(ft_uint32);
vptr->get(val);
CPPA_CHECK_EQUAL(ft_value_cast<ft_uint32>(val), 2);
vptr->set(ft_value(static_cast<std::uint32_t>(22)));
vptr->get(val);
CPPA_CHECK_EQUAL(ft_value_cast<ft_uint32>(val), 22);
}
}
}
}
};
// test as_value_property with direct member access
{
point_struct pt = { 1, 2, 3 };
abstract_object abstract_pt { as_value_property(&pt.x),
as_value_property(&pt.y),
as_value_property(&pt.z) };
manipulate_point(abstract_pt);
CPPA_CHECK_EQUAL(pt.x, 1);
CPPA_CHECK_EQUAL(pt.y, 22);
CPPA_CHECK_EQUAL(pt.z, 3);
xml_sink xs;
xs.write(abstract_pt);
cout << "XML:" << endl << xs.str() << endl;
}
// test as_value_property with direct getter / setter implementations
{
point_class pt = { 1, 2, 4 };
abstract_object abstract_pt = {
as_value_property<ft_uint32>(&pt, &point_class::x, &point_class::set_x),
as_value_property<ft_uint32>(&pt, &point_class::y, &point_class::set_y),
as_value_property<ft_uint32>(&pt, &point_class::z, &point_class::set_z)
};
manipulate_point(abstract_pt);
CPPA_CHECK_EQUAL(pt.x(), 1);
CPPA_CHECK_EQUAL(pt.y(), 22);
CPPA_CHECK_EQUAL(pt.z(), 4);
}
{
std::string str = "Hello World";
std::unique_ptr<value_property> p(as_value_property(&str));
p->set(std::string("foobar"));
CPPA_CHECK_EQUAL(str, "foobar");
}
{
std::vector<std::int32_t> ints;
std::unique_ptr<list_property> p(as_list_property(&ints));
p->push_back(static_cast<std::int32_t>(1));
p->push_back(static_cast<std::int32_t>(2));
p->push_back(static_cast<std::int32_t>(3));
for (std::unique_ptr<list_property::iterator> i(p->begin()); !i->at_end(); i->next())
{
cout << ft_value_cast<ft_int32>(i->get()) << " ";
}
cout << endl;
CPPA_CHECK_EQUAL(ints.size(), 3);
CPPA_CHECK_EQUAL(ints, (std::vector<std::int32_t>({1, 2, 3})));
}
{
std::map<std::int32_t, std::string> strings;
std::unique_ptr<map_property> p(as_map_property(&strings));
p->insert(static_cast<std::int32_t>(2), std::string("two"));
p->insert(static_cast<std::int32_t>(1), std::string("one"));
p->insert(static_cast<std::int32_t>(4), std::string("four"));
std::map<std::int32_t, std::string> verification_map = {
{ 1, "one" },
{ 2, "two" },
{ 4, "four" }
};
CPPA_CHECK_EQUAL(strings.size(), 3);
CPPA_CHECK_EQUAL(strings, verification_map);
// also check equality by iterators
if (strings.size() == verification_map.size())
{
auto siter = strings.begin();
auto send = strings.end();
std::unique_ptr<map_property::iterator> viter(p->begin());
while (siter != send)
{
CPPA_CHECK_EQUAL(ft_value_cast<ft_int32>(viter->key()),
siter->first);
CPPA_CHECK_EQUAL(ft_value_cast<ft_u8string>(viter->value()),
siter->second);
viter->next();
++siter;
}
}
}
ft_value v1("Hello World");
auto plot_objects = [] (const std::vector<cppa::object>& objs)
{
cout << "{ ";
bool first = true;
for (const cppa::object& o : objs)
{
if (first) first = false;
else cout << ", ";
cout << o.type().name() << "(";
if (o.type() == typeid(std::string))
cout << "\"" << o.to_string() << "\"";
else
cout << o.to_string();
cout << ")";
}
cout << " }" << endl;
};
plot_objects({
cppa::uniform_typeid<int>()->create(),
cppa::uniform_typeid<std::string>()->create()
});
return CPPA_TEST_RESULT;
} }
...@@ -60,7 +60,6 @@ std::size_t test__type_list() ...@@ -60,7 +60,6 @@ std::size_t test__type_list()
++i; ++i;
CPPA_CHECK((i == ifc.end())); CPPA_CHECK((i == ifc.end()));
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
...@@ -25,9 +25,6 @@ ...@@ -25,9 +25,6 @@
using std::cout; using std::cout;
using std::endl; using std::endl;
using cppa::object;
using cppa::uniform_type_info;
namespace { namespace {
struct foo struct foo
...@@ -43,14 +40,16 @@ bool operator==(const foo& lhs, const foo& rhs) ...@@ -43,14 +40,16 @@ bool operator==(const foo& lhs, const foo& rhs)
} // namespace <anonymous> } // namespace <anonymous>
using namespace cppa;
namespace { namespace {
static bool unused1 = static bool unused1 =
cppa::uniform_type_info::announce<foo>( uniform_type_info::announce<foo>(
[] (cppa::serializer& s, const foo& f) { [] (serializer& s, const foo& f) {
s << f.value; s << f.value;
}, },
[] (cppa::deserializer& d, foo& f) { [] (deserializer& d, foo& f) {
d >> f.value; d >> f.value;
}, },
[] (const foo& f) -> std::string { [] (const foo& f) -> std::string {
...@@ -65,9 +64,9 @@ static bool unused1 = ...@@ -65,9 +64,9 @@ static bool unused1 =
return new foo(tmp); return new foo(tmp);
} }
); );
bool unused2 = false;// = cppa::uniform_type_info::announce(typeid(foo), new uti_impl<foo>); bool unused2 = false;// = uniform_type_info::announce(typeid(foo), new uti_impl<foo>);
bool unused3 = false;//= cppa::uniform_type_info::announce(typeid(foo), new uti_impl<foo>); bool unused3 = false;//= uniform_type_info::announce(typeid(foo), new uti_impl<foo>);
bool unused4 = false;//= cppa::uniform_type_info::announce(typeid(foo), new uti_impl<foo>); bool unused4 = false;//= uniform_type_info::announce(typeid(foo), new uti_impl<foo>);
} // namespace <anonymous> } // namespace <anonymous>
...@@ -77,18 +76,21 @@ std::size_t test__uniform_type() ...@@ -77,18 +76,21 @@ std::size_t test__uniform_type()
{ {
//bar.create_object(); //bar.create_object();
object obj1 = cppa::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);
} }
{ {
object wstr_obj1 = cppa::uniform_typeid<std::wstring>()->create(); object wstr_obj1 = uniform_typeid<std::wstring>()->create();
cppa::object_cast<std::wstring>(wstr_obj1) = L"hello wstring!"; object_cast<std::wstring&>(wstr_obj1) = L"hello wstring!";
object wstr_obj2 = cppa::uniform_typeid<std::wstring>()->from_string("hello wstring!"); object wstr_obj2 = uniform_typeid<std::wstring>()->from_string("hello wstring!");
CPPA_CHECK_EQUAL(wstr_obj1, wstr_obj2); 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 // couldn't be converted to ASCII
cppa::object_cast<std::wstring>(wstr_obj1) = L"hello wstring\x05D4"; object_cast<std::wstring&>(wstr_obj1) = L"hello wstring\x05D4";
std::string narrowed = wstr_obj1.to_string(); std::string narrowed = wstr_obj1.to_string();
CPPA_CHECK_EQUAL(narrowed, "hello wstring?"); CPPA_CHECK_EQUAL(narrowed, "hello wstring?");
} }
...@@ -102,15 +104,15 @@ std::size_t test__uniform_type() ...@@ -102,15 +104,15 @@ std::size_t test__uniform_type()
// test foo_object implementation // test foo_object implementation
/* /*
obj_ptr o = cppa::uniform_typeid<foo>()->create(); obj_ptr o = uniform_typeid<foo>()->create();
o->from_string("123"); o->from_string("123");
CPPA_CHECK_EQUAL(o->to_string(), "123"); CPPA_CHECK_EQUAL(o->to_string(), "123");
int val = reinterpret_cast<const foo*>(o->value())->value; int val = reinterpret_cast<const foo*>(o->value())->value;
CPPA_CHECK_EQUAL(val, 123); CPPA_CHECK_EQUAL(val, 123);
*/ */
// these types (and only those) are present if the uniform_type_info // these types (and only those) are present if
// 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
...@@ -118,7 +120,7 @@ std::size_t test__uniform_type() ...@@ -118,7 +120,7 @@ std::size_t test__uniform_type()
"@u8", "@u16", "@u32", "@u64", // unsigned integer names "@u8", "@u16", "@u32", "@u64", // unsigned integer names
"@str", "@wstr", // strings "@str", "@wstr", // strings
"float", "double", // floating points "float", "double", // floating points
"@0", // cppa::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>"
...@@ -134,8 +136,8 @@ std::size_t test__uniform_type() ...@@ -134,8 +136,8 @@ std::size_t test__uniform_type()
std::set<std::string> found; std::set<std::string> found;
// fetch all available type names // fetch all available type names
auto types = cppa::uniform_type_info::instances(); auto types = uniform_type_info::instances();
for (cppa::uniform_type_info* tinfo : types) for (uniform_type_info* tinfo : types)
{ {
found.insert(tinfo->name()); found.insert(tinfo->name());
} }
...@@ -145,7 +147,23 @@ std::size_t test__uniform_type() ...@@ -145,7 +147,23 @@ std::size_t test__uniform_type()
if (expected.size() == found.size()) if (expected.size() == found.size())
{ {
CPPA_CHECK((std::equal(found.begin(), found.end(), expected.begin()))); bool expected_equals_found = std::equal(found.begin(),
found.end(),
expected.begin());
CPPA_CHECK(expected_equals_found);
if (!expected_equals_found)
{
cout << "found:" << endl;
for (const std::string& tname : found)
{
cout << " - " << tname << endl;
}
cout << "expected: " << 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