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