Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
123e61f7
Commit
123e61f7
authored
Apr 29, 2011
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
serialization tests
parent
cc1a1fc6
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1377 additions
and
1004 deletions
+1377
-1004
.gitignore
.gitignore
+1
-0
cppa.creator.user
cppa.creator.user
+7
-5
cppa.files
cppa.files
+3
-0
cppa/uniform_type_info.hpp
cppa/uniform_type_info.hpp
+248
-248
cppa/util/disable_if.hpp
cppa/util/disable_if.hpp
+24
-0
cppa/util/enable_if.hpp
cppa/util/enable_if.hpp
+4
-2
cppa/util/if_else_type.hpp
cppa/util/if_else_type.hpp
+27
-0
cppa/util/wrapped_type.hpp
cppa/util/wrapped_type.hpp
+11
-0
unit_testing/test__serialization.cpp
unit_testing/test__serialization.cpp
+1052
-749
No files found.
.gitignore
View file @
123e61f7
...
@@ -6,5 +6,6 @@ test
...
@@ -6,5 +6,6 @@ test
*.png
*.png
*.dat
*.dat
queue_test
queue_test
cppa.creator.user.1.3
8threads
8threads
4threads
4threads
cppa.creator.user
View file @
123e61f7
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
<qtcreator>
<qtcreator>
<data>
<data>
<variable>
GenericProjectManager.GenericProject.Toolchain
</variable>
<variable>
GenericProjectManager.GenericProject.Toolchain
</variable>
<value
type=
"QString"
></value>
<value
type=
"QString"
>
ProjectExplorer.ToolChain.Gcc:/opt/local/bin/g++-mp-4.6.x86-macos-generic-mach_o-64bit.
</value>
</data>
</data>
<data>
<data>
<variable>
ProjectExplorer.Project.ActiveTarget
</variable>
<variable>
ProjectExplorer.Project.ActiveTarget
</variable>
...
@@ -43,7 +43,7 @@
...
@@ -43,7 +43,7 @@
<value
key=
"ProjectExplorer.Target.ActiveRunConfiguration"
type=
"int"
>
0
</value>
<value
key=
"ProjectExplorer.Target.ActiveRunConfiguration"
type=
"int"
>
0
</value>
<valuemap
key=
"ProjectExplorer.Target.BuildConfiguration.0"
type=
"QVariantMap"
>
<valuemap
key=
"ProjectExplorer.Target.BuildConfiguration.0"
type=
"QVariantMap"
>
<value
key=
"GenericProjectManager.GenericBuildConfiguration.BuildDirectory"
type=
"QString"
>
/Users/neverlord/libcppa
</value>
<value
key=
"GenericProjectManager.GenericBuildConfiguration.BuildDirectory"
type=
"QString"
>
/Users/neverlord/libcppa
</value>
<value
key=
"ProjectExplorer.BuildCOnfiguration.ToolChain"
type=
"QString"
>
INVALID
</value>
<value
key=
"ProjectExplorer.BuildCOnfiguration.ToolChain"
type=
"QString"
>
ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-macos-generic-mach_o-64bit.
</value>
<valuemap
key=
"ProjectExplorer.BuildConfiguration.BuildStepList.0"
type=
"QVariantMap"
>
<valuemap
key=
"ProjectExplorer.BuildConfiguration.BuildStepList.0"
type=
"QVariantMap"
>
<valuemap
key=
"ProjectExplorer.BuildStepList.Step.0"
type=
"QVariantMap"
>
<valuemap
key=
"ProjectExplorer.BuildStepList.Step.0"
type=
"QVariantMap"
>
<valuelist
key=
"GenericProjectManager.GenericMakeStep.BuildTargets"
type=
"QVariantList"
>
<valuelist
key=
"GenericProjectManager.GenericMakeStep.BuildTargets"
type=
"QVariantList"
>
...
@@ -77,7 +77,7 @@
...
@@ -77,7 +77,7 @@
<valuemap
key=
"ProjectExplorer.Target.DeployConfiguration.0"
type=
"QVariantMap"
>
<valuemap
key=
"ProjectExplorer.Target.DeployConfiguration.0"
type=
"QVariantMap"
>
<valuemap
key=
"ProjectExplorer.BuildConfiguration.BuildStepList.0"
type=
"QVariantMap"
>
<valuemap
key=
"ProjectExplorer.BuildConfiguration.BuildStepList.0"
type=
"QVariantMap"
>
<value
key=
"ProjectExplorer.BuildStepList.StepsCount"
type=
"int"
>
0
</value>
<value
key=
"ProjectExplorer.BuildStepList.StepsCount"
type=
"int"
>
0
</value>
<value
key=
"ProjectExplorer.ProjectConfiguration.DefaultDisplayName"
type=
"QString"
>
Deploy
ment
</value>
<value
key=
"ProjectExplorer.ProjectConfiguration.DefaultDisplayName"
type=
"QString"
>
Deploy
</value>
<value
key=
"ProjectExplorer.ProjectConfiguration.DisplayName"
type=
"QString"
>
Deploy
</value>
<value
key=
"ProjectExplorer.ProjectConfiguration.DisplayName"
type=
"QString"
>
Deploy
</value>
<value
key=
"ProjectExplorer.ProjectConfiguration.Id"
type=
"QString"
>
ProjectExplorer.BuildSteps.Deploy
</value>
<value
key=
"ProjectExplorer.ProjectConfiguration.Id"
type=
"QString"
>
ProjectExplorer.BuildSteps.Deploy
</value>
</valuemap>
</valuemap>
...
@@ -115,7 +115,9 @@
...
@@ -115,7 +115,9 @@
<value
key=
"ProjectExplorer.CustomExecutableRunConfiguration.BaseEnvironmentBase"
type=
"int"
>
2
</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.Executable"
type=
"QString"
>
/Users/neverlord/libcppa/test
</value>
<value
key=
"ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal"
type=
"bool"
>
false
</value>
<value
key=
"ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal"
type=
"bool"
>
false
</value>
<valuelist
key=
"ProjectExplorer.CustomExecutableRunConfiguration.UserEnvironmentChanges"
type=
"QVariantList"
/>
<valuelist
key=
"ProjectExplorer.CustomExecutableRunConfiguration.UserEnvironmentChanges"
type=
"QVariantList"
>
<value
type=
"QString"
>
DYLD_LIBRARY_PATH=/Users/neverlord/libcppa
</value>
</valuelist>
<value
key=
"ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory"
type=
"QString"
>
%{buildDir}
</value>
<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.DefaultDisplayName"
type=
"QString"
>
Führe /Users/neverlord/libcppa/test aus
</value>
<value
key=
"ProjectExplorer.ProjectConfiguration.DisplayName"
type=
"QString"
>
test
</value>
<value
key=
"ProjectExplorer.ProjectConfiguration.DisplayName"
type=
"QString"
>
test
</value>
...
@@ -133,7 +135,7 @@
...
@@ -133,7 +135,7 @@
</data>
</data>
<data>
<data>
<variable>
ProjectExplorer.Project.Updater.EnvironmentId
</variable>
<variable>
ProjectExplorer.Project.Updater.EnvironmentId
</variable>
<value
type=
"QString"
>
{
349f52bc-ac64-4a14-898f-d44d989b22a2
}
</value>
<value
type=
"QString"
>
{
07fcd197-092d-45a0-8500-3be614e6ae31
}
</value>
</data>
</data>
<data>
<data>
<variable>
ProjectExplorer.Project.Updater.FileVersion
</variable>
<variable>
ProjectExplorer.Project.Updater.FileVersion
</variable>
...
...
cppa.files
View file @
123e61f7
...
@@ -118,3 +118,6 @@ src/to_uniform_name.cpp
...
@@ -118,3 +118,6 @@ src/to_uniform_name.cpp
cppa/detail/default_uniform_type_info_impl.hpp
cppa/detail/default_uniform_type_info_impl.hpp
src/object.cpp
src/object.cpp
cppa/util/comparable.hpp
cppa/util/comparable.hpp
cppa/util/disable_if.hpp
cppa/util/if_else_type.hpp
cppa/util/wrapped_type.hpp
cppa/uniform_type_info.hpp
View file @
123e61f7
...
@@ -47,311 +47,311 @@ uniform_type_info* uniform_typeid(const std::type_info& tinfo);
...
@@ -47,311 +47,311 @@ uniform_type_info* uniform_typeid(const std::type_info& tinfo);
class
uniform_type_info
:
cppa
::
util
::
comparable
<
uniform_type_info
>
class
uniform_type_info
:
cppa
::
util
::
comparable
<
uniform_type_info
>
{
{
friend
class
object
;
friend
class
object
;
// needs access to by_type_info()
// needs access to by_type_info()
template
<
typename
T
>
template
<
typename
T
>
friend
uniform_type_info
*
uniform_typeid
();
friend
uniform_type_info
*
uniform_typeid
();
friend
uniform_type_info
*
uniform_typeid
(
const
std
::
type_info
&
);
friend
uniform_type_info
*
uniform_typeid
(
const
std
::
type_info
&
);
public:
public:
class
identifier
:
cppa
::
util
::
comparable
<
identifier
>
class
identifier
:
cppa
::
util
::
comparable
<
identifier
>
{
{
friend
class
uniform_type_info
;
friend
class
uniform_type_info
;
int
m_value
;
int
m_value
;
identifier
(
int
val
)
:
m_value
(
val
)
{
}
identifier
(
int
val
)
:
m_value
(
val
)
{
}
// enable copy and move constructors
// enable copy and move constructors
identifier
(
identifier
&&
)
=
default
;
identifier
(
identifier
&&
)
=
default
;
identifier
(
const
identifier
&
)
=
default
;
identifier
(
const
identifier
&
)
=
default
;
// disable assignment operators
// disable assignment operators
identifier
&
operator
=
(
identifier
&&
)
=
delete
;
identifier
&
operator
=
(
identifier
&&
)
=
delete
;
identifier
&
operator
=
(
const
identifier
&
)
=
delete
;
identifier
&
operator
=
(
const
identifier
&
)
=
delete
;
public:
public:
// needed by cppa::detail::comparable<identifier>
// needed by cppa::detail::comparable<identifier>
inline
int
compare
(
const
identifier
&
other
)
const
inline
int
compare
(
const
identifier
&
other
)
const
{
{
return
m_value
-
other
.
m_value
;
return
m_value
-
other
.
m_value
;
}
}
};
};
private:
private:
// unique identifier
// unique identifier
identifier
m_id
;
identifier
m_id
;
// uniform type name
// uniform type name
std
::
string
m_name
;
std
::
string
m_name
;
// disable copy and move constructors
// disable copy and move constructors
uniform_type_info
(
uniform_type_info
&&
)
=
delete
;
uniform_type_info
(
uniform_type_info
&&
)
=
delete
;
uniform_type_info
(
const
uniform_type_info
&
)
=
delete
;
uniform_type_info
(
const
uniform_type_info
&
)
=
delete
;
// disable assignment operators
// disable assignment operators
uniform_type_info
&
operator
=
(
uniform_type_info
&&
)
=
delete
;
uniform_type_info
&
operator
=
(
uniform_type_info
&&
)
=
delete
;
uniform_type_info
&
operator
=
(
const
uniform_type_info
&
)
=
delete
;
uniform_type_info
&
operator
=
(
const
uniform_type_info
&
)
=
delete
;
static
uniform_type_info
*
by_type_info
(
const
std
::
type_info
&
tinfo
);
static
uniform_type_info
*
by_type_info
(
const
std
::
type_info
&
tinfo
);
protected:
protected:
explicit
uniform_type_info
(
const
std
::
type_info
&
tinfo
);
explicit
uniform_type_info
(
const
std
::
type_info
&
tinfo
);
public:
public:
/**
/**
* @brief Get instances by its
uniform name.
* @brief Get instance by
uniform name.
* @param uniform_name The libCPPA internal name for a type.
* @param uniform_name The libCPPA internal name for a type.
* @return The instance associated to @p uniform_name.
* @return The instance associated to @p uniform_name.
*/
*/
static
uniform_type_info
*
by_uniform_name
(
const
std
::
string
&
uniform_name
);
static
uniform_type_info
*
by_uniform_name
(
const
std
::
string
&
uniform_name
);
/**
/**
* @brief Get all instances.
* @brief Get all instances.
* @return A vector with all known (announced) instances.
* @return A vector with all known (announced) instances.
*/
*/
static
std
::
vector
<
uniform_type_info
*>
instances
();
static
std
::
vector
<
uniform_type_info
*>
instances
();
virtual
~
uniform_type_info
();
virtual
~
uniform_type_info
();
/**
/**
* @brief Get the internal libCPPA name for this type.
* @brief Get the internal libCPPA name for this type.
* @return A string describing the libCPPA internal type name.
* @return A string describing the libCPPA internal type name.
*/
*/
inline
const
std
::
string
&
name
()
const
{
return
m_name
;
}
inline
const
std
::
string
&
name
()
const
{
return
m_name
;
}
/**
/**
* @brief Get the unique identifier of this instance.
* @brief Get the unique identifier of this instance.
* @return The unique identifier of this instance.
* @return The unique identifier of this instance.
*/
*/
inline
const
identifier
&
id
()
const
{
return
m_id
;
}
inline
const
identifier
&
id
()
const
{
return
m_id
;
}
// needed by cppa::detail::comparable<uniform_type_info>
// needed by cppa::detail::comparable<uniform_type_info>
inline
int
compare
(
const
uniform_type_info
&
other
)
const
inline
int
compare
(
const
uniform_type_info
&
other
)
const
{
{
return
id
().
compare
(
other
.
id
());
return
id
().
compare
(
other
.
id
());
}
}
/**
/**
* @brief Add a new type mapping to the libCPPA internal type system.
* @brief Add a new type mapping to the libCPPA internal type system.
* @return <code>true</code> if @p uniform_type was added as known
* @return <code>true</code> if @p uniform_type was added as known
* instance (mapped to @p plain_type); otherwise <code>false</code>
* instance (mapped to @p plain_type); otherwise @c false
* is returned and @p uniform_type was deleted.
* is returned and @p uniform_type was deleted.
*/
*/
static
bool
announce
(
const
std
::
type_info
&
plain_type
,
static
bool
announce
(
const
std
::
type_info
&
plain_type
,
uniform_type_info
*
uniform_type
);
uniform_type_info
*
uniform_type
);
/**
/**
* auto concept value_type<typename T>
* auto concept value_type<typename T>
* {
* {
* T();
* T();
* T(const T&);
* T(const T&);
* bool operator==(const T&, const T&);
* bool operator==(const T&, const T&);
* }
* }
*/
*/
template
<
typename
T
,
template
<
typename
T
,
class
SerializeFun
,
class
DeserializeFun
,
class
SerializeFun
,
class
DeserializeFun
,
class
ToStringFun
,
class
FromStringFun
>
class
ToStringFun
,
class
FromStringFun
>
static
bool
announce
(
const
SerializeFun
&
sf
,
const
DeserializeFun
&
df
,
static
bool
announce
(
const
SerializeFun
&
sf
,
const
DeserializeFun
&
df
,
const
ToStringFun
&
ts
,
const
FromStringFun
&
fs
);
const
ToStringFun
&
ts
,
const
FromStringFun
&
fs
);
/**
/**
* @brief Create an object of this type.
* @brief Create an object of this type.
*/
*/
virtual
object
create
()
const
=
0
;
virtual
object
create
()
const
=
0
;
virtual
object
from_string
(
const
std
::
string
&
str
)
const
=
0
;
virtual
object
from_string
(
const
std
::
string
&
str
)
const
=
0
;
protected:
protected:
// needed to implement subclasses
// needed to implement subclasses
inline
void
*&
value_of
(
object
&
obj
)
const
{
return
obj
.
m_value
;
}
inline
void
*&
value_of
(
object
&
obj
)
const
{
return
obj
.
m_value
;
}
inline
const
void
*
value_of
(
const
object
&
obj
)
const
{
return
obj
.
m_value
;
}
inline
const
void
*
value_of
(
const
object
&
obj
)
const
{
return
obj
.
m_value
;
}
// object creation
// object creation
virtual
object
copy
(
const
object
&
what
)
const
=
0
;
virtual
object
copy
(
const
object
&
what
)
const
=
0
;
// object modification
// object modification
virtual
void
destroy
(
object
&
what
)
const
=
0
;
virtual
void
destroy
(
object
&
what
)
const
=
0
;
virtual
void
deserialize
(
deserializer
&
d
,
object
&
what
)
const
=
0
;
virtual
void
deserialize
(
deserializer
&
d
,
object
&
what
)
const
=
0
;
// object inspection
// object inspection
virtual
std
::
string
to_string
(
const
object
&
obj
)
const
=
0
;
virtual
std
::
string
to_string
(
const
object
&
obj
)
const
=
0
;
virtual
bool
equal
(
const
object
&
lhs
,
const
object
&
rhs
)
const
=
0
;
virtual
bool
equal
(
const
object
&
lhs
,
const
object
&
rhs
)
const
=
0
;
virtual
void
serialize
(
serializer
&
s
,
const
object
&
what
)
const
=
0
;
virtual
void
serialize
(
serializer
&
s
,
const
object
&
what
)
const
=
0
;
};
};
template
<
typename
T
>
template
<
typename
T
>
uniform_type_info
*
uniform_typeid
()
uniform_type_info
*
uniform_typeid
()
{
{
return
uniform_type_info
::
by_type_info
(
typeid
(
T
));
return
uniform_type_info
::
by_type_info
(
typeid
(
T
));
}
}
template
<
typename
T
,
template
<
typename
T
,
class
SerializeFun
,
class
DeserializeFun
,
class
SerializeFun
,
class
DeserializeFun
,
class
ToStringFun
,
class
FromStringFun
>
class
ToStringFun
,
class
FromStringFun
>
bool
uniform_type_info
::
announce
(
const
SerializeFun
&
sf
,
bool
uniform_type_info
::
announce
(
const
SerializeFun
&
sf
,
const
DeserializeFun
&
df
,
const
DeserializeFun
&
df
,
const
ToStringFun
&
ts
,
const
ToStringFun
&
ts
,
const
FromStringFun
&
fs
)
const
FromStringFun
&
fs
)
{
{
// check signature of SerializeFun::operator()
// check signature of SerializeFun::operator()
typedef
typedef
typename
typename
util
::
callable_trait
<
decltype
(
&
SerializeFun
::
operator
())
>::
arg_types
util
::
callable_trait
<
decltype
(
&
SerializeFun
::
operator
())
>::
arg_types
sf_args
;
sf_args
;
// assert arg_types == { serializer&, const T& } || { serializer&, T }
// assert arg_types == { serializer&, const T& } || { serializer&, T }
static_assert
(
static_assert
(
util
::
disjunction
<
util
::
disjunction
<
std
::
is_same
<
sf_args
,
util
::
type_list
<
serializer
&
,
const
T
&>>
,
std
::
is_same
<
sf_args
,
util
::
type_list
<
serializer
&
,
const
T
&>>
,
std
::
is_same
<
sf_args
,
util
::
type_list
<
serializer
&
,
T
>>
std
::
is_same
<
sf_args
,
util
::
type_list
<
serializer
&
,
T
>>
>::
value
,
>::
value
,
"Invalid signature of &SerializeFun::operator()"
);
"Invalid signature of &SerializeFun::operator()"
);
// check signature of DeserializeFun::operator()
// check signature of DeserializeFun::operator()
typedef
typedef
typename
typename
util
::
callable_trait
<
decltype
(
&
DeserializeFun
::
operator
())
>::
arg_types
util
::
callable_trait
<
decltype
(
&
DeserializeFun
::
operator
())
>::
arg_types
df_args
;
df_args
;
// assert arg_types == { deserializer&, T& }
// assert arg_types == { deserializer&, T& }
static_assert
(
static_assert
(
std
::
is_same
<
df_args
,
util
::
type_list
<
deserializer
&
,
T
&>>::
value
,
std
::
is_same
<
df_args
,
util
::
type_list
<
deserializer
&
,
T
&>>::
value
,
"Invalid signature of &DeserializeFun::operator()"
);
"Invalid signature of &DeserializeFun::operator()"
);
// check signature of ToStringFun::operator()
// check signature of ToStringFun::operator()
typedef
util
::
callable_trait
<
decltype
(
&
ToStringFun
::
operator
())
>
ts_sig
;
typedef
util
::
callable_trait
<
decltype
(
&
ToStringFun
::
operator
())
>
ts_sig
;
typedef
typename
ts_sig
::
arg_types
ts_args
;
typedef
typename
ts_sig
::
arg_types
ts_args
;
// assert result_type == std::string
// assert result_type == std::string
static_assert
(
static_assert
(
std
::
is_same
<
std
::
string
,
typename
ts_sig
::
result_type
>::
value
,
std
::
is_same
<
std
::
string
,
typename
ts_sig
::
result_type
>::
value
,
"ToStringFun::operator() doesn't return a string"
);
"ToStringFun::operator() doesn't return a string"
);
// assert arg_types == { const T& } || { T }
// assert arg_types == { const T& } || { T }
static_assert
(
static_assert
(
util
::
disjunction
<
util
::
disjunction
<
std
::
is_same
<
ts_args
,
util
::
type_list
<
const
T
&>>
,
std
::
is_same
<
ts_args
,
util
::
type_list
<
const
T
&>>
,
std
::
is_same
<
ts_args
,
util
::
type_list
<
T
>>
std
::
is_same
<
ts_args
,
util
::
type_list
<
T
>>
>::
value
,
>::
value
,
"Invalid signature of &ToStringFun::operator()"
);
"Invalid signature of &ToStringFun::operator()"
);
// check signature of ToStringFun::operator()
// check signature of ToStringFun::operator()
typedef
util
::
callable_trait
<
decltype
(
&
FromStringFun
::
operator
())
>
fs_sig
;
typedef
util
::
callable_trait
<
decltype
(
&
FromStringFun
::
operator
())
>
fs_sig
;
typedef
typename
fs_sig
::
arg_types
fs_args
;
typedef
typename
fs_sig
::
arg_types
fs_args
;
// assert result_type == T*
// assert result_type == T*
static_assert
(
static_assert
(
std
::
is_same
<
T
*
,
typename
fs_sig
::
result_type
>::
value
,
std
::
is_same
<
T
*
,
typename
fs_sig
::
result_type
>::
value
,
"FromStringFun::operator() doesn't return T*"
);
"FromStringFun::operator() doesn't return T*"
);
// assert arg_types == { const std::string& } || { std::string }
// assert arg_types == { const std::string& } || { std::string }
static_assert
(
static_assert
(
util
::
disjunction
<
util
::
disjunction
<
std
::
is_same
<
fs_args
,
util
::
type_list
<
const
std
::
string
&>>
,
std
::
is_same
<
fs_args
,
util
::
type_list
<
const
std
::
string
&>>
,
std
::
is_same
<
fs_args
,
util
::
type_list
<
std
::
string
>>
std
::
is_same
<
fs_args
,
util
::
type_list
<
std
::
string
>>
>::
value
,
>::
value
,
"Invalid signature of &FromStringFun::operator()"
);
"Invalid signature of &FromStringFun::operator()"
);
// "on-the-fly" implementation of uniform_type_info
// "on-the-fly" implementation of uniform_type_info
class
utimpl
:
public
uniform_type_info
class
utimpl
:
public
uniform_type_info
{
{
SerializeFun
m_serialize
;
SerializeFun
m_serialize
;
DeserializeFun
m_deserialize
;
DeserializeFun
m_deserialize
;
ToStringFun
m_to_string
;
ToStringFun
m_to_string
;
FromStringFun
m_from_string
;
FromStringFun
m_from_string
;
inline
T
&
to_ref
(
object
&
what
)
const
inline
T
&
to_ref
(
object
&
what
)
const
{
{
return
*
reinterpret_cast
<
T
*>
(
this
->
value_of
(
what
));
return
*
reinterpret_cast
<
T
*>
(
this
->
value_of
(
what
));
}
}
inline
const
T
&
to_ref
(
const
object
&
what
)
const
inline
const
T
&
to_ref
(
const
object
&
what
)
const
{
{
return
*
reinterpret_cast
<
const
T
*>
(
this
->
value_of
(
what
));
return
*
reinterpret_cast
<
const
T
*>
(
this
->
value_of
(
what
));
}
}
protected:
protected:
object
copy
(
const
object
&
what
)
const
object
copy
(
const
object
&
what
)
const
{
{
return
{
new
T
(
this
->
to_ref
(
what
)),
this
};
return
{
new
T
(
this
->
to_ref
(
what
)),
this
};
}
}
object
from_string
(
const
std
::
string
&
str
)
const
object
from_string
(
const
std
::
string
&
str
)
const
{
{
return
{
m_from_string
(
str
),
this
};
return
{
m_from_string
(
str
),
this
};
}
}
void
destroy
(
object
&
what
)
const
void
destroy
(
object
&
what
)
const
{
{
delete
reinterpret_cast
<
T
*>
(
this
->
value_of
(
what
));
delete
reinterpret_cast
<
T
*>
(
this
->
value_of
(
what
));
this
->
value_of
(
what
)
=
nullptr
;
this
->
value_of
(
what
)
=
nullptr
;
}
}
void
deserialize
(
deserializer
&
d
,
object
&
what
)
const
void
deserialize
(
deserializer
&
d
,
object
&
what
)
const
{
{
m_deserialize
(
d
,
to_ref
(
what
));
m_deserialize
(
d
,
to_ref
(
what
));
}
}
std
::
string
to_string
(
const
object
&
obj
)
const
std
::
string
to_string
(
const
object
&
obj
)
const
{
{
return
m_to_string
(
to_ref
(
obj
));
return
m_to_string
(
to_ref
(
obj
));
}
}
bool
equal
(
const
object
&
lhs
,
const
object
&
rhs
)
const
bool
equal
(
const
object
&
lhs
,
const
object
&
rhs
)
const
{
{
return
(
lhs
.
type
()
==
*
this
&&
rhs
.
type
()
==
*
this
)
return
(
lhs
.
type
()
==
*
this
&&
rhs
.
type
()
==
*
this
)
?
to_ref
(
lhs
)
==
to_ref
(
rhs
)
?
to_ref
(
lhs
)
==
to_ref
(
rhs
)
:
false
;
:
false
;
}
}
void
serialize
(
serializer
&
s
,
const
object
&
what
)
const
void
serialize
(
serializer
&
s
,
const
object
&
what
)
const
{
{
m_serialize
(
s
,
to_ref
(
what
));
m_serialize
(
s
,
to_ref
(
what
));
}
}
public:
public:
utimpl
(
const
SerializeFun
&
sfun
,
const
DeserializeFun
dfun
,
utimpl
(
const
SerializeFun
&
sfun
,
const
DeserializeFun
dfun
,
const
ToStringFun
tfun
,
const
FromStringFun
ffun
)
const
ToStringFun
tfun
,
const
FromStringFun
ffun
)
:
uniform_type_info
(
typeid
(
T
))
:
uniform_type_info
(
typeid
(
T
))
,
m_serialize
(
sfun
),
m_deserialize
(
dfun
)
,
m_serialize
(
sfun
),
m_deserialize
(
dfun
)
,
m_to_string
(
tfun
),
m_from_string
(
ffun
)
,
m_to_string
(
tfun
),
m_from_string
(
ffun
)
{
{
}
}
object
create
()
const
object
create
()
const
{
{
return
{
new
T
,
this
};
return
{
new
T
,
this
};
}
}
};
};
return
announce
(
typeid
(
T
),
new
utimpl
(
sf
,
df
,
ts
,
fs
));
return
announce
(
typeid
(
T
),
new
utimpl
(
sf
,
df
,
ts
,
fs
));
}
}
bool
operator
==
(
const
uniform_type_info
&
lhs
,
const
std
::
type_info
&
rhs
);
bool
operator
==
(
const
uniform_type_info
&
lhs
,
const
std
::
type_info
&
rhs
);
inline
bool
operator
!=
(
const
uniform_type_info
&
lhs
,
const
std
::
type_info
&
rhs
)
inline
bool
operator
!=
(
const
uniform_type_info
&
lhs
,
const
std
::
type_info
&
rhs
)
{
{
return
!
(
lhs
==
rhs
);
return
!
(
lhs
==
rhs
);
}
}
inline
bool
operator
==
(
const
std
::
type_info
&
lhs
,
const
uniform_type_info
&
rhs
)
inline
bool
operator
==
(
const
std
::
type_info
&
lhs
,
const
uniform_type_info
&
rhs
)
{
{
return
rhs
==
lhs
;
return
rhs
==
lhs
;
}
}
inline
bool
operator
!=
(
const
std
::
type_info
&
lhs
,
const
uniform_type_info
&
rhs
)
inline
bool
operator
!=
(
const
std
::
type_info
&
lhs
,
const
uniform_type_info
&
rhs
)
{
{
return
!
(
rhs
==
lhs
);
return
!
(
rhs
==
lhs
);
}
}
}
// namespace cppa
}
// namespace cppa
...
...
cppa/util/disable_if.hpp
0 → 100644
View file @
123e61f7
#ifndef DISABLE_IF_HPP
#define DISABLE_IF_HPP
namespace
cppa
{
namespace
util
{
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
>
{
};
}
}
// namespace cppa::util
#endif // DISABLE_IF_HPP
cppa/util/enable_if.hpp
View file @
123e61f7
...
@@ -4,12 +4,14 @@
...
@@ -4,12 +4,14 @@
namespace
cppa
{
namespace
util
{
namespace
cppa
{
namespace
util
{
template
<
bool
Stmt
,
typename
T
=
void
>
template
<
bool
Stmt
,
typename
T
=
void
>
struct
enable_if_c
{
};
struct
enable_if_c
{
};
template
<
typename
T
>
template
<
typename
T
>
struct
enable_if_c
<
true
,
T
>
struct
enable_if_c
<
true
,
T
>
{
{
typedef
T
type
;
typedef
T
type
;
};
};
template
<
class
Trait
,
typename
T
=
void
>
template
<
class
Trait
,
typename
T
=
void
>
...
...
cppa/util/if_else_type.hpp
0 → 100644
View file @
123e61f7
#ifndef IF_ELSE_TYPE_HPP
#define IF_ELSE_TYPE_HPP
#include "cppa/util/wrapped_type.hpp"
namespace
cppa
{
namespace
util
{
// if (IfStmt == true) type = T; else type = Else::type;
template
<
bool
IfStmt
,
typename
T
,
class
Else
>
struct
if_else_type_c
{
typedef
T
type
;
};
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
>
{
};
}
}
// namespace cppa::util
#endif // IF_ELSE_TYPE_HPP
cppa/util/wrapped_type.hpp
0 → 100644
View file @
123e61f7
#ifndef WRAPPED_TYPE_HPP
#define WRAPPED_TYPE_HPP
namespace
cppa
{
namespace
util
{
template
<
typename
T
>
struct
wrapped_type
{
typedef
T
type
;
};
}
}
// namespace cppa::util
#endif // WRAPPED_TYPE_HPP
unit_testing/test__serialization.cpp
View file @
123e61f7
...
@@ -7,11 +7,15 @@
...
@@ -7,11 +7,15 @@
#include <cstring>
#include <cstring>
#include <sstream>
#include <sstream>
#include <cstdint>
#include <cstdint>
#include <cstring>
#include <cassert>
#include <iterator>
#include <typeinfo>
#include <typeinfo>
#include <iostream>
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <algorithm>
#include <functional>
#include <type_traits>
#include <type_traits>
#include <cassert>
#include "test.hpp"
#include "test.hpp"
...
@@ -23,270 +27,224 @@
...
@@ -23,270 +27,224 @@
#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/enable_if.hpp"
#include "cppa/util/disable_if.hpp"
#include "cppa/util/if_else_type.hpp"
#include "cppa/util/wrapped_type.hpp"
#include "cppa/util.hpp"
//
#include "cppa/util.hpp"
using
std
::
cout
;
using
std
::
cout
;
using
std
::
cerr
;
using
std
::
cerr
;
using
std
::
endl
;
using
std
::
endl
;
/**
using
namespace
cppa
::
util
;
* @brief Integers, floating points and strings.
*/
template
<
class
C
,
template
<
typename
>
class
...
Traits
>
enum
fundamental_type
struct
apply
;
template
<
class
C
>
struct
apply
<
C
>
{
{
ft_int8
,
ft_int16
,
ft_int32
,
ft_int64
,
typedef
C
type
;
ft_uint8
,
ft_uint16
,
ft_uint32
,
ft_uint64
,
ft_float
,
ft_double
,
ft_long_double
,
ft_u8string
,
ft_u16string
,
ft_u32string
,
ft_null
};
};
constexpr
const
char
*
fundamental_type_names
[]
=
template
<
class
C
,
template
<
typename
>
class
Trait0
,
template
<
typename
>
class
...
Traits
>
struct
apply
<
C
,
Trait0
,
Traits
...
>
{
{
"ft_int8"
,
"ft_int16"
,
"ft_int32"
,
"ft_int64"
,
typedef
typename
apply
<
typename
Trait0
<
C
>::
type
,
Traits
...
>::
type
type
;
"ft_uint8"
,
"ft_uint16"
,
"ft_uint32"
,
"ft_uint64"
,
"ft_float"
,
"ft_double"
,
"ft_long_double"
,
"ft_u8string"
,
"ft_u16string"
,
"ft_u32string"
,
"ft_null"
};
};
constexpr
const
char
*
fundamental_type_name
(
fundamental_type
ftype
)
{
return
fundamental_type_names
[
static_cast
<
int
>
(
ftype
)];
}
// achieves static call dispatch (Int-To-Type idiom)
template
<
typename
T
>
template
<
fundamental_type
FT
>
struct
plain
struct
ft_token
{
static
const
fundamental_type
value
=
FT
;
};
{
typedef
typename
apply
<
T
,
std
::
remove_reference
,
std
::
remove_cv
>::
type
type
;
};
// if (IfStmt == true) type = T; else type = Else::type;
/**
template
<
bool
IfStmt
,
typename
T
,
class
Else
>
* @brief Integers (signed and unsigned), floating points and strings.
struct
if_else_type_c
*/
enum
primitive_type
{
{
typedef
T
type
;
pt_int8
,
pt_int16
,
pt_int32
,
pt_int64
,
pt_uint8
,
pt_uint16
,
pt_uint32
,
pt_uint64
,
pt_float
,
pt_double
,
pt_long_double
,
pt_u8string
,
pt_u16string
,
pt_u32string
,
pt_null
};
};
template
<
typename
T
,
class
Else
>
constexpr
const
char
*
primitive_type_names
[]
=
struct
if_else_type_c
<
false
,
T
,
Else
>
{
{
typedef
typename
Else
::
type
type
;
"pt_int8"
,
"pt_int16"
,
"pt_int32"
,
"pt_int64"
,
"pt_uint8"
,
"pt_uint16"
,
"pt_uint32"
,
"pt_uint64"
,
"pt_float"
,
"pt_double"
,
"pt_long_double"
,
"pt_u8string"
,
"pt_u16string"
,
"pt_u32string"
,
"pt_null"
};
};
// if (Stmt::value == true) type = T; else type = Else::type;
constexpr
const
char
*
primitive_type_name
(
primitive_type
ptype
)
template
<
class
Stmt
,
typename
T
,
class
Else
>
{
struct
if_else_type
:
if_else_type_c
<
Stmt
::
value
,
T
,
Else
>
{
};
return
primitive_type_names
[
static_cast
<
int
>
(
ptype
)];
}
template
<
typename
T
>
// achieves static call dispatch (Int-To-Type idiom)
struct
wrapped_type
{
typedef
T
type
;
};
template
<
primitive_type
FT
>
struct
pt_token
{
static
const
primitive_type
value
=
FT
;
};
// maps the fundamental_type FT to the corresponding type
// maps the fundamental_type FT to the corresponding type
template
<
fundamental
_type
FT
>
template
<
primitive
_type
FT
>
struct
f
type_to_type
struct
p
type_to_type
:
if_else_type_c
<
FT
==
f
t_int8
,
std
::
int8_t
,
:
if_else_type_c
<
FT
==
p
t_int8
,
std
::
int8_t
,
if_else_type_c
<
FT
==
f
t_int16
,
std
::
int16_t
,
if_else_type_c
<
FT
==
p
t_int16
,
std
::
int16_t
,
if_else_type_c
<
FT
==
f
t_int32
,
std
::
int32_t
,
if_else_type_c
<
FT
==
p
t_int32
,
std
::
int32_t
,
if_else_type_c
<
FT
==
f
t_int64
,
std
::
int64_t
,
if_else_type_c
<
FT
==
p
t_int64
,
std
::
int64_t
,
if_else_type_c
<
FT
==
f
t_uint8
,
std
::
uint8_t
,
if_else_type_c
<
FT
==
p
t_uint8
,
std
::
uint8_t
,
if_else_type_c
<
FT
==
f
t_uint16
,
std
::
uint16_t
,
if_else_type_c
<
FT
==
p
t_uint16
,
std
::
uint16_t
,
if_else_type_c
<
FT
==
f
t_uint32
,
std
::
uint32_t
,
if_else_type_c
<
FT
==
p
t_uint32
,
std
::
uint32_t
,
if_else_type_c
<
FT
==
f
t_uint64
,
std
::
uint64_t
,
if_else_type_c
<
FT
==
p
t_uint64
,
std
::
uint64_t
,
if_else_type_c
<
FT
==
f
t_float
,
float
,
if_else_type_c
<
FT
==
p
t_float
,
float
,
if_else_type_c
<
FT
==
f
t_double
,
double
,
if_else_type_c
<
FT
==
p
t_double
,
double
,
if_else_type_c
<
FT
==
f
t_long_double
,
long
double
,
if_else_type_c
<
FT
==
p
t_long_double
,
long
double
,
if_else_type_c
<
FT
==
f
t_u8string
,
std
::
string
,
if_else_type_c
<
FT
==
p
t_u8string
,
std
::
string
,
if_else_type_c
<
FT
==
f
t_u16string
,
std
::
u16string
,
if_else_type_c
<
FT
==
p
t_u16string
,
std
::
u16string
,
if_else_type_c
<
FT
==
f
t_u32string
,
std
::
u32string
,
if_else_type_c
<
FT
==
p
t_u32string
,
std
::
u32string
,
wrapped_type
<
void
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
wrapped_type
<
void
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
{
{
};
};
// if (IfStmt == true)
ftype = FT; else ftype = Else::f
type;
// if (IfStmt == true)
ptype = FT; else ptype = Else::p
type;
template
<
bool
IfStmt
,
fundamental
_type
FT
,
class
Else
>
template
<
bool
IfStmt
,
primitive
_type
FT
,
class
Else
>
struct
if_else_
f
type_c
struct
if_else_
p
type_c
{
{
static
const
fundamental_type
f
type
=
FT
;
static
const
primitive_type
p
type
=
FT
;
};
};
template
<
fundamental
_type
FT
,
class
Else
>
template
<
primitive
_type
FT
,
class
Else
>
struct
if_else_
f
type_c
<
false
,
FT
,
Else
>
struct
if_else_
p
type_c
<
false
,
FT
,
Else
>
{
{
static
const
fundamental_type
ftype
=
Else
::
f
type
;
static
const
primitive_type
ptype
=
Else
::
p
type
;
};
};
// if (Stmt::value == true)
ftype = FT; else ftype = Else::f
type;
// if (Stmt::value == true)
ptype = FT; else ptype = Else::p
type;
template
<
class
Stmt
,
fundamental
_type
FT
,
class
Else
>
template
<
class
Stmt
,
primitive
_type
FT
,
class
Else
>
struct
if_else_
ftype
:
if_else_f
type_c
<
Stmt
::
value
,
FT
,
Else
>
{
};
struct
if_else_
ptype
:
if_else_p
type_c
<
Stmt
::
value
,
FT
,
Else
>
{
};
template
<
fundamental
_type
FT
>
template
<
primitive
_type
FT
>
struct
wrapped_
ftype
{
static
const
fundamental_type
f
type
=
FT
;
};
struct
wrapped_
ptype
{
static
const
primitive_type
p
type
=
FT
;
};
// maps type T the the corresponding fundamental_type
// maps type T the the corresponding fundamental_type
template
<
typename
T
>
template
<
typename
T
>
struct
type_to_
ftype
struct
type_to_
ptype_impl
// signed integers
// signed integers
:
if_else_
ftype
<
std
::
is_same
<
T
,
std
::
int8_t
>
,
f
t_int8
,
:
if_else_
ptype
<
std
::
is_same
<
T
,
std
::
int8_t
>
,
p
t_int8
,
if_else_
ftype
<
std
::
is_same
<
T
,
std
::
int16_t
>
,
f
t_int16
,
if_else_
ptype
<
std
::
is_same
<
T
,
std
::
int16_t
>
,
p
t_int16
,
if_else_
ftype
<
std
::
is_same
<
T
,
std
::
int32_t
>
,
f
t_int32
,
if_else_
ptype
<
std
::
is_same
<
T
,
std
::
int32_t
>
,
p
t_int32
,
if_else_
ftype
<
std
::
is_same
<
T
,
std
::
int64_t
>
,
f
t_int64
,
if_else_
ptype
<
std
::
is_same
<
T
,
std
::
int64_t
>
,
p
t_int64
,
if_else_
ftype
<
std
::
is_same
<
T
,
std
::
uint8_t
>
,
f
t_uint8
,
if_else_
ptype
<
std
::
is_same
<
T
,
std
::
uint8_t
>
,
p
t_uint8
,
// unsigned integers
// unsigned integers
if_else_
ftype
<
std
::
is_same
<
T
,
std
::
uint16_t
>
,
f
t_uint16
,
if_else_
ptype
<
std
::
is_same
<
T
,
std
::
uint16_t
>
,
p
t_uint16
,
if_else_
ftype
<
std
::
is_same
<
T
,
std
::
uint32_t
>
,
f
t_uint32
,
if_else_
ptype
<
std
::
is_same
<
T
,
std
::
uint32_t
>
,
p
t_uint32
,
if_else_
ftype
<
std
::
is_same
<
T
,
std
::
uint64_t
>
,
f
t_uint64
,
if_else_
ptype
<
std
::
is_same
<
T
,
std
::
uint64_t
>
,
p
t_uint64
,
// float / double
// float / double
if_else_
ftype
<
std
::
is_same
<
T
,
float
>
,
f
t_float
,
if_else_
ptype
<
std
::
is_same
<
T
,
float
>
,
p
t_float
,
if_else_
ftype
<
std
::
is_same
<
T
,
double
>
,
f
t_double
,
if_else_
ptype
<
std
::
is_same
<
T
,
double
>
,
p
t_double
,
if_else_
ftype
<
std
::
is_same
<
T
,
long
double
>
,
f
t_long_double
,
if_else_
ptype
<
std
::
is_same
<
T
,
long
double
>
,
p
t_long_double
,
// strings
// strings
if_else_
ftype
<
std
::
is_convertible
<
T
,
std
::
string
>
,
f
t_u8string
,
if_else_
ptype
<
std
::
is_convertible
<
T
,
std
::
string
>
,
p
t_u8string
,
if_else_
ftype
<
std
::
is_convertible
<
T
,
std
::
u16string
>
,
f
t_u16string
,
if_else_
ptype
<
std
::
is_convertible
<
T
,
std
::
u16string
>
,
p
t_u16string
,
if_else_
ftype
<
std
::
is_convertible
<
T
,
std
::
u32string
>
,
f
t_u32string
,
if_else_
ptype
<
std
::
is_convertible
<
T
,
std
::
u32string
>
,
p
t_u32string
,
wrapped_
ftype
<
f
t_null
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
wrapped_
ptype
<
p
t_null
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
{
{
};
};
template
<
typename
T
>
template
<
typename
T
>
struct
type_to_ftype
<
T
&>
:
type_to_ftype
<
T
>
{
};
struct
type_to_ptype
:
type_to_ptype_impl
<
typename
plain
<
T
>::
type
>
{
};
template
<
typename
T
>
struct
type_to_ftype
<
T
&&>
:
type_to_ftype
<
T
>
{
};
template
<
typename
T
>
namespace
trait
{
struct
type_to_ftype
<
const
T
&>
:
type_to_ftype
<
T
>
{
};
template
<
typename
T
>
template
<
typename
T
>
struct
type_to_ftype
<
const
T
>
:
type_to_ftype
<
T
>
{
};
struct
is_primitive
struct
value
{
{
fundamental_type
type
;
static
const
bool
value
=
type_to_ptype
<
T
>::
ptype
!=
pt_null
;
inline
value
(
const
fundamental_type
&
ftype
)
:
type
(
ftype
)
{
}
};
};
struct
list
template
<
typename
T
>
class
is_iterable
{
{
fundamental_type
value_type
;
inline
list
(
const
fundamental_type
&
ftype
)
:
value_type
(
ftype
)
{
}
};
struct
map
template
<
class
C
>
{
static
bool
cmp_help_fun
(
C
&
arg0
,
fundamental_type
key_type
;
decltype
((
arg0
.
begin
()
==
arg0
.
end
())
&&
fundamental_type
value_type
;
(
*
(
++
(
arg0
.
begin
()))
==
*
(
arg0
.
end
())))
*
)
inline
map
(
const
fundamental_type
&
key_ft
,
const
fundamental_type
&
value_ft
)
:
key_type
(
key_ft
),
value_type
(
value_ft
)
{
{
return
true
;
}
}
};
using
cppa
::
util
::
enable_if
;
template
<
bool
Stmt
,
typename
T
>
template
<
class
C
>
struct
disable_if_c
{
};
static
void
cmp_help_fun
(
C
&
,
void
*
)
{
}
template
<
typename
T
>
typedef
decltype
(
cmp_help_fun
(
*
static_cast
<
T
*>
(
nullptr
),
struct
disable_if_c
<
false
,
T
>
static_cast
<
bool
*>
(
nullptr
)))
{
result_type
;
typedef
T
type
;
};
template
<
class
Trait
,
typename
T
=
void
>
public:
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
>
static
const
bool
value
=
!
is_primitive
<
T
>::
value
void
destroy_fun
(
T
&
what
,
&&
std
::
is_same
<
bool
,
result_type
>::
value
;
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
;
}
// namespace trait
template
<
typename
T
>
class
pt_value
;
T
ft_value_cast
(
ft_value
&
);
template
<
typename
T
>
template
<
typename
T
>
T
ft_value_cast
(
const
f
t_value
&
);
T
pt_value_cast
(
p
t_value
&
);
template
<
fundamental_type
FT
>
template
<
primitive_type
FT
>
typename
ftype_to_type
<
FT
>::
type
&
ft_value_cast
(
ft_value
&
);
typename
ptype_to_type
<
FT
>::
type
&
pt_value_cast
(
pt_value
&
);
template
<
fundamental_type
FT
>
const
typename
ftype_to_type
<
FT
>::
type
&
ft_value_cast
(
const
ft_value
&
);
// Utility function for static call dispatching.
// Invokes pt_token<X>(), where X is the value of ptype.
// Does nothing if ptype == pt_null
template
<
typename
Fun
>
template
<
typename
Fun
>
void
ft_invoke
(
fundamental_type
f
type
,
Fun
&&
f
)
void
pt_invoke
(
primitive_type
p
type
,
Fun
&&
f
)
{
{
switch
(
f
type
)
switch
(
p
type
)
{
{
case
ft_int8
:
f
(
ft_token
<
f
t_int8
>
());
break
;
case
pt_int8
:
f
(
pt_token
<
p
t_int8
>
());
break
;
case
ft_int16
:
f
(
ft_token
<
f
t_int16
>
());
break
;
case
pt_int16
:
f
(
pt_token
<
p
t_int16
>
());
break
;
case
ft_int32
:
f
(
ft_token
<
f
t_int32
>
());
break
;
case
pt_int32
:
f
(
pt_token
<
p
t_int32
>
());
break
;
case
ft_int64
:
f
(
ft_token
<
f
t_int64
>
());
break
;
case
pt_int64
:
f
(
pt_token
<
p
t_int64
>
());
break
;
case
ft_uint8
:
f
(
ft_token
<
f
t_uint8
>
());
break
;
case
pt_uint8
:
f
(
pt_token
<
p
t_uint8
>
());
break
;
case
ft_uint16
:
f
(
ft_token
<
f
t_uint16
>
());
break
;
case
pt_uint16
:
f
(
pt_token
<
p
t_uint16
>
());
break
;
case
ft_uint32
:
f
(
ft_token
<
f
t_uint32
>
());
break
;
case
pt_uint32
:
f
(
pt_token
<
p
t_uint32
>
());
break
;
case
ft_uint64
:
f
(
ft_token
<
f
t_uint64
>
());
break
;
case
pt_uint64
:
f
(
pt_token
<
p
t_uint64
>
());
break
;
case
ft_float
:
f
(
ft_token
<
f
t_float
>
());
break
;
case
pt_float
:
f
(
pt_token
<
p
t_float
>
());
break
;
case
ft_double
:
f
(
ft_token
<
f
t_double
>
());
break
;
case
pt_double
:
f
(
pt_token
<
p
t_double
>
());
break
;
case
ft_long_double
:
f
(
ft_token
<
f
t_long_double
>
());
break
;
case
pt_long_double
:
f
(
pt_token
<
p
t_long_double
>
());
break
;
case
ft_u8string
:
f
(
ft_token
<
f
t_u8string
>
());
break
;
case
pt_u8string
:
f
(
pt_token
<
p
t_u8string
>
());
break
;
case
ft_u16string
:
f
(
ft_token
<
f
t_u16string
>
());
break
;
case
pt_u16string
:
f
(
pt_token
<
p
t_u16string
>
());
break
;
case
ft_u32string
:
f
(
ft_token
<
f
t_u32string
>
());
break
;
case
pt_u32string
:
f
(
pt_token
<
p
t_u32string
>
());
break
;
default:
break
;
default:
break
;
}
}
}
}
/**
/**
* @brief Describes a value of a {@link
fundamental_
type}.
* @brief Describes a value of a {@link
primitive_type primitive data
type}.
*/
*/
class
f
t_value
class
p
t_value
{
{
template
<
typename
T
>
template
<
typename
T
>
friend
T
ft_value_cast
(
ft_value
&
);
friend
T
pt_value_cast
(
pt_value
&
);
template
<
typename
T
>
friend
T
ft_value_cast
(
const
ft_value
&
);
template
<
fundamental_type
F
T
>
template
<
primitive_type
P
T
>
friend
typename
ftype_to_type
<
FT
>::
type
&
ft_value_cast
(
f
t_value
&
);
friend
typename
ptype_to_type
<
PT
>::
type
&
pt_value_cast
(
p
t_value
&
);
template
<
fundamental_type
FT
>
primitive_type
m_ptype
;
friend
const
typename
ftype_to_type
<
FT
>::
type
&
ft_value_cast
(
const
ft_value
&
);
fundamental_type
m_ftype
;
union
union
{
{
...
@@ -307,93 +265,124 @@ class ft_value
...
@@ -307,93 +265,124 @@ class ft_value
};
};
// use static call dispatching to select member variable
// use static call dispatching to select member variable
inline
decltype
(
i8
)
&
get
(
ft_token
<
ft_int8
>
)
{
return
i8
;
}
inline
decltype
(
i8
)
&
get
(
pt_token
<
pt_int8
>
)
{
return
i8
;
}
inline
decltype
(
i16
)
&
get
(
ft_token
<
ft_int16
>
)
{
return
i16
;
}
inline
decltype
(
i16
)
&
get
(
pt_token
<
pt_int16
>
)
{
return
i16
;
}
inline
decltype
(
i32
)
&
get
(
ft_token
<
ft_int32
>
)
{
return
i32
;
}
inline
decltype
(
i32
)
&
get
(
pt_token
<
pt_int32
>
)
{
return
i32
;
}
inline
decltype
(
i64
)
&
get
(
ft_token
<
ft_int64
>
)
{
return
i64
;
}
inline
decltype
(
i64
)
&
get
(
pt_token
<
pt_int64
>
)
{
return
i64
;
}
inline
decltype
(
u8
)
&
get
(
ft_token
<
ft_uint8
>
)
{
return
u8
;
}
inline
decltype
(
u8
)
&
get
(
pt_token
<
pt_uint8
>
)
{
return
u8
;
}
inline
decltype
(
u16
)
&
get
(
ft_token
<
ft_uint16
>
)
{
return
u16
;
}
inline
decltype
(
u16
)
&
get
(
pt_token
<
pt_uint16
>
)
{
return
u16
;
}
inline
decltype
(
u32
)
&
get
(
ft_token
<
ft_uint32
>
)
{
return
u32
;
}
inline
decltype
(
u32
)
&
get
(
pt_token
<
pt_uint32
>
)
{
return
u32
;
}
inline
decltype
(
u64
)
&
get
(
ft_token
<
ft_uint64
>
)
{
return
u64
;
}
inline
decltype
(
u64
)
&
get
(
pt_token
<
pt_uint64
>
)
{
return
u64
;
}
inline
decltype
(
fl
)
&
get
(
ft_token
<
ft_float
>
)
{
return
fl
;
}
inline
decltype
(
fl
)
&
get
(
pt_token
<
pt_float
>
)
{
return
fl
;
}
inline
decltype
(
dbl
)
&
get
(
ft_token
<
ft_double
>
)
{
return
dbl
;
}
inline
decltype
(
dbl
)
&
get
(
pt_token
<
pt_double
>
)
{
return
dbl
;
}
inline
decltype
(
ldbl
)
&
get
(
ft_token
<
ft_long_double
>
)
{
return
ldbl
;
}
inline
decltype
(
ldbl
)
&
get
(
pt_token
<
pt_long_double
>
)
{
return
ldbl
;
}
inline
decltype
(
str8
)
&
get
(
ft_token
<
ft_u8string
>
)
{
return
str8
;
}
inline
decltype
(
str8
)
&
get
(
pt_token
<
pt_u8string
>
)
{
return
str8
;
}
inline
decltype
(
str16
)
&
get
(
ft_token
<
ft_u16string
>
)
{
return
str16
;
}
inline
decltype
(
str16
)
&
get
(
pt_token
<
pt_u16string
>
)
{
return
str16
;
}
inline
decltype
(
str32
)
&
get
(
ft_token
<
ft_u32string
>
)
{
return
str32
;
}
inline
decltype
(
str32
)
&
get
(
pt_token
<
pt_u32string
>
)
{
return
str32
;
}
template
<
primitive_type
FT
,
class
T
,
class
V
>
static
void
set
(
primitive_type
&
lhs_type
,
T
&
lhs
,
V
&&
rhs
,
typename
disable_if
<
std
::
is_arithmetic
<
T
>>::
type
*
=
0
)
{
if
(
FT
==
lhs_type
)
{
lhs
=
std
::
forward
<
V
>
(
rhs
);
}
else
{
new
(
&
lhs
)
T
(
std
::
forward
<
V
>
(
rhs
));
lhs_type
=
FT
;
}
}
// get(...) const overload
template
<
primitive_type
FT
,
class
T
,
class
V
>
template
<
fundamental_type
FT
>
static
void
set
(
primitive_type
&
lhs_type
,
T
&
lhs
,
V
&&
rhs
,
const
typename
ftype_to_type
<
FT
>::
type
&
get
(
ft_token
<
FT
>
token
)
const
typename
enable_if
<
std
::
is_arithmetic
<
T
>>::
type
*
=
0
)
{
{
return
const_cast
<
ft_value
*>
(
this
)
->
get
(
token
);
// don't call a constructor for arithmetic types
lhs
=
rhs
;
lhs_type
=
FT
;
}
template
<
class
T
>
static
void
destroy
(
T
&
what
,
typename
disable_if
<
std
::
is_arithmetic
<
T
>>::
type
*
=
0
)
{
what
.
~
T
();
}
template
<
class
T
>
static
void
destroy
(
T
&
,
typename
enable_if
<
std
::
is_arithmetic
<
T
>>::
type
*
=
0
)
{
// arithmetic types don't need destruction
}
}
struct
destroyer
struct
destroyer
{
{
f
t_value
*
m_self
;
p
t_value
*
m_self
;
inline
destroyer
(
f
t_value
*
self
)
:
m_self
(
self
)
{
}
inline
destroyer
(
p
t_value
*
self
)
:
m_self
(
self
)
{
}
template
<
fundamental
_type
FT
>
template
<
primitive
_type
FT
>
inline
void
operator
()(
f
t_token
<
FT
>
token
)
const
inline
void
operator
()(
p
t_token
<
FT
>
token
)
const
{
{
destroy
_fun
(
m_self
->
get
(
token
));
destroy
(
m_self
->
get
(
token
));
}
}
};
};
struct
initializer
struct
initializer
{
{
f
t_value
*
m_self
;
p
t_value
*
m_self
;
inline
initializer
(
f
t_value
*
self
)
:
m_self
(
self
)
{
}
inline
initializer
(
p
t_value
*
self
)
:
m_self
(
self
)
{
}
template
<
fundamental
_type
FT
>
template
<
primitive
_type
FT
>
inline
void
operator
()(
f
t_token
<
FT
>
token
)
const
inline
void
operator
()(
p
t_token
<
FT
>
token
)
const
{
{
set
_fun
<
FT
>
(
m_self
->
m_f
type
,
set
<
FT
>
(
m_self
->
m_p
type
,
m_self
->
get
(
token
),
m_self
->
get
(
token
),
typename
f
type_to_type
<
FT
>::
type
());
typename
p
type_to_type
<
FT
>::
type
());
}
}
};
};
struct
setter
struct
setter
{
{
f
t_value
*
m_self
;
p
t_value
*
m_self
;
const
f
t_value
&
m_other
;
const
p
t_value
&
m_other
;
inline
setter
(
ft_value
*
self
,
const
f
t_value
&
other
)
inline
setter
(
pt_value
*
self
,
const
p
t_value
&
other
)
:
m_self
(
self
),
m_other
(
other
)
{
}
:
m_self
(
self
),
m_other
(
other
)
{
}
template
<
fundamental
_type
FT
>
template
<
primitive
_type
FT
>
inline
void
operator
()(
f
t_token
<
FT
>
token
)
const
inline
void
operator
()(
p
t_token
<
FT
>
token
)
const
{
{
set
_fun
<
FT
>
(
m_self
->
m_f
type
,
set
<
FT
>
(
m_self
->
m_p
type
,
m_self
->
get
(
token
),
m_self
->
get
(
token
),
m_other
.
get
(
token
));
m_other
.
get
(
token
));
}
}
};
};
struct
mover
struct
mover
{
{
f
t_value
*
m_self
;
p
t_value
*
m_self
;
const
f
t_value
&
m_other
;
const
p
t_value
&
m_other
;
inline
mover
(
ft_value
*
self
,
const
f
t_value
&
other
)
inline
mover
(
pt_value
*
self
,
const
p
t_value
&
other
)
:
m_self
(
self
),
m_other
(
other
)
{
}
:
m_self
(
self
),
m_other
(
other
)
{
}
template
<
fundamental
_type
FT
>
template
<
primitive
_type
FT
>
inline
void
operator
()(
f
t_token
<
FT
>
token
)
const
inline
void
operator
()(
p
t_token
<
FT
>
token
)
const
{
{
set
_fun
<
FT
>
(
m_self
->
m_f
type
,
set
<
FT
>
(
m_self
->
m_p
type
,
m_self
->
get
(
token
),
m_self
->
get
(
token
),
std
::
move
(
m_other
.
get
(
token
)));
std
::
move
(
m_other
.
get
(
token
)));
}
}
};
};
struct
comparator
struct
comparator
{
{
bool
m_result
;
bool
m_result
;
const
f
t_value
*
m_self
;
const
p
t_value
*
m_self
;
const
f
t_value
&
m_other
;
const
p
t_value
&
m_other
;
inline
comparator
(
const
ft_value
*
self
,
const
f
t_value
&
other
)
inline
comparator
(
const
pt_value
*
self
,
const
p
t_value
&
other
)
:
m_result
(
false
),
m_self
(
self
),
m_other
(
other
)
{
}
:
m_result
(
false
),
m_self
(
self
),
m_other
(
other
)
{
}
template
<
fundamental
_type
FT
>
template
<
primitive
_type
FT
>
inline
void
operator
()(
f
t_token
<
FT
>
token
)
inline
void
operator
()(
p
t_token
<
FT
>
token
)
{
{
if
(
m_other
.
m_
f
type
==
FT
)
if
(
m_other
.
m_
p
type
==
FT
)
{
{
m_result
=
(
m_self
->
get
(
token
)
==
m_other
.
get
(
token
));
m_result
=
(
m_self
->
get
(
token
)
==
m_other
.
get
(
token
));
}
}
...
@@ -401,735 +390,1115 @@ class ft_value
...
@@ -401,735 +390,1115 @@ class ft_value
inline
bool
result
()
const
{
return
m_result
;
}
inline
bool
result
()
const
{
return
m_result
;
}
};
};
void
destroy
()
{
ft_invoke
(
m_ftype
,
destroyer
(
this
));
m_ftype
=
ft_null
;
}
template
<
class
Self
,
typename
Fun
>
template
<
class
Self
,
typename
Fun
>
struct
forward
er
struct
appli
er
{
{
Self
*
m_self
;
Self
*
m_self
;
Fun
&
m_f
;
Fun
&
m_f
;
forward
er
(
Self
*
self
,
Fun
&
f
)
:
m_self
(
self
),
m_f
(
f
)
{
}
appli
er
(
Self
*
self
,
Fun
&
f
)
:
m_self
(
self
),
m_f
(
f
)
{
}
template
<
fundamental
_type
FT
>
template
<
primitive
_type
FT
>
inline
void
operator
()(
f
t_token
<
FT
>
token
)
inline
void
operator
()(
p
t_token
<
FT
>
token
)
{
{
m_f
(
m_self
->
get
(
token
));
m_f
(
m_self
->
get
(
token
));
}
}
};
};
struct
type_reader
{
const
std
::
type_info
*
tinfo
;
type_reader
()
:
tinfo
(
nullptr
)
{
}
template
<
primitive_type
FT
>
inline
void
operator
()(
pt_token
<
FT
>
)
{
tinfo
=
&
typeid
(
typename
ptype_to_type
<
FT
>::
type
);
}
};
void
destroy
()
{
pt_invoke
(
m_ptype
,
destroyer
(
this
));
m_ptype
=
pt_null
;
}
public:
public:
// get(...) const overload
template
<
primitive_type
FT
>
const
typename
ptype_to_type
<
FT
>::
type
&
get
(
pt_token
<
FT
>
token
)
const
{
return
const_cast
<
pt_value
*>
(
this
)
->
get
(
token
);
}
template
<
typename
Fun
>
template
<
typename
Fun
>
void
apply
(
Fun
&&
f
)
void
apply
(
Fun
&&
f
)
{
{
ft_invoke
(
m_ftype
,
forwarder
<
f
t_value
,
Fun
>
(
this
,
f
));
pt_invoke
(
m_ptype
,
applier
<
p
t_value
,
Fun
>
(
this
,
f
));
}
}
template
<
typename
Fun
>
template
<
typename
Fun
>
void
apply
(
Fun
&&
f
)
const
void
apply
(
Fun
&&
f
)
const
{
{
ft_invoke
(
m_ftype
,
forwarder
<
const
f
t_value
,
Fun
>
(
this
,
f
));
pt_invoke
(
m_ptype
,
applier
<
const
p
t_value
,
Fun
>
(
this
,
f
));
}
}
ft_value
()
:
m_ftype
(
f
t_null
)
{
}
pt_value
()
:
m_ptype
(
p
t_null
)
{
}
template
<
typename
V
>
template
<
typename
V
>
ft_value
(
V
&&
value
)
:
m_ftype
(
f
t_null
)
pt_value
(
V
&&
value
)
:
m_ptype
(
p
t_null
)
{
{
static_assert
(
type_to_
ftype
<
V
>::
ftype
!=
f
t_null
,
static_assert
(
type_to_
ptype
<
V
>::
ptype
!=
p
t_null
,
"T
is not a valid value for ft_valu
e"
);
"T
couldn't be mapped to an ptyp
e"
);
set
_fun
<
type_to_ftype
<
V
>::
ftype
>
(
m_f
type
,
set
<
type_to_ptype
<
V
>::
ptype
>
(
m_p
type
,
get
(
ft_token
<
type_to_ftype
<
V
>::
f
type
>
()),
get
(
pt_token
<
type_to_ptype
<
V
>::
p
type
>
()),
std
::
forward
<
V
>
(
value
));
std
::
forward
<
V
>
(
value
));
}
}
ft_value
(
fundamental_type
ftype
)
:
m_ftype
(
f
t_null
)
pt_value
(
primitive_type
ptype
)
:
m_ptype
(
p
t_null
)
{
{
ft_invoke
(
f
type
,
initializer
(
this
));
pt_invoke
(
p
type
,
initializer
(
this
));
}
}
ft_value
(
const
ft_value
&
other
)
:
m_ftype
(
f
t_null
)
pt_value
(
const
pt_value
&
other
)
:
m_ptype
(
p
t_null
)
{
{
//invoke(setter(other));
//invoke(setter(other));
ft_invoke
(
other
.
m_f
type
,
setter
(
this
,
other
));
pt_invoke
(
other
.
m_p
type
,
setter
(
this
,
other
));
}
}
ft_value
(
ft_value
&&
other
)
:
m_ftype
(
f
t_null
)
pt_value
(
pt_value
&&
other
)
:
m_ptype
(
p
t_null
)
{
{
//invoke(mover(other));
//invoke(mover(other));
ft_invoke
(
other
.
m_f
type
,
mover
(
this
,
other
));
pt_invoke
(
other
.
m_p
type
,
mover
(
this
,
other
));
}
}
ft_value
&
operator
=
(
const
f
t_value
&
other
)
pt_value
&
operator
=
(
const
p
t_value
&
other
)
{
{
//invoke(setter(other));
//invoke(setter(other));
ft_invoke
(
other
.
m_f
type
,
setter
(
this
,
other
));
pt_invoke
(
other
.
m_p
type
,
setter
(
this
,
other
));
return
*
this
;
return
*
this
;
}
}
ft_value
&
operator
=
(
f
t_value
&&
other
)
pt_value
&
operator
=
(
p
t_value
&&
other
)
{
{
//invoke(mover(other));
//invoke(mover(other));
ft_invoke
(
other
.
m_f
type
,
mover
(
this
,
other
));
pt_invoke
(
other
.
m_p
type
,
mover
(
this
,
other
));
return
*
this
;
return
*
this
;
}
}
bool
operator
==
(
const
f
t_value
&
other
)
const
bool
operator
==
(
const
p
t_value
&
other
)
const
{
{
comparator
cmp
(
this
,
other
);
comparator
cmp
(
this
,
other
);
ft_invoke
(
m_f
type
,
cmp
);
pt_invoke
(
m_p
type
,
cmp
);
return
cmp
.
result
();
return
cmp
.
result
();
}
}
bool
operator
!=
(
const
f
t_value
&
other
)
const
inline
bool
operator
!=
(
const
p
t_value
&
other
)
const
{
{
return
!
(
*
this
==
other
);
return
!
(
*
this
==
other
);
}
}
inline
fundamental_type
type
()
const
{
return
m_ftype
;
}
inline
primitive_type
ptype
()
const
{
return
m_ptype
;
}
const
std
::
type_info
&
type
()
const
{
type_reader
tr
;
pt_invoke
(
m_ptype
,
tr
);
return
(
tr
.
tinfo
)
?
*
tr
.
tinfo
:
typeid
(
void
);
}
~
f
t_value
()
{
destroy
();
}
~
p
t_value
()
{
destroy
();
}
};
};
template
<
typename
T
>
template
<
typename
T
>
typename
cppa
::
util
::
enable_if
<
std
::
is_arithmetic
<
T
>
,
bool
>::
type
typename
enable_if
<
trait
::
is_primitive
<
T
>
,
bool
>::
type
operator
==
(
const
T
&
lhs
,
const
f
t_value
&
rhs
)
operator
==
(
const
T
&
lhs
,
const
p
t_value
&
rhs
)
{
{
return
(
rhs
.
type
()
==
type_to_ftype
<
T
>::
ftype
)
constexpr
primitive_type
ptype
=
type_to_ptype
<
T
>::
ptype
;
?
lhs
==
ft_value_cast
<
const
T
&>
(
rhs
)
static_assert
(
ptype
!=
pt_null
,
"T couldn't be mapped to an ptype"
);
:
false
;
return
(
rhs
.
ptype
()
==
ptype
)
?
lhs
==
pt_value_cast
<
ptype
>
(
rhs
)
:
false
;
}
}
template
<
typename
T
>
template
<
typename
T
>
typename
cppa
::
util
::
enable_if
<
std
::
is_arithmetic
<
T
>
,
bool
>::
type
typename
enable_if
<
trait
::
is_primitive
<
T
>
,
bool
>::
type
operator
==
(
const
f
t_value
&
lhs
,
const
T
&
rhs
)
operator
==
(
const
p
t_value
&
lhs
,
const
T
&
rhs
)
{
{
return
(
lhs
.
type
()
==
type_to_ftype
<
T
>::
ftype
)
return
(
rhs
==
lhs
);
?
ft_value_cast
<
const
T
&>
(
lhs
)
==
rhs
:
false
;
}
}
template
<
typename
T
>
template
<
typename
T
>
typename
cppa
::
util
::
enable_if
<
std
::
is_arithmetic
<
T
>
,
bool
>::
type
typename
enable_if
<
trait
::
is_primitive
<
T
>
,
bool
>::
type
operator
!=
(
const
T
&
lhs
,
const
ft_value
&
rhs
)
operator
!=
(
const
pt_value
&
lhs
,
const
T
&
rhs
)
{
{
return
!
(
lhs
==
rhs
);
return
!
(
lhs
==
rhs
);
}
}
template
<
typename
T
>
template
<
typename
T
>
typename
cppa
::
util
::
enable_if
<
std
::
is_arithmetic
<
T
>
,
bool
>::
type
typename
enable_if
<
trait
::
is_primitive
<
T
>
,
bool
>::
type
operator
!=
(
const
ft_value
&
lhs
,
const
T
&
rhs
)
operator
!=
(
const
T
&
lhs
,
const
pt_value
&
rhs
)
{
{
return
!
(
lhs
==
rhs
);
return
!
(
lhs
==
rhs
);
}
}
template
<
fundamental
_type
FT
>
template
<
primitive
_type
FT
>
typename
ftype_to_type
<
FT
>::
type
&
ft_value_cast
(
f
t_value
&
v
)
typename
ptype_to_type
<
FT
>::
type
&
pt_value_cast
(
p
t_value
&
v
)
{
{
if
(
v
.
type
()
!=
FT
)
throw
std
::
bad_cast
();
if
(
v
.
p
type
()
!=
FT
)
throw
std
::
bad_cast
();
return
v
.
get
(
f
t_token
<
FT
>
());
return
v
.
get
(
p
t_token
<
FT
>
());
}
}
template
<
fundamental
_type
FT
>
template
<
primitive
_type
FT
>
const
typename
ftype_to_type
<
FT
>::
type
&
ft_value_cast
(
const
f
t_value
&
v
)
const
typename
ptype_to_type
<
FT
>::
type
&
pt_value_cast
(
const
p
t_value
&
v
)
{
{
if
(
v
.
type
()
!=
FT
)
throw
std
::
bad_cast
();
if
(
v
.
p
type
()
!=
FT
)
throw
std
::
bad_cast
();
return
v
.
get
(
f
t_token
<
FT
>
());
return
v
.
get
(
p
t_token
<
FT
>
());
}
}
template
<
typename
T
>
template
<
typename
T
>
T
ft_value_cast
(
f
t_value
&
v
)
T
pt_value_cast
(
p
t_value
&
v
)
{
{
static
const
fundamental_type
ftype
=
type_to_ftype
<
T
>::
f
type
;
static
const
primitive_type
ptype
=
type_to_ptype
<
T
>::
p
type
;
if
(
v
.
type
()
!=
f
type
)
throw
std
::
bad_cast
();
if
(
v
.
ptype
()
!=
p
type
)
throw
std
::
bad_cast
();
return
v
.
get
(
ft_token
<
f
type
>
());
return
v
.
get
(
pt_token
<
p
type
>
());
}
}
template
<
typename
T
>
template
<
typename
T
>
T
ft_value_cast
(
const
f
t_value
&
v
)
T
pt_value_cast
(
const
p
t_value
&
v
)
{
{
typedef
typename
std
::
remove_reference
<
T
>::
type
plain_t
;
typedef
typename
std
::
remove_reference
<
T
>::
type
plain_t
;
static_assert
(
!
std
::
is_reference
<
T
>::
value
||
std
::
is_const
<
plain_t
>::
value
,
static_assert
(
!
std
::
is_reference
<
T
>::
value
||
std
::
is_const
<
plain_t
>::
value
,
"Could not get a non-const reference from const
f
t_value&"
);
"Could not get a non-const reference from const
p
t_value&"
);
static
const
fundamental_type
ftype
=
type_to_ftype
<
T
>::
f
type
;
static
const
primitive_type
ptype
=
type_to_ptype
<
T
>::
p
type
;
if
(
v
.
type
()
!=
f
type
)
throw
std
::
bad_cast
();
if
(
v
.
ptype
()
!=
p
type
)
throw
std
::
bad_cast
();
return
v
.
get
(
ft_token
<
f
type
>
());
return
v
.
get
(
pt_token
<
p
type
>
());
}
}
class
value_property
struct
getter_setter_pair
{
{
public:
std
::
function
<
pt_value
(
void
*
)
>
getter
;
std
::
function
<
void
(
void
*
,
pt_value
&&
)
>
setter
;
getter_setter_pair
(
getter_setter_pair
&&
)
=
default
;
getter_setter_pair
(
const
getter_setter_pair
&
)
=
default
;
template
<
class
C
,
typename
T
>
getter_setter_pair
(
T
C
::*
member_ptr
)
{
getter
=
[
=
]
(
void
*
self
)
->
pt_value
{
return
*
reinterpret_cast
<
C
*>
(
self
).
*
member_ptr
;
};
setter
=
[
=
]
(
void
*
self
,
pt_value
&&
value
)
{
*
reinterpret_cast
<
C
*>
(
self
).
*
member_ptr
=
std
::
move
(
pt_value_cast
<
T
&>
(
value
));
};
}
virtual
~
value_property
()
{
}
template
<
class
C
,
typename
GT
,
typename
ST
>
virtual
void
set
(
ft_value
&&
what
)
=
0
;
getter_setter_pair
(
GT
(
C
::*
get_memfn
)()
const
,
void
(
C
::*
set_memfn
)(
ST
))
virtual
void
get
(
ft_value
&
storage
)
const
=
0
;
{
virtual
fundamental_type
type
()
const
=
0
;
getter
=
[
=
]
(
void
*
self
)
->
pt_value
{
return
(
*
reinterpret_cast
<
C
*>
(
self
).
*
get_memfn
)();
};
setter
=
[
=
]
(
void
*
self
,
pt_value
&&
value
)
{
(
*
reinterpret_cast
<
C
*>
(
self
).
*
set_memfn
)(
std
::
move
(
pt_value_cast
<
typename
plain
<
ST
>::
type
&>
(
value
)));
};
}
};
};
class
list_property
class
serializer
{
{
public:
public:
class
iterator
virtual
void
begin_object
(
const
std
::
string
&
type_name
)
=
0
;
{
virtual
void
end_object
()
=
0
;
public:
virtual
void
begin_list
(
size_t
size
)
=
0
;
virtual
void
end_list
()
=
0
;
virtual
~
iterator
()
{
}
virtual
void
write_value
(
const
pt_value
&
value
)
=
0
;
virtual
void
next
()
=
0
;
virtual
bool
at_end
()
const
=
0
;
virtual
ft_value
get
()
const
=
0
;
};
};
class
serializer
;
class
deserializer
;
virtual
~
list_property
()
{
}
class
meta_type
virtual
size_t
size
()
const
=
0
;
{
virtual
iterator
*
begin
()
const
=
0
;
virtual
fundamental_type
value_type
()
const
=
0
;
public:
virtual
void
push_back
(
ft_value
&&
what
)
=
0
;
virtual
~
meta_type
()
{
}
/**
* @brief Create an instance of this type, initialized
* with its default constructor.
*/
virtual
void
*
default_constructed
()
=
0
;
virtual
void
delete_instance
(
void
*
)
=
0
;
virtual
void
serialize
(
void
*
,
serializer
*
)
=
0
;
virtual
void
deserialize
(
void
*
,
deserializer
*
)
=
0
;
};
};
class
map_property
std
::
map
<
std
::
string
,
meta_type
*>
s_meta_types
;
/**
*
*/
class
deserializer
{
{
public:
public:
class
iterator
/**
{
* @brief Seek the beginning of the next object and return its type name.
*/
virtual
std
::
string
seek_object
()
=
0
;
public:
/**
* @brief Seek the beginning of the next object and return its type name,
* but don't modify the internal in-stream position.
*/
virtual
std
::
string
peek_object
()
=
0
;
virtual
~
iterator
()
{
}
virtual
void
begin_object
(
const
std
::
string
&
type_name
)
=
0
;
virtual
void
next
()
=
0
;
virtual
void
end_object
()
=
0
;
virtual
bool
at_end
()
const
=
0
;
virtual
ft_value
key
()
const
=
0
;
virtual
ft_value
value
()
const
=
0
;
};
virtual
size_t
begin_list
(
primitive_type
value_type
)
=
0
;
virtual
void
end_list
()
=
0
;
virtual
~
map_property
()
{
}
virtual
pt_value
read_value
(
primitive_type
ptype
)
=
0
;
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
Getter
,
typename
Setter
,
fundamental_type
FT
>
class
root_object
class
value_property_impl
:
public
value_property
{
{
Getter
m_get
;
Setter
m_set
;
// T* m_ptr;
public:
public:
// value_property_impl(T* ptr) : m_ptr(ptr) { }
std
::
pair
<
void
*
,
meta_type
*>
deserialize
(
deserializer
*
d
)
{
void
*
result
;
std
::
string
tname
=
d
->
peek_object
();
auto
i
=
s_meta_types
.
find
(
tname
);
if
(
i
==
s_meta_types
.
end
())
{
throw
std
::
logic_error
(
"no meta object found for "
+
tname
);
}
auto
mobj
=
i
->
second
;
if
(
mobj
==
nullptr
)
{
throw
std
::
logic_error
(
"mobj == nullptr"
);
}
result
=
mobj
->
default_constructed
();
if
(
result
==
nullptr
)
{
throw
std
::
logic_error
(
"result == nullptr"
);
}
try
{
mobj
->
deserialize
(
result
,
d
);
}
catch
(...)
{
mobj
->
delete_instance
(
result
);
return
{
nullptr
,
nullptr
};
}
return
{
result
,
mobj
};
}
};
value_property_impl
(
Getter
g
,
Setter
s
)
:
m_get
(
g
),
m_set
(
s
)
{
}
template
<
typename
T
>
class
meta_value_property
:
public
meta_type
{
void
set
(
ft_value
&&
what
)
static
constexpr
primitive_type
ptype
=
type_to_ptype
<
T
>::
ptype
;
static_assert
(
ptype
!=
pt_null
,
"T is not a primitive type"
);
public:
meta_value_property
()
{
}
pt_value
get
(
void
*
obj
)
{
{
// *m_ptr = std::move(ft_value_cast<FT>(what));
return
*
reinterpret_cast
<
T
*>
(
obj
);
m_set
(
std
::
move
(
ft_value_cast
<
FT
>
(
what
)));
}
}
void
get
(
ft_value
&
storage
)
const
void
set
(
void
*
obj
,
pt_value
&&
value
)
{
{
// ft_value_cast<FT>(storage) = *m_ptr;
*
reinterpret_cast
<
T
*>
(
obj
)
=
std
::
move
(
pt_value_cast
<
T
&>
(
value
));
ft_value_cast
<
FT
>
(
storage
)
=
m_get
();
}
}
fundamental_type
type
()
const
void
*
default_constructed
()
{
{
return
FT
;
return
new
T
()
;
}
}
};
void
delete_instance
(
void
*
ptr
)
template
<
class
List
,
fundamental_type
FT
>
class
list_property_impl
:
public
list_property
{
class
iterator
:
public
list_property
::
iterator
{
{
delete
reinterpret_cast
<
T
*>
(
ptr
);
}
typedef
typename
List
::
const_iterator
native_iterator
;
void
serialize
(
void
*
obj
,
serializer
*
s
)
{
native_iterator
pos
;
s
->
write_value
(
get
(
obj
));
native_iterator
end
;
}
public:
iterator
(
native_iterator
bg
,
native_iterator
nd
)
:
pos
(
bg
),
end
(
nd
)
{
}
bool
at_end
()
const
{
return
pos
==
end
;
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
{
set
(
obj
,
d
->
read_value
(
ptype
));
}
void
next
()
{
++
pos
;
}
};
ft_value
get
()
const
{
return
*
pos
;
}
// std::vector or std::list
template
<
typename
List
>
class
meta_list_property
:
public
meta_type
{
};
typedef
typename
List
::
value_type
value_type
;
static
constexpr
primitive_type
vptype
=
type_to_ptype
<
value_type
>::
ptype
;
List
*
m_list
;
static_assert
(
vptype
!=
pt_null
,
"T doesn't have a primitive value_type"
)
;
public:
public:
list_property_impl
(
List
*
native_list
)
:
m_list
(
native_list
)
{
}
meta_list_property
(
)
{
}
size_t
size
()
const
{
return
m_list
->
size
();
}
void
serialize
(
void
*
obj
,
serializer
*
s
)
{
auto
&
ls
=
*
reinterpret_cast
<
List
*>
(
obj
);
s
->
begin_list
(
ls
.
size
());
for
(
const
auto
&
val
:
ls
)
{
s
->
write_value
(
val
);
}
s
->
end_list
();
}
list_property
::
iterator
*
begin
()
const
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
{
{
return
new
iterator
(
m_list
->
begin
(),
m_list
->
end
());
auto
&
ls
=
*
reinterpret_cast
<
List
*>
(
obj
);
size_t
ls_size
=
d
->
begin_list
(
vptype
);
for
(
size_t
i
=
0
;
i
<
ls_size
;
++
i
)
{
pt_value
val
=
d
->
read_value
(
vptype
);
ls
.
push_back
(
std
::
move
(
pt_value_cast
<
value_type
&>
(
val
)));
}
d
->
end_list
();
}
}
void
push_back
(
ft_value
&&
what
)
void
*
default_constructed
(
)
{
{
m_list
->
push_back
(
std
::
move
(
ft_value_cast
<
FT
>
(
what
))
);
return
new
List
(
);
}
}
fundamental_type
value_type
()
const
void
delete_instance
(
void
*
ptr
)
{
{
return
FT
;
delete
reinterpret_cast
<
List
*>
(
ptr
)
;
}
}
};
};
template
<
class
Map
,
fundamental_type
KeyType
,
fundamental_type
ValueType
>
template
<
class
Object
>
class
m
ap_property_impl
:
public
map_property
class
m
eta_object
:
public
meta_type
{
{
class
iterator
:
public
map_property
::
iterato
r
class
membe
r
{
{
typedef
typename
Map
::
const_iterator
native_iterator
;
meta_type
*
m_meta
;
std
::
function
<
void
*
(
void
*
)
>
m_deref
;
native_iterator
pos
;
native_iterator
end
;
public:
public:
iterator
(
native_iterator
bg
,
native_iterator
nd
)
:
pos
(
bg
),
end
(
nd
)
{
}
template
<
typename
T
,
class
C
>
member
(
meta_type
*
mtptr
,
T
C
::*
mem_ptr
)
:
m_meta
(
mtptr
)
{
m_deref
=
[
mem_ptr
]
(
void
*
obj
)
->
void
*
{
return
&
(
*
reinterpret_cast
<
C
*>
(
obj
).
*
mem_ptr
);
};
}
void
next
()
{
++
pos
;
}
member
(
meta_type
*
pptr
,
std
::
function
<
void
*
(
void
*
)
>&&
gpm
)
:
m_meta
(
pptr
),
m_deref
(
std
::
move
(
gpm
))
{
}
member
(
member
&&
)
=
default
;
bool
at_end
()
const
{
return
pos
==
end
;
}
member
(
const
member
&
)
=
default
;
ft_value
key
()
const
{
return
pos
->
first
;
}
inline
void
serialize
(
void
*
parent
,
serializer
*
s
)
{
m_meta
->
serialize
(
m_deref
(
parent
),
s
);
}
ft_value
value
()
const
{
return
pos
->
second
;
}
inline
void
deserialize
(
void
*
parent
,
deserializer
*
s
)
{
m_meta
->
deserialize
(
m_deref
(
parent
),
s
);
}
};
};
Map
*
m_map
;
std
::
string
class_name
;
std
::
vector
<
member
>
m_members
;
public:
// terminates recursion
inline
void
push_back
()
{
}
map_property_impl
(
Map
*
ptr
)
:
m_map
(
ptr
)
{
}
template
<
typename
T
,
class
C
,
typename
...
Args
>
void
push_back
(
std
::
pair
<
T
C
::*
,
meta_object
<
T
>*>
pr
,
const
Args
&
...
args
)
{
m_members
.
push_back
({
pr
.
second
,
pr
.
first
});
push_back
(
args
...);
}
size_t
size
()
const
template
<
class
C
,
typename
T
,
typename
...
Args
>
typename
enable_if
<
trait
::
is_primitive
<
T
>
>::
type
push_back
(
T
C
::*
mem_ptr
,
const
Args
&
...
args
)
{
{
return
m_map
->
size
();
m_members
.
push_back
({
new
meta_value_property
<
T
>
(),
mem_ptr
});
push_back
(
args
...);
}
}
iterator
*
begin
()
const
template
<
class
C
,
typename
T
,
typename
...
Args
>
typename
enable_if
<
trait
::
is_iterable
<
T
>
>::
type
push_back
(
T
C
::*
mem_ptr
,
const
Args
&
...
args
)
{
{
return
new
iterator
(
m_map
->
begin
(),
m_map
->
end
());
m_members
.
push_back
({
new
meta_list_property
<
T
>
(),
mem_ptr
});
push_back
(
args
...);
}
}
void
insert
(
ft_value
&&
k
,
ft_value
&&
v
)
template
<
class
C
,
typename
T
,
typename
...
Args
>
typename
disable_if_c
<
trait
::
is_primitive
<
T
>::
value
||
trait
::
is_iterable
<
T
>::
value
,
void
>::
type
push_back
(
T
C
::*
mem_ptr
,
const
Args
&
...
args
)
{
{
m_map
->
insert
(
std
::
make_pair
(
static_assert
(
trait
::
is_primitive
<
T
>::
value
,
std
::
move
(
ft_value_cast
<
KeyType
>
(
k
)),
"T is neither a primitive type nor an iterable type"
);
std
::
move
(
ft_value_cast
<
ValueType
>
(
v
))));
}
}
fundamental_type
key_type
()
const
public:
template
<
typename
...
Args
>
meta_object
(
const
Args
&
...
args
)
:
class_name
(
cppa
::
detail
::
to_uniform_name
(
cppa
::
detail
::
demangle
(
typeid
(
Object
).
name
())))
{
push_back
(
args
...);
}
void
serialize
(
void
*
obj
,
serializer
*
s
)
{
s
->
begin_object
(
class_name
);
for
(
auto
&
m
:
m_members
)
{
m
.
serialize
(
obj
,
s
);
}
s
->
end_object
();
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
{
std
::
string
cname
=
d
->
seek_object
();
if
(
cname
!=
class_name
)
{
throw
std
::
logic_error
(
"wrong type name found"
);
}
d
->
begin_object
(
class_name
);
for
(
auto
&
m
:
m_members
)
{
m
.
deserialize
(
obj
,
d
);
}
d
->
end_object
();
}
void
*
default_constructed
()
{
{
return
KeyType
;
return
new
Object
()
;
}
}
fundamental_type
value_type
()
const
void
delete_instance
(
void
*
ptr
)
{
{
return
ValueType
;
delete
reinterpret_cast
<
Object
*>
(
ptr
)
;
}
}
};
};
template
<
fundamental_type
FT
,
typename
Getter
,
typename
Setter
>
struct
struct_a
value_property
*
as_value_property
(
Getter
getter
,
Setter
setter
)
{
{
return
new
value_property_impl
<
Getter
,
Setter
,
FT
>
(
getter
,
setter
);
int
x
;
}
int
y
;
};
using
cppa
::
util
::
enable_if
;
bool
operator
==
(
const
struct_a
&
lhs
,
const
struct_a
&
rhs
)
using
cppa
::
util
::
conjunction
;
{
return
lhs
.
x
==
rhs
.
x
&&
lhs
.
y
==
rhs
.
y
;
}
template
<
fundamental_type
FT
,
class
C
,
typename
Getter
,
typename
Setter
>
bool
operator
!=
(
const
struct_a
&
lhs
,
const
struct_a
&
rhs
)
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
;
return
!
(
lhs
==
rhs
);
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
));
});
}
}
template
<
typename
T
,
fundamental_type
FT
=
type_to_ftype
<
T
>
::
ftype
>
struct
struct_b
value_property
*
as_value_property
(
T
*
ptr
)
{
struct_a
a
;
int
z
;
std
::
list
<
int
>
ints
;
};
bool
operator
==
(
const
struct_b
&
lhs
,
const
struct_b
&
rhs
)
{
{
return
as_value_property
<
FT
>
([
ptr
]()
->
const
T
&
{
return
*
ptr
;
},
return
lhs
.
a
==
rhs
.
a
&&
lhs
.
z
==
rhs
.
z
&&
lhs
.
ints
==
rhs
.
ints
;
[
ptr
](
T
&&
val
)
{
*
ptr
=
std
::
move
(
val
);
});
}
}
template
<
typename
List
,
bool
operator
!=
(
const
struct_b
&
lhs
,
const
struct_b
&
rhs
)
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
);
return
!
(
lhs
==
rhs
);
}
}
template
<
typename
Map
,
template
<
class
C
,
class
Parent
,
typename
...
Args
>
fundamental_type
KT
=
type_to_ftype
<
typename
Map
::
key_type
>
::
ftype
,
std
::
pair
<
C
Parent
::*
,
meta_object
<
C
>*>
compound_member
(
C
Parent
::*
c_ptr
,
const
Args
&
...
args
)
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
);
return
std
::
make_pair
(
c_ptr
,
new
meta_object
<
C
>
(
args
...)
);
}
}
struct
property_pt
r
class
string_serializer
:
public
serialize
r
{
{
enum
flag_type
{
is_null
,
is_vp
,
is_lp
,
is_mp
}
m_flag
;
std
::
ostream
&
out
;
union
struct
pt_writer
{
{
value_property
*
m_vp
;
list_property
*
m_lp
;
map_property
*
m_mp
;
};
void
set
(
value_property
*
vp
)
std
::
ostream
&
out
;
{
m_flag
=
is_vp
;
m_vp
=
vp
;
}
void
set
(
list_property
*
lp
)
pt_writer
(
std
::
ostream
&
mout
)
:
out
(
mout
)
{
}
{
m_flag
=
is_lp
;
m_lp
=
lp
;
}
void
set
(
map_property
*
mp
)
template
<
typename
T
>
{
void
operator
()(
const
T
&
value
)
m_flag
=
is_mp
;
{
m_mp
=
mp
;
out
<<
value
;
}
}
void
destroy
()
void
operator
()(
const
std
::
string
&
str
)
{
switch
(
m_flag
)
{
{
case
is_vp
:
delete
m_vp
;
break
;
out
<<
"
\"
"
<<
str
<<
"
\"
"
;
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
)
void
operator
()(
const
std
::
u16string
&
)
{
}
void
operator
()(
const
std
::
u32string
&
)
{
}
};
int
m_open_objects
;
bool
m_after_value
;
inline
void
clear
()
{
{
m_flag
=
other
.
m_flag
;
if
(
m_after_value
)
switch
(
other
.
m_flag
)
{
{
case
is_vp
:
m_vp
=
other
.
m_vp
;
break
;
out
<<
", "
;
case
is_lp
:
m_lp
=
other
.
m_lp
;
break
;
m_after_value
=
false
;
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
)
public:
string_serializer
(
std
::
ostream
&
mout
)
:
out
(
mout
),
m_open_objects
(
0
),
m_after_value
(
false
)
{
}
void
begin_object
(
const
std
::
string
&
type_name
)
{
{
if
(
m_flag
!=
is_vp
)
throw
std
::
bad_cast
();
clear
();
return
m_vp
;
++
m_open_objects
;
out
<<
type_name
<<
" ( "
;
}
}
void
end_object
()
list_property
*
get
(
std
::
false_type
,
std
::
true_type
,
std
::
false_type
)
{
{
if
(
m_flag
!=
is_lp
)
throw
std
::
bad_cast
();
out
<<
" )"
;
return
m_lp
;
}
}
map_property
*
get
(
std
::
false_type
,
std
::
false_type
,
std
::
true_type
)
void
begin_list
(
size_t
)
{
{
if
(
m_flag
!=
is_mp
)
throw
std
::
bad_cast
();
clear
();
return
m_mp
;
out
<<
"{ "
;
}
}
public:
void
end_list
()
{
if
(
!
m_after_value
)
{
out
<<
"}"
;
}
else
{
out
<<
" }"
;
}
}
property_ptr
(
value_property
*
ptr
)
{
set
(
ptr
);
}
void
write_value
(
const
pt_value
&
value
)
{
clear
();
value
.
apply
(
pt_writer
(
out
));
m_after_value
=
true
;
}
property_ptr
(
list_property
*
ptr
)
{
set
(
ptr
);
}
};
property_ptr
(
map_property
*
ptr
)
{
set
(
ptr
);
}
class
xml_serializer
:
public
serializer
{
property_ptr
()
:
m_flag
(
is_null
)
{
}
std
::
ostream
&
out
;
std
::
string
indentation
;
property_ptr
(
property_ptr
&&
other
)
inline
void
inc_indentation
(
)
{
{
move_from
(
other
);
indentation
.
resize
(
indentation
.
size
()
+
4
,
' '
);
}
}
property_ptr
&
operator
=
(
property_ptr
&&
other
)
inline
void
dec_indentation
(
)
{
{
destroy
();
auto
isize
=
indentation
.
size
();
move_from
(
other
);
indentation
.
resize
((
isize
>
4
)
?
(
isize
-
4
)
:
0
);
return
*
this
;
}
}
~
property_ptr
()
struct
pt_writer
{
{
destroy
();
}
property_ptr
(
const
property_ptr
&
)
=
delete
;
std
::
ostream
&
out
;
const
std
::
string
&
indentation
;
property_ptr
&
operator
=
(
const
property_ptr
&
)
=
delete
;
pt_writer
(
std
::
ostream
&
ostr
,
const
std
::
string
&
indent
)
:
out
(
ostr
),
indentation
(
indent
)
{
}
inline
bool
is_value_property
()
const
{
return
m_flag
==
is_vp
;
}
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
&
)
{
}
};
inline
bool
is_list_property
()
const
{
return
m_flag
==
is_lp
;
}
public:
inline
bool
is_map_property
()
const
{
return
m_flag
==
is_mp
;
}
xml_serializer
(
std
::
ostream
&
ostr
)
:
out
(
ostr
),
indentation
(
""
)
{
}
inline
explicit
operator
bool
()
const
{
return
m_flag
!=
is_null
;
}
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
"
;
}
inline
bool
operator
==
(
const
std
::
nullptr_t
&
)
void
begin_list
(
size_t
)
{
{
return
m_flag
==
is_null
;
out
<<
indentation
<<
"<list>
\n
"
;
inc_indentation
();
}
}
inline
bool
operator
!=
(
const
std
::
nullptr_t
&
)
void
end_list
(
)
{
{
return
m_flag
!=
is_null
;
dec_indentation
();
out
<<
indentation
<<
"</list>
\n
"
;
}
}
template
<
typename
T
>
void
write_value
(
const
pt_value
&
value
)
T
*
as
()
{
{
return
get
(
std
::
is_same
<
T
,
value_property
>
(),
value
.
apply
(
pt_writer
(
out
,
indentation
));
std
::
is_same
<
T
,
list_property
>
(),
std
::
is_same
<
T
,
map_property
>
());
}
}
};
};
/**
class
binary_serializer
:
public
serializer
* @brief
*/
class
abstract_object
{
{
inline
void
push_back
()
{
}
typedef
char
*
buf_type
;
buf_type
m_buf
;
size_t
m_wr_pos
;
template
<
typename
T0
,
typename
...
Tn
>
struct
pt_writer
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:
buf_type
&
m_buf
;
size_t
&
m_wr_pos
;
typedef
std
::
vector
<
property_ptr
>
pptr_vector
;
pt_writer
(
buf_type
&
buf
,
size_t
&
pos
)
:
m_buf
(
buf
),
m_wr_pos
(
pos
)
{
}
abstract_object
(
pptr_vector
&&
pvec
)
:
m_properties
(
std
::
move
(
pvec
))
{
}
template
<
typename
T
>
void
operator
()(
const
T
&
value
)
{
memcpy
(
m_buf
+
m_wr_pos
,
&
value
,
sizeof
(
T
));
m_wr_pos
+=
sizeof
(
T
);
}
void
operator
()(
const
std
::
u16string
&
)
{
}
void
operator
()(
const
std
::
u32string
&
)
{
}
template
<
typename
T0
,
typename
...
Tn
>
};
abstract_object
(
T0
*
ptr0
,
Tn
*
...
ptrs
)
template
<
typename
T
>
void
write
(
const
T
&
value
)
{
{
push_back
(
ptr0
,
ptrs
...);
memcpy
(
m_buf
+
m_wr_pos
,
&
value
,
sizeof
(
T
));
m_wr_pos
+=
sizeof
(
T
);
}
}
abstract_object
()
=
default
;
void
write
(
const
std
::
string
&
str
)
abstract_object
(
abstract_object
&&
)
=
default
;
{
abstract_object
&
operator
=
(
abstract_object
&&
)
=
default
;
write
(
static_cast
<
std
::
uint32_t
>
(
str
.
size
()));
memcpy
(
m_buf
+
m_wr_pos
,
str
.
c_str
(),
str
.
size
());
m_wr_pos
+=
str
.
size
();
}
public:
abstract_object
(
const
abstract_object
&
)
=
delete
;
binary_serializer
(
char
*
buf
)
:
m_buf
(
buf
),
m_wr_pos
(
0
)
{
}
abstract_object
&
operator
=
(
const
abstract_object
&
)
=
delete
;
size_t
properties
(
)
void
begin_object
(
const
std
::
string
&
tname
)
{
{
return
m_properties
.
size
(
);
write
(
tname
);
}
}
property_ptr
&
property
(
size_t
pos
)
void
end_object
()
{
}
void
begin_list
(
size_t
list_size
)
{
{
return
m_properties
[
pos
]
;
write
(
static_cast
<
std
::
uint32_t
>
(
list_size
))
;
}
}
private:
void
end_list
()
{
}
pptr_vector
m_properties
;
void
write_value
(
const
pt_value
&
value
)
{
value
.
apply
(
pt_writer
(
m_buf
,
m_wr_pos
));
}
};
};
class
sink
class
binary_deserializer
:
public
deserializer
{
{
public:
typedef
char
*
buf_type
;
virtual
void
write
(
abstract_object
&
)
=
0
;
buf_type
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()"
);
}
}
struct
xml_sink_helper
{
std
::
ostringstream
&
ostr
;
const
std
::
string
&
indent
;
xml_sink_helper
(
std
::
ostringstream
&
mostr
,
const
std
::
string
&
idn
)
:
ostr
(
mostr
),
indent
(
idn
)
{
}
template
<
typename
T
>
template
<
typename
T
>
void
operator
()(
const
T
&
what
)
void
read
(
T
&
storage
,
bool
modify_rd_pos
=
true
)
{
{
static
const
fundamental_type
ftype
=
type_to_ftype
<
T
>::
ftype
;
range_check
(
sizeof
(
T
));
ostr
<<
indent
memcpy
(
&
storage
,
m_buf
+
m_rd_pos
,
sizeof
(
T
));
<<
"<"
<<
fundamental_type_name
(
ftype
)
<<
">"
if
(
modify_rd_pos
)
m_rd_pos
+=
sizeof
(
T
);
<<
what
<<
"</"
<<
fundamental_type_name
(
ftype
)
<<
">
\n
"
;
}
}
void
operator
()(
const
std
::
u16string
&
)
{
}
void
operator
()(
const
std
::
u32string
&
)
{
}
};
class
xml_sink
void
read
(
std
::
string
&
str
,
bool
modify_rd_pos
=
true
)
{
{
std
::
uint32_t
str_size
;
static
const
char
br
=
'\n'
;
read
(
str_size
,
modify_rd_pos
);
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
);
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
;
}
std
::
ostringstream
ostr
;
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_size
+=
static_cast
<
typename
StringType
::
value_type
>
(
c
);
}
}
void
append
(
const
std
::
string
&
indentation
,
const
ft_value
&
what
)
void
read
(
std
::
u16string
&
str
)
{
{
what
.
apply
(
xml_sink_helper
(
ostr
,
indentation
));
// 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
);
}
}
public:
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
);
}
void
write
(
abstract_object
&
obj
)
struct
pt_reader
{
{
ostr
<<
"<object>"
<<
br
;
binary_deserializer
*
self
;
for
(
size_t
i
=
0
;
i
<
obj
.
properties
();
++
i
)
inline
pt_reader
(
binary_deserializer
*
mself
)
:
self
(
mself
)
{
}
template
<
typename
T
>
inline
void
operator
()(
T
&
value
)
{
{
property_ptr
&
pptr
=
obj
.
property
(
i
);
self
->
read
(
value
);
if
(
pptr
.
is_value_property
())
{
auto
vp
=
pptr
.
as
<
value_property
>
();
ft_value
val
(
vp
->
type
());
vp
->
get
(
val
);
append
(
" "
,
val
);
}
}
}
ostr
<<
"</object>"
;
};
public:
binary_deserializer
(
buf_type
buf
,
size_t
buf_size
)
:
m_buf
(
buf
),
m_rd_pos
(
0
),
m_buf_size
(
buf_size
)
{
}
}
std
::
string
str
()
const
{
return
ostr
.
str
();
}
std
::
string
seek_object
()
{
std
::
string
result
;
read
(
result
);
return
result
;
}
};
std
::
string
peek_object
()
{
std
::
string
result
;
read
(
result
,
false
);
return
result
;
}
class
source
void
begin_object
(
const
std
::
string
&
)
{
{
}
public:
void
end_object
()
{
}
virtual
void
read
(
abstract_object
&
)
=
0
;
size_t
begin_list
(
primitive_type
)
{
std
::
uint32_t
size
;
read
(
size
);
return
size
;
}
};
void
end_list
()
{
}
pt_value
read_value
(
primitive_type
ptype
)
{
pt_value
val
(
ptype
);
val
.
apply
(
pt_reader
(
this
));
return
val
;
}
struct
point_struct
{
std
::
uint32_t
x
,
y
,
z
;
};
};
class
point_class
class
string_deserializer
:
public
deserializer
{
{
std
::
uint32_t
m_x
,
m_y
,
m_z
;
std
::
string
m_str
;
std
::
string
::
iterator
m_pos
;
size_t
m_obj_count
;
public:
void
skip_space_and_comma
()
{
while
(
*
m_pos
==
' '
||
*
m_pos
==
','
)
++
m_pos
;
}
point_class
()
:
m_x
(
0
),
m_y
(
0
),
m_z
(
0
)
{
}
void
throw_malformed
(
const
std
::
string
&
error_msg
)
{
throw
std
::
logic_error
(
"malformed string: "
+
error_msg
);
}
point_class
(
std
::
uint32_t
mx
,
std
::
uint32_t
my
,
std
::
uint32_t
mz
)
void
consume
(
char
c
)
:
m_x
(
mx
),
m_y
(
my
),
m_z
(
mz
)
{
{
skip_space_and_comma
();
if
(
*
m_pos
!=
c
)
{
std
::
string
error
;
error
+=
"expected '"
;
error
+=
c
;
error
+=
"' found '"
;
error
+=
*
m_pos
;
error
+=
"'"
;
throw_malformed
(
error
);
}
++
m_pos
;
}
}
std
::
uint32_t
x
()
const
{
return
m_x
;
}
inline
std
::
string
::
iterator
next_delimiter
()
{
return
std
::
find_if
(
m_pos
,
m_str
.
end
(),
[]
(
char
c
)
->
bool
{
switch
(
c
)
{
case
'('
:
case
')'
:
case
'{'
:
case
'}'
:
case
' '
:
case
','
:
return
true
;
default
:
return
false
;
}
});
}
std
::
uint32_t
y
()
const
{
return
m_y
;
}
public:
std
::
uint32_t
z
()
const
{
return
m_z
;
}
string_deserializer
(
const
std
::
string
&
str
)
:
m_str
(
str
)
{
m_pos
=
m_str
.
begin
();
m_obj_count
=
0
;
}
void
set_x
(
std
::
uint32_t
value
)
{
m_x
=
value
;
}
string_deserializer
(
std
::
string
&&
str
)
:
m_str
(
std
::
move
(
str
))
{
m_pos
=
m_str
.
begin
();
m_obj_count
=
0
;
}
void
set_y
(
std
::
uint32_t
value
)
{
m_y
=
value
;
}
std
::
string
seek_object
()
{
skip_space_and_comma
();
auto
substr_end
=
next_delimiter
();
// next delimiter must eiter be '(' or "\w+\("
if
(
substr_end
==
m_str
.
end
()
||
*
substr_end
!=
'('
)
{
auto
peeker
=
substr_end
;
while
(
peeker
!=
m_str
.
end
()
&&
*
peeker
==
' '
)
++
peeker
;
if
(
peeker
==
m_str
.
end
()
||
*
peeker
!=
'('
)
{
throw_malformed
(
"type name not followed by '('"
);
}
}
std
::
string
result
(
m_pos
,
substr_end
);
m_pos
=
substr_end
;
return
result
;
}
void
set_z
(
std
::
uint32_t
value
)
{
m_z
=
value
;
}
std
::
string
peek_object
()
{
std
::
string
result
=
seek_object
();
// restore position in stream
m_pos
-=
result
.
size
();
return
result
;
}
};
void
begin_object
(
const
std
::
string
&
)
{
++
m_obj_count
;
skip_space_and_comma
();
consume
(
'('
);
}
void
plot
(
value_property
*
vp
)
void
end_object
()
{
ft_value
v
(
vp
->
type
());
vp
->
get
(
v
);
switch
(
v
.
type
())
{
{
case
ft_uint32
:
cout
<<
ft_value_cast
<
ft_uint32
>
(
v
)
<<
" "
;
break
;
consume
(
')'
);
default:
break
;
if
(
--
m_obj_count
==
0
)
{
skip_space_and_comma
();
if
(
m_pos
!=
m_str
.
end
())
{
throw_malformed
(
"expected end of of string"
);
}
}
}
}
}
void
plot
(
property_ptr
&
pptr
)
size_t
begin_list
(
primitive_type
)
{
if
(
pptr
.
is_value_property
())
{
{
plot
(
pptr
.
as
<
value_property
>
());
consume
(
'{'
);
auto
list_end
=
std
::
find
(
m_pos
,
m_str
.
end
(),
'}'
);
return
std
::
count
(
m_pos
,
list_end
,
','
)
+
1
;
}
}
}
void
plot
(
abstract_object
&
what
,
const
std
::
string
&
what_name
)
void
end_list
()
{
cout
<<
what_name
<<
" ("
<<
what
.
properties
()
<<
" properties): "
;
for
(
size_t
i
=
0
;
i
<
what
.
properties
();
++
i
)
{
{
plot
(
what
.
property
(
i
)
);
consume
(
'}'
);
}
}
cout
<<
endl
;
struct
from_string
{
const
std
::
string
&
str
;
from_string
(
const
std
::
string
&
s
)
:
str
(
s
)
{
}
template
<
typename
T
>
void
operator
()(
T
&
what
)
{
std
::
istringstream
s
(
str
);
s
>>
what
;
}
void
operator
()(
std
::
string
&
what
)
{
what
=
str
;
}
void
operator
()(
std
::
u16string
&
)
{
}
void
operator
()(
std
::
u32string
&
)
{
}
};
pt_value
read_value
(
primitive_type
ptype
)
{
skip_space_and_comma
();
auto
substr_end
=
std
::
find_if
(
m_pos
,
m_str
.
end
(),
[]
(
char
c
)
->
bool
{
switch
(
c
)
{
case
')'
:
case
'}'
:
case
' '
:
case
','
:
return
true
;
default
:
return
false
;
}
});
std
::
string
substr
(
m_pos
,
substr_end
);
pt_value
result
(
ptype
);
result
.
apply
(
from_string
(
substr
));
m_pos
+=
substr
.
size
();
return
result
;
}
};
template
<
typename
T
>
std
::
string
to_string
(
T
*
what
,
meta_object
<
T
>*
mobj
)
{
std
::
ostringstream
osstr
;
string_serializer
strs
(
osstr
);
mobj
->
serialize
(
what
,
&
strs
);
return
osstr
.
str
();
}
}
std
::
size_t
test__serialization
()
std
::
size_t
test__serialization
()
...
@@ -1137,150 +1506,84 @@ std::size_t test__serialization()
...
@@ -1137,150 +1506,84 @@ std::size_t test__serialization()
CPPA_TEST
(
test__serialization
);
CPPA_TEST
(
test__serialization
);
CPPA_CHECK_EQUAL
((
trait
::
is_iterable
<
int
>::
value
),
false
);
// std::string is primitive and thus not identified by is_iterable
CPPA_CHECK_EQUAL
((
trait
::
is_iterable
<
std
::
string
>::
value
),
false
);
CPPA_CHECK_EQUAL
((
trait
::
is_iterable
<
std
::
list
<
int
>>::
value
),
true
);
CPPA_CHECK_EQUAL
((
trait
::
is_iterable
<
std
::
map
<
int
,
int
>>::
value
),
true
);
// test pt_value implementation
{
{
f
t_value
v1
(
42
);
p
t_value
v1
(
42
);
f
t_value
v2
(
42
);
p
t_value
v2
(
42
);
CPPA_CHECK_EQUAL
(
v1
,
v2
);
CPPA_CHECK_EQUAL
(
v1
,
v2
);
CPPA_CHECK_EQUAL
(
v1
,
42
);
CPPA_CHECK_EQUAL
(
v1
,
42
);
CPPA_CHECK_EQUAL
(
42
,
v2
);
CPPA_CHECK_EQUAL
(
42
,
v2
);
// type mismatch => unequal
CPPA_CHECK
(
v2
!=
static_cast
<
std
::
int8_t
>
(
42
));
CPPA_CHECK
(
v2
!=
static_cast
<
std
::
int8_t
>
(
42
));
}
}
auto
manipulate_point
=
[
&
](
abstract_object
&
pt
)
{
root_object
root
;
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 acces
s
// test
serializers / deserializer
s
{
{
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
meta_object
<
struct_b
>
meta_b
{
{
compound_member
(
&
struct_b
::
a
,
&
struct_a
::
x
,
&
struct_a
::
y
),
point_class
pt
=
{
1
,
2
,
4
};
&
struct_b
::
z
,
abstract_object
abstract_pt
=
{
&
struct_b
::
ints
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
);
}
{
// "announce" meta types
std
::
string
str
=
"Hello World"
;
s_meta_types
[
"struct_b"
]
=
&
meta_b
;
std
::
unique_ptr
<
value_property
>
p
(
as_value_property
(
&
str
));
p
->
set
(
std
::
string
(
"foobar"
));
CPPA_CHECK_EQUAL
(
str
,
"foobar"
);
}
{
struct_b
b1
=
{
{
1
,
2
},
3
,
{
4
,
5
,
6
,
7
,
8
,
9
,
10
}
};
std
::
vector
<
std
::
int32_t
>
ints
;
struct_b
b2
;
std
::
unique_ptr
<
list_property
>
p
(
as_list_property
(
&
ints
));
struct_b
b3
;
p
->
push_back
(
static_cast
<
std
::
int32_t
>
(
1
));
p
->
push_back
(
static_cast
<
std
::
int32_t
>
(
2
));
auto
b1str
=
"struct_b ( struct_a ( 1, 2 ), 3, "
p
->
push_back
(
static_cast
<
std
::
int32_t
>
(
3
));
"{ 4, 5, 6, 7, 8, 9, 10 } )"
;
for
(
std
::
unique_ptr
<
list_property
::
iterator
>
i
(
p
->
begin
());
!
i
->
at_end
();
i
->
next
())
CPPA_CHECK_EQUAL
((
to_string
(
&
b1
,
&
meta_b
)),
b1str
);
char
buf
[
512
];
// serialize b1 to buf
{
{
cout
<<
ft_value_cast
<
ft_int32
>
(
i
->
get
())
<<
" "
;
binary_serializer
bs
(
buf
);
meta_b
.
serialize
(
&
b1
,
&
bs
);
}
}
cout
<<
endl
;
CPPA_CHECK_EQUAL
(
ints
.
size
(),
3
);
CPPA_CHECK_EQUAL
(
ints
,
(
std
::
vector
<
std
::
int32_t
>
({
1
,
2
,
3
})));
}
{
// deserialize b2 from buf
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
(
);
binary_deserializer
bd
(
buf
,
512
);
auto
send
=
strings
.
end
(
);
auto
res
=
root
.
deserialize
(
&
bd
);
std
::
unique_ptr
<
map_property
::
iterator
>
viter
(
p
->
begin
()
);
CPPA_CHECK_EQUAL
(
res
.
second
,
&
meta_b
);
while
(
siter
!=
send
)
if
(
res
.
second
==
&
meta_b
)
{
{
CPPA_CHECK_EQUAL
(
ft_value_cast
<
ft_int32
>
(
viter
->
key
()),
b2
=
*
reinterpret_cast
<
struct_b
*>
(
res
.
first
);
siter
->
first
);
CPPA_CHECK_EQUAL
(
ft_value_cast
<
ft_u8string
>
(
viter
->
value
()),
siter
->
second
);
viter
->
next
();
++
siter
;
}
}
res
.
second
->
delete_instance
(
res
.
first
);
}
}
}
ft_value
v1
(
"Hello World"
);
CPPA_CHECK_EQUAL
(
b1
,
b2
);
CPPA_CHECK_EQUAL
((
to_string
(
&
b2
,
&
meta_b
)),
b1str
);
auto
plot_objects
=
[]
(
const
std
::
vector
<
cppa
::
object
>&
objs
)
// deserialize b3 from string, using string_deserializer
{
cout
<<
"{ "
;
bool
first
=
true
;
for
(
const
cppa
::
object
&
o
:
objs
)
{
{
if
(
first
)
first
=
false
;
string_deserializer
strd
(
b1str
)
;
else
cout
<<
", "
;
auto
res
=
root
.
deserialize
(
&
strd
)
;
cout
<<
o
.
type
().
name
()
<<
"("
;
CPPA_CHECK_EQUAL
(
res
.
second
,
&
meta_b
)
;
if
(
o
.
type
()
==
typeid
(
std
::
string
)
)
if
(
res
.
second
==
&
meta_b
)
cout
<<
"
\"
"
<<
o
.
to_string
()
<<
"
\"
"
;
{
else
b3
=
*
reinterpret_cast
<
struct_b
*>
(
res
.
first
);
cout
<<
o
.
to_string
();
}
cout
<<
")"
;
res
.
second
->
delete_instance
(
res
.
first
)
;
}
}
cout
<<
" }"
<<
endl
;
};
plot_objects
({
CPPA_CHECK_EQUAL
(
b1
,
b3
);
cppa
::
uniform_typeid
<
int
>
()
->
create
(),
cppa
::
uniform_typeid
<
std
::
string
>
()
->
create
()
}
});
return
CPPA_TEST_RESULT
;
return
CPPA_TEST_RESULT
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment