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
010f3f6b
Commit
010f3f6b
authored
Apr 30, 2011
by
neverlord
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
serialization improvements
parent
123e61f7
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
776 additions
and
363 deletions
+776
-363
cppa/detail/to_uniform_name.hpp
cppa/detail/to_uniform_name.hpp
+2
-0
src/to_uniform_name.cpp
src/to_uniform_name.cpp
+173
-167
unit_testing/test__serialization.cpp
unit_testing/test__serialization.cpp
+601
-196
No files found.
cppa/detail/to_uniform_name.hpp
View file @
010f3f6b
...
@@ -2,10 +2,12 @@
...
@@ -2,10 +2,12 @@
#define TO_UNIFORM_NAME_HPP
#define TO_UNIFORM_NAME_HPP
#include <string>
#include <string>
#include <typeinfo>
namespace
cppa
{
namespace
detail
{
namespace
cppa
{
namespace
detail
{
std
::
string
to_uniform_name
(
const
std
::
string
&
demangled_name
);
std
::
string
to_uniform_name
(
const
std
::
string
&
demangled_name
);
std
::
string
to_uniform_name
(
const
std
::
type_info
&
tinfo
);
}
}
// namespace cppa::detail
}
}
// namespace cppa::detail
...
...
src/to_uniform_name.cpp
View file @
010f3f6b
...
@@ -211,4 +211,10 @@ std::string to_uniform_name(const std::string& dname)
...
@@ -211,4 +211,10 @@ std::string to_uniform_name(const std::string& dname)
return
r
;
return
r
;
}
}
std
::
string
to_uniform_name
(
const
std
::
type_info
&
tinfo
)
{
return
to_uniform_name
(
demangle
(
tinfo
.
name
()));
}
}
}
// namespace cppa::detail
}
}
// namespace cppa::detail
unit_testing/test__serialization.cpp
View file @
010f3f6b
#include <new>
#include <new>
#include <set>
#include <locale>
#include <locale>
#include <memory>
#include <memory>
#include <string>
#include <string>
...
@@ -162,8 +163,6 @@ struct type_to_ptype_impl
...
@@ -162,8 +163,6 @@ struct type_to_ptype_impl
template
<
typename
T
>
template
<
typename
T
>
struct
type_to_ptype
:
type_to_ptype_impl
<
typename
plain
<
T
>::
type
>
{
};
struct
type_to_ptype
:
type_to_ptype_impl
<
typename
plain
<
T
>::
type
>
{
};
namespace
trait
{
template
<
typename
T
>
template
<
typename
T
>
struct
is_primitive
struct
is_primitive
{
{
...
@@ -191,12 +190,58 @@ class is_iterable
...
@@ -191,12 +190,58 @@ class is_iterable
public:
public:
static
const
bool
value
=
!
is_primitive
<
T
>::
value
static
const
bool
value
=
is_primitive
<
T
>::
value
==
false
&&
std
::
is_same
<
bool
,
result_type
>::
value
;
};
template
<
typename
T
>
class
has_push_back
{
template
<
class
C
>
static
bool
cmp_help_fun
(
C
*
arg0
,
decltype
(
arg0
->
push_back
(
typename
C
::
value_type
()))
*
)
{
return
true
;
}
static
void
cmp_help_fun
(
void
*
,
void
*
)
{
}
typedef
decltype
(
cmp_help_fun
(
static_cast
<
T
*>
(
nullptr
),
static_cast
<
void
*>
(
nullptr
)))
result_type
;
public:
static
const
bool
value
=
is_iterable
<
T
>::
value
&&
std
::
is_same
<
bool
,
result_type
>::
value
;
&&
std
::
is_same
<
bool
,
result_type
>::
value
;
};
};
}
// namespace trait
template
<
typename
T
>
class
has_insert
{
template
<
class
C
>
static
bool
cmp_help_fun
(
C
*
arg0
,
decltype
((
arg0
->
insert
(
typename
C
::
value_type
())).
second
)
*
)
{
return
true
;
}
static
void
cmp_help_fun
(
void
*
,
void
*
)
{
}
typedef
decltype
(
cmp_help_fun
(
static_cast
<
T
*>
(
nullptr
),
static_cast
<
bool
*>
(
nullptr
)))
result_type
;
public:
static
const
bool
value
=
is_iterable
<
T
>::
value
&&
std
::
is_same
<
bool
,
result_type
>::
value
;
};
class
pt_value
;
class
pt_value
;
...
@@ -282,7 +327,7 @@ class pt_value
...
@@ -282,7 +327,7 @@ class pt_value
template
<
primitive_type
FT
,
class
T
,
class
V
>
template
<
primitive_type
FT
,
class
T
,
class
V
>
static
void
set
(
primitive_type
&
lhs_type
,
T
&
lhs
,
V
&&
rhs
,
static
void
set
(
primitive_type
&
lhs_type
,
T
&
lhs
,
V
&&
rhs
,
typename
disable_if
<
std
::
is_arithmetic
<
T
>
>::
type
*
=
0
)
typename
disable_if
<
std
::
is_arithmetic
<
T
>
>::
type
*
=
0
)
{
{
if
(
FT
==
lhs_type
)
if
(
FT
==
lhs_type
)
{
{
...
@@ -297,7 +342,7 @@ class pt_value
...
@@ -297,7 +342,7 @@ class pt_value
template
<
primitive_type
FT
,
class
T
,
class
V
>
template
<
primitive_type
FT
,
class
T
,
class
V
>
static
void
set
(
primitive_type
&
lhs_type
,
T
&
lhs
,
V
&&
rhs
,
static
void
set
(
primitive_type
&
lhs_type
,
T
&
lhs
,
V
&&
rhs
,
typename
enable_if
<
std
::
is_arithmetic
<
T
>>::
type
*
=
0
)
typename
enable_if
<
std
::
is_arithmetic
<
T
>
,
int
>::
type
*
=
0
)
{
{
// don't call a constructor for arithmetic types
// don't call a constructor for arithmetic types
lhs
=
rhs
;
lhs
=
rhs
;
...
@@ -305,17 +350,17 @@ class pt_value
...
@@ -305,17 +350,17 @@ class pt_value
}
}
template
<
class
T
>
template
<
class
T
>
static
void
destroy
(
T
&
what
,
inline
static
void
destroy
(
T
&
,
typename
disable_if
<
std
::
is_arithmetic
<
T
>
>::
type
*
=
0
)
typename
enable_if
<
std
::
is_arithmetic
<
T
>
,
int
>::
type
*
=
0
)
{
{
what
.
~
T
();
// arithmetic types don't need destruction
}
}
template
<
class
T
>
template
<
class
T
>
static
void
destroy
(
T
&
,
inline
static
void
destroy
(
T
&
what
,
typename
enable_if
<
std
::
is_arithmetic
<
T
>
>::
type
*
=
0
)
typename
disable_if
<
std
::
is_arithmetic
<
T
>
>::
type
*
=
0
)
{
{
// arithmetic types don't need destruction
what
.
~
T
();
}
}
struct
destroyer
struct
destroyer
...
@@ -447,7 +492,7 @@ class pt_value
...
@@ -447,7 +492,7 @@ class pt_value
pt_value
(
V
&&
value
)
:
m_ptype
(
pt_null
)
pt_value
(
V
&&
value
)
:
m_ptype
(
pt_null
)
{
{
static_assert
(
type_to_ptype
<
V
>::
ptype
!=
pt_null
,
static_assert
(
type_to_ptype
<
V
>::
ptype
!=
pt_null
,
"
T couldn't be mapped to an p
type"
);
"
V is not a primitive
type"
);
set
<
type_to_ptype
<
V
>::
ptype
>
(
m_ptype
,
set
<
type_to_ptype
<
V
>::
ptype
>
(
m_ptype
,
get
(
pt_token
<
type_to_ptype
<
V
>::
ptype
>
()),
get
(
pt_token
<
type_to_ptype
<
V
>::
ptype
>
()),
std
::
forward
<
V
>
(
value
));
std
::
forward
<
V
>
(
value
));
...
@@ -510,30 +555,30 @@ class pt_value
...
@@ -510,30 +555,30 @@ class pt_value
};
};
template
<
typename
T
>
template
<
typename
T
>
typename
enable_if
<
trait
::
is_primitive
<
T
>
,
bool
>::
type
typename
enable_if
<
is_primitive
<
T
>
,
bool
>::
type
operator
==
(
const
T
&
lhs
,
const
pt_value
&
rhs
)
operator
==
(
const
T
&
lhs
,
const
pt_value
&
rhs
)
{
{
constexpr
primitive_type
ptype
=
type_to_ptype
<
T
>::
ptype
;
static
constexpr
primitive_type
ptype
=
type_to_ptype
<
T
>::
ptype
;
static_assert
(
ptype
!=
pt_null
,
"T couldn't be mapped to an ptype"
);
static_assert
(
ptype
!=
pt_null
,
"T couldn't be mapped to an ptype"
);
return
(
rhs
.
ptype
()
==
ptype
)
?
lhs
==
pt_value_cast
<
ptype
>
(
rhs
)
:
false
;
return
(
rhs
.
ptype
()
==
ptype
)
?
lhs
==
pt_value_cast
<
ptype
>
(
rhs
)
:
false
;
}
}
template
<
typename
T
>
template
<
typename
T
>
typename
enable_if
<
trait
::
is_primitive
<
T
>
,
bool
>::
type
typename
enable_if
<
is_primitive
<
T
>
,
bool
>::
type
operator
==
(
const
pt_value
&
lhs
,
const
T
&
rhs
)
operator
==
(
const
pt_value
&
lhs
,
const
T
&
rhs
)
{
{
return
(
rhs
==
lhs
);
return
(
rhs
==
lhs
);
}
}
template
<
typename
T
>
template
<
typename
T
>
typename
enable_if
<
trait
::
is_primitive
<
T
>
,
bool
>::
type
typename
enable_if
<
is_primitive
<
T
>
,
bool
>::
type
operator
!=
(
const
pt_value
&
lhs
,
const
T
&
rhs
)
operator
!=
(
const
pt_value
&
lhs
,
const
T
&
rhs
)
{
{
return
!
(
lhs
==
rhs
);
return
!
(
lhs
==
rhs
);
}
}
template
<
typename
T
>
template
<
typename
T
>
typename
enable_if
<
trait
::
is_primitive
<
T
>
,
bool
>::
type
typename
enable_if
<
is_primitive
<
T
>
,
bool
>::
type
operator
!=
(
const
T
&
lhs
,
const
pt_value
&
rhs
)
operator
!=
(
const
T
&
lhs
,
const
pt_value
&
rhs
)
{
{
return
!
(
lhs
==
rhs
);
return
!
(
lhs
==
rhs
);
...
@@ -613,74 +658,96 @@ class serializer
...
@@ -613,74 +658,96 @@ class serializer
virtual
void
begin_object
(
const
std
::
string
&
type_name
)
=
0
;
virtual
void
begin_object
(
const
std
::
string
&
type_name
)
=
0
;
virtual
void
end_object
()
=
0
;
virtual
void
end_object
()
=
0
;
virtual
void
begin_
list
(
size_t
size
)
=
0
;
virtual
void
begin_
sequence
(
size_t
size
)
=
0
;
virtual
void
end_
list
()
=
0
;
virtual
void
end_
sequence
()
=
0
;
/**
* @brief Writes a single value.
*/
virtual
void
write_value
(
const
pt_value
&
value
)
=
0
;
virtual
void
write_value
(
const
pt_value
&
value
)
=
0
;
};
class
serializer
;
class
deserializer
;
class
meta_type
{
public:
virtual
~
meta_type
()
{
}
/**
/**
* @brief Create an instance of this type, initialized
* @brief Writes @p size values.
* with its default constructor.
*/
*/
virtual
void
*
default_constructed
()
=
0
;
virtual
void
write_tuple
(
size_t
size
,
const
pt_value
*
values
)
=
0
;
virtual
void
delete_instance
(
void
*
)
=
0
;
virtual
void
serialize
(
void
*
,
serializer
*
)
=
0
;
virtual
void
deserialize
(
void
*
,
deserializer
*
)
=
0
;
};
};
std
::
map
<
std
::
string
,
meta_type
*>
s_meta_types
;
/**
*
*/
class
deserializer
class
deserializer
{
{
public:
public:
/**
/**
* @brief Seek the beginning of the next object and return its type name.
* @brief Seek
s
the beginning of the next object and return its type name.
*/
*/
virtual
std
::
string
seek_object
()
=
0
;
virtual
std
::
string
seek_object
()
=
0
;
/**
/**
* @brief
Seek the beginning of the next object and return its type name,
* @brief
Equal to {@link seek_object()} but doesn't
*
but don't
modify the internal in-stream position.
* modify the internal in-stream position.
*/
*/
virtual
std
::
string
peek_object
()
=
0
;
virtual
std
::
string
peek_object
()
=
0
;
virtual
void
begin_object
(
const
std
::
string
&
type_name
)
=
0
;
virtual
void
begin_object
(
const
std
::
string
&
type_name
)
=
0
;
virtual
void
end_object
()
=
0
;
virtual
void
end_object
()
=
0
;
virtual
size_t
begin_
list
(
primitive_type
value_type
)
=
0
;
virtual
size_t
begin_
sequence
(
)
=
0
;
virtual
void
end_
list
()
=
0
;
virtual
void
end_
sequence
()
=
0
;
virtual
pt_value
read_value
(
primitive_type
ptype
)
=
0
;
virtual
pt_value
read_value
(
primitive_type
ptype
)
=
0
;
virtual
void
read_tuple
(
size_t
size
,
const
primitive_type
*
ptypes
,
pt_value
*
storage
)
=
0
;
};
class
meta_type
{
public:
virtual
~
meta_type
()
{
}
/**
* @brief Creates an instance of this type, initialized
* with the default constructor.
*/
virtual
void
*
new_instance
()
const
=
0
;
/**
* @brief Cast @p instance to the native type and delete it.
*/
virtual
void
delete_instance
(
void
*
instance
)
const
=
0
;
/**
* @brief Serializes @p instance to @p sink.
*/
virtual
void
serialize
(
const
void
*
instance
,
serializer
*
sink
)
const
=
0
;
/**
* @brief Deserializes @p instance from @p source.
*/
virtual
void
deserialize
(
void
*
instance
,
deserializer
*
source
)
const
=
0
;
};
};
std
::
map
<
std
::
string
,
meta_type
*>
s_meta_types
;
class
root_object
class
root_object
{
{
public:
public:
std
::
pair
<
void
*
,
meta_type
*>
deserialize
(
deserializer
*
d
)
/**
* @brief Deserializes a new object from @p source and returns the
* new (deserialized) instance with its meta_type.
*/
std
::
pair
<
void
*
,
meta_type
*>
deserialize
(
deserializer
*
source
)
const
{
{
void
*
result
;
void
*
result
;
std
::
string
tname
=
d
->
peek_object
();
std
::
string
tname
=
source
->
peek_object
();
auto
i
=
s_meta_types
.
find
(
tname
);
auto
i
=
s_meta_types
.
find
(
tname
);
if
(
i
==
s_meta_types
.
end
())
if
(
i
==
s_meta_types
.
end
())
{
{
...
@@ -691,14 +758,14 @@ class root_object
...
@@ -691,14 +758,14 @@ class root_object
{
{
throw
std
::
logic_error
(
"mobj == nullptr"
);
throw
std
::
logic_error
(
"mobj == nullptr"
);
}
}
result
=
mobj
->
default_constructed
();
result
=
mobj
->
new_instance
();
if
(
result
==
nullptr
)
if
(
result
==
nullptr
)
{
{
throw
std
::
logic_error
(
"result == nullptr"
);
throw
std
::
logic_error
(
"result == nullptr"
);
}
}
try
try
{
{
mobj
->
deserialize
(
result
,
d
);
mobj
->
deserialize
(
result
,
source
);
}
}
catch
(...)
catch
(...)
{
{
...
@@ -710,8 +777,11 @@ class root_object
...
@@ -710,8 +777,11 @@ class root_object
};
};
/**
* @brief {@link meta_type} implementation for primitive data types.
*/
template
<
typename
T
>
template
<
typename
T
>
class
meta_value_property
:
public
meta_type
class
primitive_member
:
public
meta_type
{
{
static
constexpr
primitive_type
ptype
=
type_to_ptype
<
T
>::
ptype
;
static
constexpr
primitive_type
ptype
=
type_to_ptype
<
T
>::
ptype
;
...
@@ -720,127 +790,324 @@ class meta_value_property : public meta_type
...
@@ -720,127 +790,324 @@ class meta_value_property : public meta_type
public:
public:
meta_value_property
()
{
}
void
*
new_instance
()
const
pt_value
get
(
void
*
obj
)
{
return
*
reinterpret_cast
<
T
*>
(
obj
);
}
void
set
(
void
*
obj
,
pt_value
&&
value
)
{
*
reinterpret_cast
<
T
*>
(
obj
)
=
std
::
move
(
pt_value_cast
<
T
&>
(
value
));
}
void
*
default_constructed
()
{
{
return
new
T
();
return
new
T
();
}
}
void
delete_instance
(
void
*
ptr
)
void
delete_instance
(
void
*
ptr
)
const
{
{
delete
reinterpret_cast
<
T
*>
(
ptr
);
delete
reinterpret_cast
<
T
*>
(
ptr
);
}
}
void
serialize
(
void
*
obj
,
serializer
*
s
)
void
serialize
(
const
void
*
obj
,
serializer
*
s
)
const
{
{
s
->
write_value
(
get
(
obj
));
s
->
write_value
(
*
reinterpret_cast
<
const
T
*>
(
obj
));
}
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
const
{
{
set
(
obj
,
d
->
read_value
(
ptype
));
pt_value
val
(
d
->
read_value
(
ptype
));
*
reinterpret_cast
<
T
*>
(
obj
)
=
std
::
move
(
pt_value_cast
<
T
&>
(
val
));
}
}
};
};
// std::vector or std::list
/**
* @brief {@link meta_type} implementation for STL compliant
* lists (such as std::vector and std::list).
*
* This implementation requires a primitive List::value_type.
*/
template
<
typename
List
>
template
<
typename
List
>
class
meta_list_property
:
public
meta_type
class
list_member
:
public
meta_type
{
{
typedef
typename
List
::
value_type
value_type
;
typedef
typename
List
::
value_type
value_type
;
static
constexpr
primitive_type
vptype
=
type_to_ptype
<
value_type
>::
ptype
;
static
constexpr
primitive_type
vptype
=
type_to_ptype
<
value_type
>::
ptype
;
static_assert
(
vptype
!=
pt_null
,
"T doesn't have a primitive value_type"
);
static_assert
(
vptype
!=
pt_null
,
"List::value_type is not a primitive data type"
);
public:
public:
meta_list_property
()
{
}
void
serialize
(
const
void
*
obj
,
serializer
*
s
)
const
void
serialize
(
void
*
obj
,
serializer
*
s
)
{
{
auto
&
ls
=
*
reinterpret_cast
<
List
*>
(
obj
);
auto
&
ls
=
*
reinterpret_cast
<
const
List
*>
(
obj
);
s
->
begin_
list
(
ls
.
size
());
s
->
begin_
sequence
(
ls
.
size
());
for
(
const
auto
&
val
:
ls
)
for
(
const
auto
&
val
:
ls
)
{
{
s
->
write_value
(
val
);
s
->
write_value
(
val
);
}
}
s
->
end_
list
();
s
->
end_
sequence
();
}
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
const
{
{
auto
&
ls
=
*
reinterpret_cast
<
List
*>
(
obj
);
auto
&
ls
=
*
reinterpret_cast
<
List
*>
(
obj
);
size_t
ls_size
=
d
->
begin_
list
(
vptype
);
size_t
ls_size
=
d
->
begin_
sequence
(
);
for
(
size_t
i
=
0
;
i
<
ls_size
;
++
i
)
for
(
size_t
i
=
0
;
i
<
ls_size
;
++
i
)
{
{
pt_value
val
=
d
->
read_value
(
vptype
);
pt_value
val
=
d
->
read_value
(
vptype
);
ls
.
push_back
(
std
::
move
(
pt_value_cast
<
value_type
&>
(
val
)));
ls
.
push_back
(
std
::
move
(
pt_value_cast
<
value_type
&>
(
val
)));
}
}
d
->
end_
list
();
d
->
end_
sequence
();
}
}
void
*
default_constructed
()
void
*
new_instance
()
const
{
{
return
new
List
();
return
new
List
();
}
}
void
delete_instance
(
void
*
ptr
)
void
delete_instance
(
void
*
ptr
)
const
{
{
delete
reinterpret_cast
<
List
*>
(
ptr
);
delete
reinterpret_cast
<
List
*>
(
ptr
);
}
}
};
};
template
<
class
Object
>
/**
class
meta_object
:
public
meta_type
* @brief {@link meta_type} implementation for std::pair.
*/
template
<
typename
T1
,
typename
T2
>
class
pair_member
:
public
meta_type
{
static
constexpr
primitive_type
ptype1
=
type_to_ptype
<
T1
>::
ptype
;
static
constexpr
primitive_type
ptype2
=
type_to_ptype
<
T2
>::
ptype
;
static_assert
(
ptype1
!=
pt_null
,
"T1 is not a primitive type"
);
static_assert
(
ptype2
!=
pt_null
,
"T2 is not a primitive type"
);
typedef
std
::
pair
<
T1
,
T2
>
pair_type
;
public:
void
serialize
(
const
void
*
obj
,
serializer
*
s
)
const
{
auto
&
p
=
*
reinterpret_cast
<
const
pair_type
*>
(
obj
);
pt_value
values
[
2
]
=
{
p
.
first
,
p
.
second
};
s
->
write_tuple
(
2
,
values
);
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
const
{
primitive_type
ptypes
[
2
]
=
{
ptype1
,
ptype2
};
pt_value
values
[
2
];
d
->
read_tuple
(
2
,
ptypes
,
values
);
auto
&
p
=
*
reinterpret_cast
<
pair_type
*>
(
obj
);
p
.
first
=
std
::
move
(
pt_value_cast
<
T1
&>
(
values
[
0
]));
p
.
second
=
std
::
move
(
pt_value_cast
<
T2
&>
(
values
[
1
]));
}
void
*
new_instance
()
const
{
return
new
pair_type
();
}
void
delete_instance
(
void
*
ptr
)
const
{
delete
reinterpret_cast
<
pair_type
*>
(
ptr
);
}
};
// matches value_type of std::set
template
<
typename
T
>
struct
meta_value_type
{
primitive_member
<
T
>
impl
;
void
serialize_value
(
const
T
&
what
,
serializer
*
s
)
const
{
impl
.
serialize
(
&
what
,
s
);
}
template
<
typename
M
>
void
deserialize_and_insert
(
M
&
map
,
deserializer
*
d
)
const
{
T
value
;
impl
.
deserialize
(
&
value
,
d
);
map
.
insert
(
std
::
move
(
value
));
}
};
// matches value_type of std::map
template
<
typename
T1
,
typename
T2
>
struct
meta_value_type
<
std
::
pair
<
const
T1
,
T2
>>
{
pair_member
<
T1
,
T2
>
impl
;
void
serialize_value
(
const
std
::
pair
<
const
T1
,
T2
>&
what
,
serializer
*
s
)
const
{
std
::
pair
<
T1
,
T2
>
p
(
what
.
first
,
what
.
second
);
impl
.
serialize
(
&
p
,
s
);
}
template
<
typename
M
>
void
deserialize_and_insert
(
M
&
map
,
deserializer
*
d
)
const
{
std
::
pair
<
T1
,
T2
>
p
;
impl
.
deserialize
(
&
p
,
d
);
std
::
pair
<
const
T1
,
T2
>
v
(
std
::
move
(
p
.
first
),
std
::
move
(
p
.
second
));
map
.
insert
(
std
::
move
(
v
));
}
};
/**
* @brief {@link meta_type} implementation for STL compliant
* maps (such as std::map and std::set).
*
* This implementation requires primitive key and value types
* (or a pair of primitive types as value type).
*/
template
<
typename
Map
>
class
map_member
:
public
meta_type
{
typedef
typename
Map
::
key_type
key_type
;
typedef
typename
Map
::
value_type
value_type
;
meta_value_type
<
value_type
>
m_value_type_meta
;
public:
void
serialize
(
const
void
*
obj
,
serializer
*
s
)
const
{
auto
&
mp
=
*
reinterpret_cast
<
const
Map
*>
(
obj
);
s
->
begin_sequence
(
mp
.
size
());
for
(
const
auto
&
val
:
mp
)
{
m_value_type_meta
.
serialize_value
(
val
,
s
);
}
s
->
end_sequence
();
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
const
{
auto
&
mp
=
*
reinterpret_cast
<
Map
*>
(
obj
);
size_t
mp_size
=
d
->
begin_sequence
();
for
(
size_t
i
=
0
;
i
<
mp_size
;
++
i
)
{
m_value_type_meta
.
deserialize_and_insert
(
mp
,
d
);
}
d
->
end_sequence
();
}
void
*
new_instance
()
const
{
return
new
Map
();
}
void
delete_instance
(
void
*
ptr
)
const
{
delete
reinterpret_cast
<
Map
*>
(
ptr
);
}
};
/**
* @brief {@link meta_type} implementation for user-defined structs.
*/
template
<
class
Struct
>
class
meta_struct
:
public
meta_type
{
{
template
<
typename
T
>
struct
is_invalid
{
static
const
bool
value
=
!
is_primitive
<
T
>::
value
&&
!
has_push_back
<
T
>::
value
&&
!
has_insert
<
T
>::
value
;
};
class
member
class
member
{
{
meta_type
*
m_meta
;
meta_type
*
m_meta
;
std
::
function
<
void
*
(
void
*
)
>
m_deref
;
std
::
function
<
void
(
const
meta_type
*
,
const
void
*
,
serializer
*
)
>
m_serialize
;
std
::
function
<
void
(
const
meta_type
*
,
void
*
,
deserializer
*
)
>
m_deserialize
;
member
(
const
member
&
)
=
delete
;
member
&
operator
=
(
const
member
&
)
=
delete
;
void
swap
(
member
&
other
)
{
std
::
swap
(
m_meta
,
other
.
m_meta
);
std
::
swap
(
m_serialize
,
other
.
m_serialize
);
std
::
swap
(
m_deserialize
,
other
.
m_deserialize
);
}
template
<
typename
S
,
class
D
>
member
(
meta_type
*
mtptr
,
S
&&
s
,
D
&&
d
)
:
m_meta
(
mtptr
)
,
m_serialize
(
std
::
forward
<
S
>
(
s
))
,
m_deserialize
(
std
::
forward
<
D
>
(
d
))
{
}
public:
public:
template
<
typename
T
,
class
C
>
template
<
typename
T
,
class
C
>
member
(
meta_type
*
mtptr
,
T
C
::*
mem_ptr
)
:
m_meta
(
mtptr
)
member
(
meta_type
*
mtptr
,
T
C
::*
mem_ptr
)
:
m_meta
(
mtptr
)
{
{
m_deref
=
[
mem_ptr
]
(
void
*
obj
)
->
void
*
m_serialize
=
[
mem_ptr
]
(
const
meta_type
*
mt
,
const
void
*
obj
,
serializer
*
s
)
{
{
return
&
(
*
reinterpret_cast
<
C
*>
(
obj
).
*
mem_ptr
);
mt
->
serialize
(
&
(
*
reinterpret_cast
<
const
C
*>
(
obj
).
*
mem_ptr
),
s
);
};
m_deserialize
=
[
mem_ptr
]
(
const
meta_type
*
mt
,
void
*
obj
,
deserializer
*
d
)
{
mt
->
deserialize
(
&
(
*
reinterpret_cast
<
C
*>
(
obj
).
*
mem_ptr
),
d
);
};
};
}
}
member
(
meta_type
*
pptr
,
std
::
function
<
void
*
(
void
*
)
>&&
gpm
)
member
(
member
&&
other
)
:
m_meta
(
nullptr
)
:
m_meta
(
pptr
),
m_deref
(
std
::
move
(
gpm
))
{
swap
(
other
);
}
// a member that's not a member at all, but "forwards"
// the 'self' pointer to make use *_member implementations
static
member
fake_member
(
meta_type
*
mtptr
)
{
return
{
mtptr
,
[]
(
const
meta_type
*
mt
,
const
void
*
obj
,
serializer
*
s
)
{
{
mt
->
serialize
(
obj
,
s
);
},
[]
(
const
meta_type
*
mt
,
void
*
obj
,
deserializer
*
d
)
{
mt
->
deserialize
(
obj
,
d
);
}
};
}
}
member
(
member
&&
)
=
default
;
~
member
()
{
delete
m_meta
;
}
member
(
const
member
&
)
=
default
;
member
&
operator
=
(
member
&&
other
)
{
swap
(
other
);
return
*
this
;
}
inline
void
serialize
(
void
*
parent
,
serializer
*
s
)
inline
void
serialize
(
const
void
*
parent
,
serializer
*
s
)
const
{
{
m_
meta
->
serialize
(
m_deref
(
parent
)
,
s
);
m_
serialize
(
m_meta
,
parent
,
s
);
}
}
inline
void
deserialize
(
void
*
parent
,
deserializer
*
s
)
inline
void
deserialize
(
void
*
parent
,
deserializer
*
d
)
const
{
{
m_
meta
->
deserialize
(
m_deref
(
parent
),
s
);
m_
deserialize
(
m_meta
,
parent
,
d
);
}
}
};
};
...
@@ -851,47 +1118,75 @@ class meta_object : public meta_type
...
@@ -851,47 +1118,75 @@ class meta_object : public meta_type
// terminates recursion
// terminates recursion
inline
void
push_back
()
{
}
inline
void
push_back
()
{
}
// pr.first = member pointer
// pr.second = meta object to handle pr.first
template
<
typename
T
,
class
C
,
typename
...
Args
>
template
<
typename
T
,
class
C
,
typename
...
Args
>
void
push_back
(
std
::
pair
<
T
C
::*
,
meta_
obje
ct
<
T
>*>
pr
,
const
Args
&
...
args
)
void
push_back
(
std
::
pair
<
T
C
::*
,
meta_
stru
ct
<
T
>*>
pr
,
const
Args
&
...
args
)
{
{
m_members
.
push_back
({
pr
.
second
,
pr
.
first
});
m_members
.
push_back
({
pr
.
second
,
pr
.
first
});
push_back
(
args
...);
push_back
(
args
...);
}
}
template
<
class
C
,
typename
T
,
typename
...
Args
>
template
<
class
C
,
typename
T
,
typename
...
Args
>
typename
enable_if
<
trait
::
is_primitive
<
T
>
>::
type
typename
enable_if
<
is_primitive
<
T
>
>::
type
push_back
(
T
C
::*
mem_ptr
,
const
Args
&
...
args
)
push_back
(
T
C
::*
mem_ptr
,
const
Args
&
...
args
)
{
{
m_members
.
push_back
({
new
meta_value_property
<
T
>
(),
mem_ptr
});
m_members
.
push_back
({
new
primitive_member
<
T
>
(),
mem_ptr
});
push_back
(
args
...);
push_back
(
args
...);
}
}
template
<
class
C
,
typename
T
,
typename
...
Args
>
template
<
class
C
,
typename
T
,
typename
...
Args
>
typename
enable_if
<
trait
::
is_iterable
<
T
>
>::
type
typename
enable_if
<
has_push_back
<
T
>
>::
type
push_back
(
T
C
::*
mem_ptr
,
const
Args
&
...
args
)
push_back
(
T
C
::*
mem_ptr
,
const
Args
&
...
args
)
{
{
m_members
.
push_back
({
new
meta_list_property
<
T
>
(),
mem_ptr
});
m_members
.
push_back
({
new
list_member
<
T
>
(),
mem_ptr
});
push_back
(
args
...);
push_back
(
args
...);
}
}
template
<
class
C
,
typename
T
,
typename
...
Args
>
template
<
class
C
,
typename
T
,
typename
...
Args
>
typename
disable_if_c
<
trait
::
is_primitive
<
T
>::
value
typename
enable_if
<
has_insert
<
T
>
>::
type
||
trait
::
is_iterable
<
T
>::
value
,
void
>::
type
push_back
(
T
C
::*
mem_ptr
,
const
Args
&
...
args
)
push_back
(
T
C
::*
mem_ptr
,
const
Args
&
...
args
)
{
{
static_assert
(
trait
::
is_primitive
<
T
>::
value
,
m_members
.
push_back
({
new
map_member
<
T
>
(),
mem_ptr
});
"T is neither a primitive type nor an iterable type"
);
push_back
(
args
...);
}
template
<
class
C
,
typename
T
,
typename
...
Args
>
typename
enable_if
<
is_invalid
<
T
>>::
type
push_back
(
T
C
::*
mem_ptr
,
const
Args
&
...
args
)
{
static_assert
(
is_primitive
<
T
>::
value
,
"T is neither a primitive type nor a list nor a map"
);
}
template
<
typename
T
>
void
init_
(
typename
enable_if
<
is_primitive
<
T
>>::
type
*
=
nullptr
)
{
m_members
.
push_back
(
member
::
fake_member
(
new
primitive_member
<
T
>
()));
}
template
<
typename
T
>
void
init_
(
typename
disable_if
<
is_primitive
<
T
>>::
type
*
=
nullptr
)
{
static_assert
(
is_primitive
<
T
>::
value
,
"T is neither a primitive type nor a list nor a map"
);
}
}
public:
public:
template
<
typename
...
Args
>
template
<
typename
...
Args
>
meta_object
(
const
Args
&
...
args
)
:
class_name
(
cppa
::
detail
::
to_uniform_name
(
cppa
::
detail
::
demangle
(
typeid
(
Object
).
name
())))
meta_struct
(
const
Args
&
...
args
)
:
class_name
(
cppa
::
detail
::
to_uniform_name
(
typeid
(
Struct
)))
{
{
push_back
(
args
...);
push_back
(
args
...);
}
}
void
serialize
(
void
*
obj
,
serializer
*
s
)
meta_struct
()
:
class_name
(
cppa
::
detail
::
to_uniform_name
(
typeid
(
Struct
)))
{
init_
<
Struct
>
();
}
void
serialize
(
const
void
*
obj
,
serializer
*
s
)
const
{
{
s
->
begin_object
(
class_name
);
s
->
begin_object
(
class_name
);
for
(
auto
&
m
:
m_members
)
for
(
auto
&
m
:
m_members
)
...
@@ -901,7 +1196,7 @@ class meta_object : public meta_type
...
@@ -901,7 +1196,7 @@ class meta_object : public meta_type
s
->
end_object
();
s
->
end_object
();
}
}
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
void
deserialize
(
void
*
obj
,
deserializer
*
d
)
const
{
{
std
::
string
cname
=
d
->
seek_object
();
std
::
string
cname
=
d
->
seek_object
();
if
(
cname
!=
class_name
)
if
(
cname
!=
class_name
)
...
@@ -916,14 +1211,14 @@ class meta_object : public meta_type
...
@@ -916,14 +1211,14 @@ class meta_object : public meta_type
d
->
end_object
();
d
->
end_object
();
}
}
void
*
default_constructed
()
void
*
new_instance
()
const
{
{
return
new
Obje
ct
();
return
new
Stru
ct
();
}
}
void
delete_instance
(
void
*
ptr
)
void
delete_instance
(
void
*
ptr
)
const
{
{
delete
reinterpret_cast
<
Obje
ct
*>
(
ptr
);
delete
reinterpret_cast
<
Stru
ct
*>
(
ptr
);
}
}
};
};
...
@@ -961,10 +1256,20 @@ bool operator!=(const struct_b& lhs, const struct_b& rhs)
...
@@ -961,10 +1256,20 @@ bool operator!=(const struct_b& lhs, const struct_b& rhs)
return
!
(
lhs
==
rhs
);
return
!
(
lhs
==
rhs
);
}
}
template
<
class
C
,
class
Parent
,
typename
...
Args
>
struct
struct_c
std
::
pair
<
C
Parent
::*
,
meta_object
<
C
>*>
compound_member
(
C
Parent
::*
c_ptr
,
const
Args
&
...
args
)
{
{
return
std
::
make_pair
(
c_ptr
,
new
meta_object
<
C
>
(
args
...));
std
::
map
<
std
::
string
,
std
::
u16string
>
strings
;
std
::
set
<
int
>
ints
;
};
bool
operator
==
(
const
struct_c
&
lhs
,
const
struct_c
&
rhs
)
{
return
lhs
.
strings
==
rhs
.
strings
&&
lhs
.
ints
==
rhs
.
ints
;
}
bool
operator
!=
(
const
struct_c
&
lhs
,
const
struct_c
&
rhs
)
{
return
!
(
lhs
==
rhs
);
}
}
class
string_serializer
:
public
serializer
class
string_serializer
:
public
serializer
...
@@ -1024,22 +1329,15 @@ class string_serializer : public serializer
...
@@ -1024,22 +1329,15 @@ class string_serializer : public serializer
out
<<
" )"
;
out
<<
" )"
;
}
}
void
begin_
list
(
size_t
)
void
begin_
sequence
(
size_t
)
{
{
clear
();
clear
();
out
<<
"{ "
;
out
<<
"{ "
;
}
}
void
end_
list
()
void
end_
sequence
()
{
{
if
(
!
m_after_value
)
out
<<
(
m_after_value
?
" }"
:
"}"
);
{
out
<<
"}"
;
}
else
{
out
<<
" }"
;
}
}
}
void
write_value
(
const
pt_value
&
value
)
void
write_value
(
const
pt_value
&
value
)
...
@@ -1049,8 +1347,21 @@ class string_serializer : public serializer
...
@@ -1049,8 +1347,21 @@ class string_serializer : public serializer
m_after_value
=
true
;
m_after_value
=
true
;
}
}
void
write_tuple
(
size_t
size
,
const
pt_value
*
values
)
{
clear
();
out
<<
" {"
;
const
pt_value
*
end
=
values
+
size
;
for
(
;
values
!=
end
;
++
values
)
{
write_value
(
*
values
);
}
out
<<
(
m_after_value
?
" }"
:
"}"
);
}
};
};
/*
class xml_serializer : public serializer
class xml_serializer : public serializer
{
{
...
@@ -1126,6 +1437,7 @@ class xml_serializer : public serializer
...
@@ -1126,6 +1437,7 @@ class xml_serializer : public serializer
}
}
};
};
*/
class
binary_serializer
:
public
serializer
class
binary_serializer
:
public
serializer
{
{
...
@@ -1135,40 +1447,52 @@ class binary_serializer : public serializer
...
@@ -1135,40 +1447,52 @@ class binary_serializer : public serializer
buf_type
m_buf
;
buf_type
m_buf
;
size_t
m_wr_pos
;
size_t
m_wr_pos
;
struct
pt_writer
template
<
typename
T
>
void
write
(
const
T
&
value
)
{
{
memcpy
(
m_buf
+
m_wr_pos
,
&
value
,
sizeof
(
T
));
m_wr_pos
+=
sizeof
(
T
);
}
buf_type
&
m_buf
;
void
write
(
const
std
::
string
&
str
)
size_t
&
m_wr_pos
;
{
write
(
static_cast
<
std
::
uint32_t
>
(
str
.
size
()));
memcpy
(
m_buf
+
m_wr_pos
,
str
.
c_str
(),
str
.
size
());
m_wr_pos
+=
str
.
size
();
}
pt_writer
(
buf_type
&
buf
,
size_t
&
pos
)
:
m_buf
(
buf
),
m_wr_pos
(
pos
)
{
}
void
write
(
const
std
::
u16string
&
str
)
{
write
(
static_cast
<
std
::
uint32_t
>
(
str
.
size
()));
for
(
char16_t
c
:
str
)
{
write
(
static_cast
<
std
::
uint16_t
>
(
c
));
}
}
template
<
typename
T
>
void
write
(
const
std
::
u32string
&
str
)
void
operator
()(
const
T
&
value
)
{
{
memcpy
(
m_buf
+
m_wr_pos
,
&
value
,
sizeof
(
T
));
write
(
static_cast
<
std
::
uint32_t
>
(
str
.
size
()));
m_wr_pos
+=
sizeof
(
T
);
for
(
char32_t
c
:
str
)
{
write
(
static_cast
<
std
::
uint32_t
>
(
c
));
}
}
}
void
operator
()(
const
std
::
u16string
&
)
{
}
struct
pt_writer
{
void
operator
()(
const
std
::
u32string
&
)
{
}
binary_serializer
*
self
;
};
inline
pt_writer
(
binary_serializer
*
mself
)
:
self
(
mself
)
{
}
template
<
typename
T
>
template
<
typename
T
>
void
write
(
const
T
&
value
)
inline
void
operator
()
(
const
T
&
value
)
{
{
memcpy
(
m_buf
+
m_wr_pos
,
&
value
,
sizeof
(
T
));
self
->
write
(
value
);
m_wr_pos
+=
sizeof
(
T
);
}
}
void
write
(
const
std
::
string
&
str
)
};
{
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:
public:
...
@@ -1179,18 +1503,31 @@ class binary_serializer : public serializer
...
@@ -1179,18 +1503,31 @@ class binary_serializer : public serializer
write
(
tname
);
write
(
tname
);
}
}
void
end_object
()
{
}
void
end_object
()
{
}
void
begin_
list
(
size_t
list_size
)
void
begin_
sequence
(
size_t
list_size
)
{
{
write
(
static_cast
<
std
::
uint32_t
>
(
list_size
));
write
(
static_cast
<
std
::
uint32_t
>
(
list_size
));
}
}
void
end_list
()
{
}
void
end_sequence
()
{
}
void
write_value
(
const
pt_value
&
value
)
void
write_value
(
const
pt_value
&
value
)
{
{
value
.
apply
(
pt_writer
(
m_buf
,
m_wr_pos
));
value
.
apply
(
pt_writer
(
this
));
}
void
write_tuple
(
size_t
size
,
const
pt_value
*
values
)
{
const
pt_value
*
end
=
values
+
size
;
for
(
;
values
!=
end
;
++
values
)
{
write_value
(
*
values
);
}
}
}
};
};
...
@@ -1252,7 +1589,7 @@ class binary_deserializer : public deserializer
...
@@ -1252,7 +1589,7 @@ class binary_deserializer : public deserializer
{
{
CharType
c
;
CharType
c
;
read
(
c
);
read
(
c
);
str
_size
+=
static_cast
<
typename
StringType
::
value_type
>
(
c
);
str
+=
static_cast
<
typename
StringType
::
value_type
>
(
c
);
}
}
}
}
...
@@ -1310,14 +1647,14 @@ class binary_deserializer : public deserializer
...
@@ -1310,14 +1647,14 @@ class binary_deserializer : public deserializer
{
{
}
}
size_t
begin_
list
(
primitive_type
)
size_t
begin_
sequence
(
)
{
{
std
::
uint32_t
size
;
std
::
uint32_t
size
;
read
(
size
);
read
(
size
);
return
size
;
return
size
;
}
}
void
end_
list
()
void
end_
sequence
()
{
{
}
}
...
@@ -1328,6 +1665,18 @@ class binary_deserializer : public deserializer
...
@@ -1328,6 +1665,18 @@ class binary_deserializer : public deserializer
return
val
;
return
val
;
}
}
void
read_tuple
(
size_t
size
,
const
primitive_type
*
ptypes
,
pt_value
*
storage
)
{
const
primitive_type
*
end
=
ptypes
+
size
;
for
(
;
ptypes
!=
end
;
++
ptypes
)
{
*
storage
=
std
::
move
(
read_value
(
*
ptypes
));
++
storage
;
}
}
};
};
class
string_deserializer
:
public
deserializer
class
string_deserializer
:
public
deserializer
...
@@ -1440,14 +1789,14 @@ class string_deserializer : public deserializer
...
@@ -1440,14 +1789,14 @@ class string_deserializer : public deserializer
}
}
}
}
size_t
begin_
list
(
primitive_type
)
size_t
begin_
sequence
(
)
{
{
consume
(
'{'
);
consume
(
'{'
);
auto
list_end
=
std
::
find
(
m_pos
,
m_str
.
end
(),
'}'
);
auto
list_end
=
std
::
find
(
m_pos
,
m_str
.
end
(),
'}'
);
return
std
::
count
(
m_pos
,
list_end
,
','
)
+
1
;
return
std
::
count
(
m_pos
,
list_end
,
','
)
+
1
;
}
}
void
end_
list
()
void
end_
sequence
()
{
{
consume
(
'}'
);
consume
(
'}'
);
}
}
...
@@ -1490,10 +1839,23 @@ class string_deserializer : public deserializer
...
@@ -1490,10 +1839,23 @@ class string_deserializer : public deserializer
return
result
;
return
result
;
}
}
void
foo
()
{}
void
read_tuple
(
size_t
size
,
const
primitive_type
*
begin
,
pt_value
*
storage
)
{
consume
(
'{'
);
const
primitive_type
*
end
=
begin
+
size
;
for
(
;
begin
!=
end
;
++
begin
)
{
*
storage
=
std
::
move
(
read_value
(
*
begin
));
++
storage
;
}
consume
(
'}'
);
}
};
};
template
<
typename
T
>
std
::
string
to_string
(
void
*
what
,
meta_type
*
mobj
)
std
::
string
to_string
(
T
*
what
,
meta_object
<
T
>*
mobj
)
{
{
std
::
ostringstream
osstr
;
std
::
ostringstream
osstr
;
string_serializer
strs
(
osstr
);
string_serializer
strs
(
osstr
);
...
@@ -1501,17 +1863,30 @@ std::string to_string(T* what, meta_object<T>* mobj)
...
@@ -1501,17 +1863,30 @@ std::string to_string(T* what, meta_object<T>* mobj)
return
osstr
.
str
();
return
osstr
.
str
();
}
}
std
::
size_t
test__serialization
()
template
<
class
C
,
class
Parent
,
typename
...
Args
>
std
::
pair
<
C
Parent
::*
,
meta_struct
<
C
>*>
compound_member
(
C
Parent
::*
c_ptr
,
const
Args
&
...
args
)
{
{
return
std
::
make_pair
(
c_ptr
,
new
meta_struct
<
C
>
(
args
...));
}
template
<
class
C
,
typename
...
Args
>
meta_type
*
meta_object
(
const
Args
&
...
args
)
{
return
new
meta_struct
<
C
>
(
args
...);
}
std
::
size_t
test__serialization
()
{
CPPA_TEST
(
test__serialization
);
CPPA_TEST
(
test__serialization
);
CPPA_CHECK_EQUAL
((
trait
::
is_iterable
<
int
>::
value
),
false
);
CPPA_CHECK_EQUAL
((
is_iterable
<
int
>::
value
),
false
);
// std::string is primitive and thus not identified by is_iterable
// std::string is primitive and thus not identified by is_iterable
CPPA_CHECK_EQUAL
((
trait
::
is_iterable
<
std
::
string
>::
value
),
false
);
CPPA_CHECK_EQUAL
((
is_iterable
<
std
::
string
>::
value
),
false
);
CPPA_CHECK_EQUAL
((
trait
::
is_iterable
<
std
::
list
<
int
>>::
value
),
true
);
CPPA_CHECK_EQUAL
((
is_iterable
<
std
::
list
<
int
>>::
value
),
true
);
CPPA_CHECK_EQUAL
((
trait
::
is_iterable
<
std
::
map
<
int
,
int
>>::
value
),
true
);
CPPA_CHECK_EQUAL
((
is_iterable
<
std
::
map
<
int
,
int
>>::
value
),
true
);
// test pt_value implementation
// test pt_value implementation
{
{
pt_value
v1
(
42
);
pt_value
v1
(
42
);
...
@@ -1522,69 +1897,99 @@ std::size_t test__serialization()
...
@@ -1522,69 +1897,99 @@ std::size_t test__serialization()
// type mismatch => unequal
// type mismatch => unequal
CPPA_CHECK
(
v2
!=
static_cast
<
std
::
int8_t
>
(
42
));
CPPA_CHECK
(
v2
!=
static_cast
<
std
::
int8_t
>
(
42
));
}
}
root_object
root
;
root_object
root
;
// test meta_struct implementation for primitive types
// test serializers / deserializers
{
{
meta_struct
<
std
::
uint32_t
>
meta_int
;
meta_object
<
struct_b
>
meta_b
{
auto
i
=
meta_int
.
new_instance
();
compound_member
(
&
struct_b
::
a
,
&
struct_a
::
x
,
&
struct_a
::
y
),
auto
str
=
to_string
(
i
,
&
meta_int
);
meta_int
.
delete_instance
(
i
);
cout
<<
"str: "
<<
str
<<
endl
;
}
// test serializers / deserializers with struct_b
{
// get meta object for struct_b
auto
meta_b
=
meta_object
<
struct_b
>
(
compound_member
(
&
struct_b
::
a
,
&
struct_a
::
x
,
&
struct_a
::
y
),
&
struct_b
::
z
,
&
struct_b
::
z
,
&
struct_b
::
ints
&
struct_b
::
ints
);
};
// "announce" meta types
// "announce" meta types
s_meta_types
[
"struct_b"
]
=
&
meta_b
;
s_meta_types
[
"struct_b"
]
=
meta_b
;
// testees
struct_b
b1
=
{
{
1
,
2
},
3
,
{
4
,
5
,
6
,
7
,
8
,
9
,
10
}
};
struct_b
b1
=
{
{
1
,
2
},
3
,
{
4
,
5
,
6
,
7
,
8
,
9
,
10
}
};
struct_b
b2
;
struct_b
b2
;
struct_b
b3
;
struct_b
b3
;
// expected result of to_string(&b1, meta_b)
auto
b1str
=
"struct_b ( struct_a ( 1, 2 ), 3, "
auto
b1str
=
"struct_b ( struct_a ( 1, 2 ), 3, "
"{ 4, 5, 6, 7, 8, 9, 10 } )"
;
"{ 4, 5, 6, 7, 8, 9, 10 } )"
;
// verify
CPPA_CHECK_EQUAL
((
to_string
(
&
b1
,
&
meta_b
)),
b1str
);
CPPA_CHECK_EQUAL
((
to_string
(
&
b1
,
meta_b
)),
b1str
);
// binary buffer
char
buf
[
512
];
char
buf
[
512
];
// serialize b1 to buf
// serialize b1 to buf
{
{
binary_serializer
bs
(
buf
);
binary_serializer
bs
(
buf
);
meta_b
.
serialize
(
&
b1
,
&
bs
);
meta_b
->
serialize
(
&
b1
,
&
bs
);
}
}
// deserialize b2 from buf
// deserialize b2 from buf
{
{
binary_deserializer
bd
(
buf
,
512
);
binary_deserializer
bd
(
buf
,
512
);
auto
res
=
root
.
deserialize
(
&
bd
);
auto
res
=
root
.
deserialize
(
&
bd
);
CPPA_CHECK_EQUAL
(
res
.
second
,
&
meta_b
);
CPPA_CHECK_EQUAL
(
res
.
second
,
meta_b
);
if
(
res
.
second
==
&
meta_b
)
if
(
res
.
second
==
meta_b
)
{
{
b2
=
*
reinterpret_cast
<
struct_b
*>
(
res
.
first
);
b2
=
*
reinterpret_cast
<
struct_b
*>
(
res
.
first
);
}
}
res
.
second
->
delete_instance
(
res
.
first
);
res
.
second
->
delete_instance
(
res
.
first
);
}
}
// verify result of serialization / deserialization
CPPA_CHECK_EQUAL
(
b1
,
b2
);
CPPA_CHECK_EQUAL
(
b1
,
b2
);
CPPA_CHECK_EQUAL
((
to_string
(
&
b2
,
&
meta_b
)),
b1str
);
CPPA_CHECK_EQUAL
((
to_string
(
&
b2
,
meta_b
)),
b1str
);
// deserialize b3 from string, using string_deserializer
// deserialize b3 from string, using string_deserializer
{
{
string_deserializer
strd
(
b1str
);
string_deserializer
strd
(
b1str
);
auto
res
=
root
.
deserialize
(
&
strd
);
auto
res
=
root
.
deserialize
(
&
strd
);
CPPA_CHECK_EQUAL
(
res
.
second
,
&
meta_b
);
CPPA_CHECK_EQUAL
(
res
.
second
,
meta_b
);
if
(
res
.
second
==
&
meta_b
)
if
(
res
.
second
==
meta_b
)
{
{
b3
=
*
reinterpret_cast
<
struct_b
*>
(
res
.
first
);
b3
=
*
reinterpret_cast
<
struct_b
*>
(
res
.
first
);
}
}
res
.
second
->
delete_instance
(
res
.
first
);
res
.
second
->
delete_instance
(
res
.
first
);
}
}
CPPA_CHECK_EQUAL
(
b1
,
b3
);
CPPA_CHECK_EQUAL
(
b1
,
b3
);
// cleanup
s_meta_types
.
clear
();
delete
meta_b
;
}
// test serializers / deserializers with struct_c
{
// get meta type of struct_c and "announce"
auto
meta_c
=
meta_object
<
struct_c
>
(
&
struct_c
::
strings
,
&
struct_c
::
ints
);
s_meta_types
[
"struct_c"
]
=
meta_c
;
// testees
struct_c
c1
=
{
{
{
"abc"
,
u"cba"
},
{
"x"
,
u"y"
}
},
{
9
,
4
,
5
}
};
struct_c
c2
;
// binary buffer
char
buf
[
512
];
// serialize c1 to buf
{
binary_serializer
bs
(
buf
);
meta_c
->
serialize
(
&
c1
,
&
bs
);
}
// serialize c2 from buf
{
binary_deserializer
bd
(
buf
,
512
);
auto
res
=
root
.
deserialize
(
&
bd
);
CPPA_CHECK_EQUAL
(
res
.
second
,
meta_c
);
if
(
res
.
second
==
meta_c
)
{
c2
=
*
reinterpret_cast
<
struct_c
*>
(
res
.
first
);
}
res
.
second
->
delete_instance
(
res
.
first
);
}
// verify result of serialization / deserialization
CPPA_CHECK_EQUAL
(
c1
,
c2
);
}
}
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