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
59ed7e08
Commit
59ed7e08
authored
Sep 03, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement new settings writer
parent
2d771bf0
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1252 additions
and
349 deletions
+1252
-349
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+3
-0
libcaf_core/caf/binary_deserializer.hpp
libcaf_core/caf/binary_deserializer.hpp
+16
-0
libcaf_core/caf/binary_serializer.hpp
libcaf_core/caf/binary_serializer.hpp
+16
-0
libcaf_core/caf/deserializer.hpp
libcaf_core/caf/deserializer.hpp
+17
-0
libcaf_core/caf/detail/stringification_inspector.hpp
libcaf_core/caf/detail/stringification_inspector.hpp
+22
-2
libcaf_core/caf/hash/fnv.hpp
libcaf_core/caf/hash/fnv.hpp
+16
-0
libcaf_core/caf/inspector_access.hpp
libcaf_core/caf/inspector_access.hpp
+10
-11
libcaf_core/caf/serializer.hpp
libcaf_core/caf/serializer.hpp
+17
-0
libcaf_core/caf/settings_writer.hpp
libcaf_core/caf/settings_writer.hpp
+146
-0
libcaf_core/src/deserializer.cpp
libcaf_core/src/deserializer.cpp
+16
-0
libcaf_core/src/detail/stringification_inspector.cpp
libcaf_core/src/detail/stringification_inspector.cpp
+0
-8
libcaf_core/src/serializer.cpp
libcaf_core/src/serializer.cpp
+16
-0
libcaf_core/src/settings_writer.cpp
libcaf_core/src/settings_writer.cpp
+438
-0
libcaf_core/src/type_id.cpp
libcaf_core/src/type_id.cpp
+39
-0
libcaf_core/test/inspector-tests.hpp
libcaf_core/test/inspector-tests.hpp
+178
-0
libcaf_core/test/load_inspector.cpp
libcaf_core/test/load_inspector.cpp
+123
-163
libcaf_core/test/save_inspector.cpp
libcaf_core/test/save_inspector.cpp
+42
-156
libcaf_core/test/settings_writer.cpp
libcaf_core/test/settings_writer.cpp
+125
-0
libcaf_test/caf/test/unit_test.hpp
libcaf_test/caf/test/unit_test.hpp
+12
-9
No files found.
libcaf_core/CMakeLists.txt
View file @
59ed7e08
...
...
@@ -158,6 +158,7 @@ add_library(libcaf_core_obj OBJECT ${CAF_CORE_HEADERS}
src/sec_strings.cpp
src/serializer.cpp
src/settings.cpp
src/settings_writer.cpp
src/size_based_credit_controller.cpp
src/skip.cpp
src/stream_aborter.cpp
...
...
@@ -177,6 +178,7 @@ add_library(libcaf_core_obj OBJECT ${CAF_CORE_HEADERS}
src/timestamp.cpp
src/tracing_data.cpp
src/tracing_data_factory.cpp
src/type_id.cpp
src/type_id_list.cpp
src/uri.cpp
src/uri_builder.cpp
...
...
@@ -310,6 +312,7 @@ caf_add_test_suites(caf-core-test
serial_reply
serialization
settings
settings_writer
simple_timeout
span
stateful_actor
...
...
libcaf_core/caf/binary_deserializer.hpp
View file @
59ed7e08
...
...
@@ -138,12 +138,28 @@ public:
return
ok
;
}
constexpr
bool
begin_key_value_pair
()
noexcept
{
return
ok
;
}
constexpr
bool
end_key_value_pair
()
noexcept
{
return
ok
;
}
bool
begin_sequence
(
size_t
&
list_size
)
noexcept
;
constexpr
bool
end_sequence
()
noexcept
{
return
ok
;
}
bool
begin_associative_array
(
size_t
&
size
)
noexcept
{
return
begin_sequence
(
size
);
}
bool
end_associative_array
()
noexcept
{
return
end_sequence
();
}
bool
value
(
bool
&
x
)
noexcept
;
bool
value
(
byte
&
x
)
noexcept
;
...
...
libcaf_core/caf/binary_serializer.hpp
View file @
59ed7e08
...
...
@@ -124,12 +124,28 @@ public:
return
ok
;
}
constexpr
bool
begin_key_value_pair
()
{
return
ok
;
}
constexpr
bool
end_key_value_pair
()
{
return
ok
;
}
bool
begin_sequence
(
size_t
list_size
);
constexpr
bool
end_sequence
()
{
return
ok
;
}
bool
begin_associative_array
(
size_t
size
)
{
return
begin_sequence
(
size
);
}
bool
end_associative_array
()
{
return
end_sequence
();
}
bool
value
(
byte
x
);
bool
value
(
bool
x
);
...
...
libcaf_core/caf/deserializer.hpp
View file @
59ed7e08
...
...
@@ -88,12 +88,29 @@ public:
/// Ends processing of a sequence.
virtual
bool
end_tuple
()
=
0
;
/// Begins processing of a tuple with two elements, whereas the first element
/// represents the key in an associative array.
/// @note the default implementation calls `begin_tuple(2)`.
virtual
bool
begin_key_value_pair
();
/// Ends processing of a key-value pair after both values were written.
/// @note the default implementation calls `end_tuple()`.
virtual
bool
end_key_value_pair
();
/// Begins processing of a sequence.
virtual
bool
begin_sequence
(
size_t
&
size
)
=
0
;
/// Ends processing of a sequence.
virtual
bool
end_sequence
()
=
0
;
/// Begins processing of an associative array (map).
/// @note the default implementation calls `begin_sequence(size)`.
virtual
bool
begin_associative_array
(
size_t
&
size
);
/// Ends processing of an associative array (map).
/// @note the default implementation calls `end_sequence()`.
virtual
bool
end_associative_array
();
/// Reads primitive value from the input.
/// @param x The primitive value.
/// @returns A non-zero error code on failure, `sec::success` otherwise.
...
...
libcaf_core/caf/detail/stringification_inspector.hpp
View file @
59ed7e08
...
...
@@ -71,13 +71,33 @@ public:
bool
end_field
();
bool
begin_tuple
(
size_t
size
)
{
return
begin_sequence
(
size
);
}
bool
end_tuple
()
{
return
end_sequence
();
}
bool
begin_key_value_pair
()
{
return
begin_tuple
(
2
);
}
bool
end_key_value_pair
()
{
return
end_tuple
();
}
bool
begin_sequence
(
size_t
size
);
bool
end_sequence
();
bool
begin_tuple
(
size_t
size
);
bool
begin_associative_array
(
size_t
size
)
{
return
begin_sequence
(
size
);
}
bool
end_tuple
();
bool
end_associative_array
()
{
return
end_sequence
();
}
bool
value
(
bool
x
);
...
...
libcaf_core/caf/hash/fnv.hpp
View file @
59ed7e08
...
...
@@ -93,6 +93,14 @@ public:
return
true
;
}
constexpr
bool
begin_key_value_pair
()
{
return
true
;
}
constexpr
bool
end_key_value_pair
()
{
return
true
;
}
constexpr
bool
begin_sequence
(
size_t
)
{
return
true
;
}
...
...
@@ -101,6 +109,14 @@ public:
return
true
;
}
constexpr
bool
begin_associative_array
(
size_t
)
{
return
true
;
}
constexpr
bool
end_associative_array
()
{
return
true
;
}
template
<
class
Integral
>
std
::
enable_if_t
<
std
::
is_integral
<
Integral
>::
value
,
bool
>
value
(
Integral
x
)
noexcept
{
...
...
libcaf_core/caf/inspector_access.hpp
View file @
59ed7e08
...
...
@@ -142,22 +142,22 @@ template <class Inspector, class T>
bool
load_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
map
)
{
x
.
clear
();
size_t
size
=
0
;
if
(
!
f
.
begin_
sequence
(
size
))
if
(
!
f
.
begin_
associative_array
(
size
))
return
false
;
for
(
size_t
i
=
0
;
i
<
size
;
++
i
)
{
auto
key
=
typename
T
::
key_type
{};
auto
val
=
typename
T
::
mapped_type
{};
if
(
!
(
f
.
begin_
tuple
(
2
)
//
&&
load_value
(
f
,
key
)
//
&&
load_value
(
f
,
val
)
//
&&
f
.
end_
tuple
()))
if
(
!
(
f
.
begin_
key_value_pair
()
//
&&
load_value
(
f
,
key
)
//
&&
load_value
(
f
,
val
)
//
&&
f
.
end_
key_value_pair
()))
return
false
;
if
(
!
x
.
emplace
(
std
::
move
(
key
),
std
::
move
(
val
)).
second
)
{
f
.
emplace_error
(
sec
::
runtime_error
,
"multiple key definitions"
);
return
false
;
}
}
return
f
.
end_
sequence
();
return
f
.
end_
associative_array
();
}
template
<
class
Inspector
,
class
T
>
...
...
@@ -310,17 +310,16 @@ bool save_value(Inspector& f, T& x, inspector_access_type::tuple) {
template
<
class
Inspector
,
class
T
>
bool
save_value
(
Inspector
&
f
,
T
&
x
,
inspector_access_type
::
map
)
{
auto
size
=
x
.
size
();
if
(
!
f
.
begin_sequence
(
size
))
if
(
!
f
.
begin_associative_array
(
x
.
size
()))
return
false
;
for
(
auto
&&
kvp
:
x
)
{
if
(
!
(
f
.
begin_
tuple
(
2
)
//
if
(
!
(
f
.
begin_
key_value_pair
()
//
&&
save_value
(
f
,
kvp
.
first
)
//
&&
save_value
(
f
,
kvp
.
second
)
//
&&
f
.
end_
tuple
()))
&&
f
.
end_
key_value_pair
()))
return
false
;
}
return
f
.
end_
sequence
();
return
f
.
end_
associative_array
();
}
template
<
class
Inspector
,
class
T
>
...
...
libcaf_core/caf/serializer.hpp
View file @
59ed7e08
...
...
@@ -93,12 +93,29 @@ public:
/// Ends processing of a tuple.
virtual
bool
end_tuple
()
=
0
;
/// Begins processing of a tuple with two elements, whereas the first element
/// represents the key in an associative array.
/// @note the default implementation calls `begin_tuple(2)`.
virtual
bool
begin_key_value_pair
();
/// Ends processing of a key-value pair after both values were written.
/// @note the default implementation calls `end_tuple()`.
virtual
bool
end_key_value_pair
();
/// Begins processing of a sequence. Saves the size to the underlying storage.
virtual
bool
begin_sequence
(
size_t
size
)
=
0
;
/// Ends processing of a sequence.
virtual
bool
end_sequence
()
=
0
;
/// Begins processing of an associative array (map).
/// @note the default implementation calls `begin_sequence(size)`.
virtual
bool
begin_associative_array
(
size_t
size
);
/// Ends processing of an associative array (map).
/// @note the default implementation calls `end_sequence()`.
virtual
bool
end_associative_array
();
/// Adds the primitive type `x` to the output.
/// @param x The primitive value.
/// @returns A non-zero error code on failure, `sec::success` otherwise.
...
...
libcaf_core/caf/settings_writer.hpp
0 → 100644
View file @
59ed7e08
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include "caf/config_value.hpp"
#include "caf/serializer.hpp"
#include "caf/settings.hpp"
#include <stack>
#include <vector>
namespace
caf
{
/// Writes objects into @ref settings.
class
settings_writer
final
:
public
serializer
{
public:
// -- member types------------------------------------------------------------
using
super
=
serializer
;
struct
present_field
{
settings
*
parent
;
string_view
name
;
string_view
type
;
};
struct
absent_field
{};
using
value_type
=
variant
<
settings
*
,
absent_field
,
present_field
,
config_value
::
list
*>
;
using
stack_type
=
std
::
stack
<
value_type
,
std
::
vector
<
value_type
>>
;
// -- constructors, destructors, and assignment operators --------------------
settings_writer
(
settings
*
destination
,
actor_system
&
sys
)
:
super
(
sys
),
root_
(
destination
)
{
st_
.
push
(
destination
);
has_human_readable_format_
=
true
;
}
settings_writer
(
settings
*
destination
,
execution_unit
*
ctx
)
:
super
(
ctx
),
root_
(
destination
)
{
has_human_readable_format_
=
true
;
}
explicit
settings_writer
(
settings
*
destination
)
:
settings_writer
(
destination
,
nullptr
)
{
// nop
}
~
settings_writer
()
override
;
// -- interface functions ----------------------------------------------------
bool
inject_next_object_type
(
type_id_t
type
)
override
;
bool
begin_object
(
string_view
name
)
override
;
bool
end_object
()
override
;
bool
begin_field
(
string_view
)
override
;
bool
begin_field
(
string_view
name
,
bool
is_present
)
override
;
bool
begin_field
(
string_view
name
,
span
<
const
type_id_t
>
types
,
size_t
index
)
override
;
bool
begin_field
(
string_view
name
,
bool
is_present
,
span
<
const
type_id_t
>
types
,
size_t
index
)
override
;
bool
end_field
()
override
;
bool
begin_tuple
(
size_t
size
)
override
;
bool
end_tuple
()
override
;
bool
begin_key_value_pair
()
override
;
bool
end_key_value_pair
()
override
;
bool
begin_sequence
(
size_t
size
)
override
;
bool
end_sequence
()
override
;
bool
begin_associative_array
(
size_t
size
)
override
;
bool
end_associative_array
()
override
;
bool
value
(
bool
x
)
override
;
bool
value
(
int8_t
x
)
override
;
bool
value
(
uint8_t
x
)
override
;
bool
value
(
int16_t
x
)
override
;
bool
value
(
uint16_t
x
)
override
;
bool
value
(
int32_t
x
)
override
;
bool
value
(
uint32_t
x
)
override
;
bool
value
(
int64_t
x
)
override
;
bool
value
(
uint64_t
x
)
override
;
bool
value
(
float
x
)
override
;
bool
value
(
double
x
)
override
;
bool
value
(
long
double
x
)
override
;
bool
value
(
string_view
x
)
override
;
bool
value
(
const
std
::
u16string
&
x
)
override
;
bool
value
(
const
std
::
u32string
&
x
)
override
;
bool
value
(
span
<
const
byte
>
x
)
override
;
private:
bool
push
(
config_value
&&
x
);
stack_type
st_
;
string_view
type_hint_
;
settings
*
root_
;
};
}
// namespace caf
libcaf_core/src/deserializer.cpp
View file @
59ed7e08
...
...
@@ -35,6 +35,22 @@ deserializer::~deserializer() {
// nop
}
bool
deserializer
::
begin_key_value_pair
()
{
return
begin_tuple
(
2
);
}
bool
deserializer
::
end_key_value_pair
()
{
return
end_tuple
();
}
bool
deserializer
::
begin_associative_array
(
size_t
&
size
)
{
return
begin_sequence
(
size
);
}
bool
deserializer
::
end_associative_array
()
{
return
end_sequence
();
}
bool
deserializer
::
value
(
std
::
vector
<
bool
>&
x
)
{
x
.
clear
();
size_t
size
=
0
;
...
...
libcaf_core/src/detail/stringification_inspector.cpp
View file @
59ed7e08
...
...
@@ -104,14 +104,6 @@ bool stringification_inspector::end_sequence() {
return
ok
;
}
bool
stringification_inspector
::
begin_tuple
(
size_t
size
)
{
return
begin_sequence
(
size
);
}
bool
stringification_inspector
::
end_tuple
()
{
return
end_sequence
();
}
bool
stringification_inspector
::
value
(
bool
x
)
{
sep
();
result_
+=
x
?
"true"
:
"false"
;
...
...
libcaf_core/src/serializer.cpp
View file @
59ed7e08
...
...
@@ -35,6 +35,22 @@ serializer::~serializer() {
// nop
}
bool
serializer
::
begin_key_value_pair
()
{
return
begin_tuple
(
2
);
}
bool
serializer
::
end_key_value_pair
()
{
return
end_tuple
();
}
bool
serializer
::
begin_associative_array
(
size_t
size
)
{
return
begin_sequence
(
size
);
}
bool
serializer
::
end_associative_array
()
{
return
end_sequence
();
}
bool
serializer
::
value
(
const
std
::
vector
<
bool
>&
xs
)
{
if
(
!
begin_sequence
(
xs
.
size
()))
return
false
;
...
...
libcaf_core/src/settings_writer.cpp
0 → 100644
View file @
59ed7e08
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/settings_writer.hpp"
#include "caf/detail/append_hex.hpp"
#include "caf/detail/overload.hpp"
#define CHECK_NOT_EMPTY() \
do { \
if (st_.empty()) { \
emplace_error(sec::runtime_error, "mismatching calls to begin/end"); \
return false; \
} \
} while (false)
#define CHECK_VALID() \
do { \
CHECK_NOT_EMPTY(); \
if (holds_alternative<none_t>(st_.top())) { \
emplace_error(sec::runtime_error, \
"attempted to write to a non-existent optional field"); \
return false; \
} \
} while (false)
#define SCOPE(top_type) \
CHECK_VALID(); \
if (!holds_alternative<top_type>(st_.top())) { \
if constexpr (std::is_same<top_type, settings>::value) { \
emplace_error(sec::runtime_error, \
"attempted to add list items before calling " \
"begin_sequence or begin_tuple"); \
} else { \
emplace_error(sec::runtime_error, \
"attempted to add fields to a list item"); \
} \
return false; \
} \
[[maybe_unused]] auto& top = get<top_type>(st_.top());
namespace
caf
{
// -- constructors, destructors, and assignment operators ----------------------
settings_writer
::~
settings_writer
()
{
// nop
}
// -- interface functions ------------------------------------------------------
bool
settings_writer
::
inject_next_object_type
(
type_id_t
type
)
{
CHECK_NOT_EMPTY
();
type_hint_
=
query_type_name
(
type
);
if
(
type_hint_
.
empty
())
{
emplace_error
(
sec
::
runtime_error
,
"query_type_name returned an empty string for type ID"
);
return
false
;
}
return
true
;
}
bool
settings_writer
::
begin_object
(
string_view
)
{
if
(
st_
.
empty
())
{
if
(
root_
==
nullptr
)
{
emplace_error
(
sec
::
runtime_error
,
"tried to serialize multiple objects into the root object"
);
return
false
;
}
st_
.
push
(
root_
);
root_
=
nullptr
;
}
else
{
auto
f
=
detail
::
make_overload
(
[
this
](
settings
*
)
{
emplace_error
(
sec
::
runtime_error
,
"begin_object called inside another object"
);
return
false
;
},
[
this
](
absent_field
)
{
emplace_error
(
sec
::
runtime_error
,
"begin_object called inside non-existent optional field"
);
return
false
;
},
[
this
](
present_field
fld
)
{
auto
[
iter
,
added
]
=
fld
.
parent
->
emplace
(
fld
.
name
,
settings
{});
if
(
!
added
)
{
emplace_error
(
sec
::
runtime_error
,
"field already defined: "
+
to_string
(
fld
.
name
));
return
false
;
}
auto
obj
=
std
::
addressof
(
get
<
settings
>
(
iter
->
second
));
if
(
!
fld
.
type
.
empty
())
put
(
*
obj
,
"@type"
,
fld
.
type
);
st_
.
push
(
obj
);
return
true
;
},
[
this
](
config_value
::
list
*
ls
)
{
ls
->
emplace_back
(
settings
{});
st_
.
push
(
std
::
addressof
(
get
<
settings
>
(
ls
->
back
())));
return
true
;
});
if
(
!
visit
(
f
,
st_
.
top
()))
return
false
;
}
if
(
!
type_hint_
.
empty
())
{
put
(
*
get
<
settings
*>
(
st_
.
top
()),
"@type"
,
type_hint_
);
type_hint_
=
string_view
{};
}
return
true
;
}
bool
settings_writer
::
end_object
()
{
SCOPE
(
settings
*
);
st_
.
pop
();
return
true
;
}
bool
settings_writer
::
begin_field
(
string_view
name
)
{
SCOPE
(
settings
*
);
st_
.
push
(
present_field
{
top
,
name
,
string_view
{}});
return
true
;
}
bool
settings_writer
::
begin_field
(
string_view
name
,
bool
is_present
)
{
SCOPE
(
settings
*
);
if
(
is_present
)
st_
.
push
(
present_field
{
top
,
name
,
string_view
{}});
else
st_
.
push
(
absent_field
{});
return
true
;
}
bool
settings_writer
::
begin_field
(
string_view
name
,
span
<
const
type_id_t
>
types
,
size_t
index
)
{
SCOPE
(
settings
*
);
if
(
index
>=
types
.
size
())
{
emplace_error
(
sec
::
invalid_argument
,
"index out of range in optional variant field "
+
to_string
(
name
));
return
false
;
}
auto
tn
=
query_type_name
(
types
[
index
]);
if
(
tn
.
empty
())
{
emplace_error
(
sec
::
runtime_error
,
"query_type_name returned an empty string for type ID"
);
return
false
;
}
st_
.
push
(
present_field
{
top
,
name
,
tn
});
return
true
;
}
bool
settings_writer
::
begin_field
(
string_view
name
,
bool
is_present
,
span
<
const
type_id_t
>
types
,
size_t
index
)
{
if
(
is_present
)
return
begin_field
(
name
,
types
,
index
);
else
return
begin_field
(
name
,
false
);
}
bool
settings_writer
::
end_field
()
{
CHECK_NOT_EMPTY
();
if
(
!
holds_alternative
<
present_field
>
(
st_
.
top
())
&&
!
holds_alternative
<
absent_field
>
(
st_
.
top
()))
{
emplace_error
(
sec
::
runtime_error
,
"end_field called outside of a field"
);
return
false
;
}
st_
.
pop
();
return
true
;
}
bool
settings_writer
::
begin_tuple
(
size_t
size
)
{
return
begin_sequence
(
size
);
}
bool
settings_writer
::
end_tuple
()
{
return
end_sequence
();
}
bool
settings_writer
::
begin_key_value_pair
()
{
SCOPE
(
settings
*
);
auto
[
iter
,
added
]
=
top
->
emplace
(
"@tmp"
,
config_value
::
list
{});
if
(
!
added
)
{
emplace_error
(
sec
::
runtime_error
,
"temporary entry @tmp already exists"
);
return
false
;
}
st_
.
push
(
std
::
addressof
(
get
<
config_value
::
list
>
(
iter
->
second
)));
return
true
;
}
bool
settings_writer
::
end_key_value_pair
()
{
config_value
::
list
tmp
;
/* lifetime scope of the list */
{
SCOPE
(
config_value
::
list
*
);
if
(
top
->
size
()
!=
2
)
{
emplace_error
(
sec
::
runtime_error
,
"a key-value pair must have exactly two elements"
);
return
false
;
}
tmp
=
std
::
move
(
*
top
);
st_
.
pop
();
}
SCOPE
(
settings
*
);
// Get key and value from the temporary list.
top
->
container
().
erase
(
"@tmp"
);
std
::
string
key
;
if
(
auto
str
=
get_if
<
std
::
string
>
(
std
::
addressof
(
tmp
[
0
])))
key
=
std
::
move
(
*
str
);
else
key
=
to_string
(
tmp
[
0
]);
if
(
!
top
->
emplace
(
std
::
move
(
key
),
std
::
move
(
tmp
[
1
])).
second
)
{
emplace_error
(
sec
::
runtime_error
,
"multiple definitions for key"
);
return
false
;
}
return
true
;
}
bool
settings_writer
::
begin_sequence
(
size_t
)
{
CHECK_NOT_EMPTY
();
auto
f
=
detail
::
make_overload
(
[
this
](
settings
*
)
{
emplace_error
(
sec
::
runtime_error
,
"cannot start sequence/tuple inside an object"
);
return
false
;
},
[
this
](
absent_field
)
{
emplace_error
(
sec
::
runtime_error
,
"cannot start sequence/tuple inside non-existent optional field"
);
return
false
;
},
[
this
](
present_field
fld
)
{
auto
[
iter
,
added
]
=
fld
.
parent
->
emplace
(
fld
.
name
,
config_value
::
list
{});
if
(
!
added
)
{
emplace_error
(
sec
::
runtime_error
,
"field already defined: "
+
to_string
(
fld
.
name
));
return
false
;
}
st_
.
push
(
std
::
addressof
(
get
<
config_value
::
list
>
(
iter
->
second
)));
return
true
;
},
[
this
](
config_value
::
list
*
ls
)
{
ls
->
emplace_back
(
config_value
::
list
{});
st_
.
push
(
std
::
addressof
(
get
<
config_value
::
list
>
(
ls
->
back
())));
return
true
;
});
return
visit
(
f
,
st_
.
top
());
}
bool
settings_writer
::
end_sequence
()
{
SCOPE
(
config_value
::
list
*
);
st_
.
pop
();
return
true
;
}
bool
settings_writer
::
begin_associative_array
(
size_t
)
{
CHECK_NOT_EMPTY
();
settings
*
inner
=
nullptr
;
auto
f
=
detail
::
make_overload
(
[
this
](
settings
*
)
{
emplace_error
(
sec
::
runtime_error
,
"cannot write values outside fields"
);
return
false
;
},
[
this
](
absent_field
)
{
emplace_error
(
sec
::
runtime_error
,
"cannot add values to non-existent optional field"
);
return
false
;
},
[
this
,
&
inner
](
present_field
fld
)
{
auto
[
iter
,
added
]
=
fld
.
parent
->
emplace
(
fld
.
name
,
config_value
{
settings
{}});
if
(
!
added
)
{
emplace_error
(
sec
::
runtime_error
,
"field already defined: "
+
to_string
(
fld
.
name
));
return
false
;
}
if
(
!
fld
.
type
.
empty
())
{
std
::
string
key
;
key
+=
'@'
;
key
.
insert
(
key
.
end
(),
fld
.
name
.
begin
(),
fld
.
name
.
end
());
key
+=
"-type"
;
if
(
fld
.
parent
->
contains
(
key
))
{
emplace_error
(
sec
::
runtime_error
,
"type of variant field already defined."
);
return
false
;
}
put
(
*
fld
.
parent
,
key
,
fld
.
type
);
}
inner
=
std
::
addressof
(
get
<
settings
>
(
iter
->
second
));
return
true
;
},
[
&
inner
](
config_value
::
list
*
ls
)
{
ls
->
emplace_back
(
config_value
{
settings
{}});
inner
=
std
::
addressof
(
get
<
settings
>
(
ls
->
back
()));
return
true
;
});
if
(
visit
(
f
,
st_
.
top
()))
{
CAF_ASSERT
(
inner
!=
nullptr
);
st_
.
push
(
inner
);
return
true
;
}
return
false
;
}
bool
settings_writer
::
end_associative_array
()
{
SCOPE
(
settings
*
);
st_
.
pop
();
return
true
;
}
bool
settings_writer
::
value
(
bool
x
)
{
return
push
(
config_value
{
x
});
}
bool
settings_writer
::
value
(
int8_t
x
)
{
return
push
(
config_value
{
static_cast
<
config_value
::
integer
>
(
x
)});
}
bool
settings_writer
::
value
(
uint8_t
x
)
{
return
push
(
config_value
{
static_cast
<
config_value
::
integer
>
(
x
)});
}
bool
settings_writer
::
value
(
int16_t
x
)
{
return
push
(
config_value
{
static_cast
<
config_value
::
integer
>
(
x
)});
}
bool
settings_writer
::
value
(
uint16_t
x
)
{
return
push
(
config_value
{
static_cast
<
config_value
::
integer
>
(
x
)});
}
bool
settings_writer
::
value
(
int32_t
x
)
{
return
push
(
config_value
{
static_cast
<
config_value
::
integer
>
(
x
)});
}
bool
settings_writer
::
value
(
uint32_t
x
)
{
return
push
(
config_value
{
static_cast
<
config_value
::
integer
>
(
x
)});
}
bool
settings_writer
::
value
(
int64_t
x
)
{
return
push
(
config_value
{
static_cast
<
config_value
::
integer
>
(
x
)});
}
bool
settings_writer
::
value
(
uint64_t
x
)
{
auto
max_val
=
std
::
numeric_limits
<
config_value
::
integer
>::
max
();
if
(
x
>
static_cast
<
uint64_t
>
(
max_val
))
{
emplace_error
(
sec
::
runtime_error
,
"integer overflow"
);
return
false
;
}
return
push
(
config_value
{
static_cast
<
config_value
::
integer
>
(
x
)});
}
bool
settings_writer
::
value
(
float
x
)
{
return
push
(
config_value
{
double
{
x
}});
}
bool
settings_writer
::
value
(
double
x
)
{
return
push
(
config_value
{
x
});
}
bool
settings_writer
::
value
(
long
double
x
)
{
return
push
(
config_value
{
std
::
to_string
(
x
)});
}
bool
settings_writer
::
value
(
string_view
x
)
{
return
push
(
config_value
{
to_string
(
x
)});
}
bool
settings_writer
::
value
(
const
std
::
u16string
&
)
{
emplace_error
(
sec
::
runtime_error
,
"u16string support not implemented yet"
);
return
false
;
}
bool
settings_writer
::
value
(
const
std
::
u32string
&
)
{
emplace_error
(
sec
::
runtime_error
,
"u32string support not implemented yet"
);
return
false
;
}
bool
settings_writer
::
value
(
span
<
const
byte
>
x
)
{
std
::
string
str
;
detail
::
append_hex
(
str
,
x
.
data
(),
x
.
size
());
return
push
(
config_value
{
std
::
move
(
str
)});
}
bool
settings_writer
::
push
(
config_value
&&
x
)
{
CHECK_NOT_EMPTY
();
auto
f
=
detail
::
make_overload
(
[
this
](
settings
*
)
{
emplace_error
(
sec
::
runtime_error
,
"cannot write values outside fields"
);
return
false
;
},
[
this
](
absent_field
)
{
emplace_error
(
sec
::
runtime_error
,
"cannot add values to non-existent optional field"
);
return
false
;
},
[
this
,
&
x
](
present_field
fld
)
{
auto
[
iter
,
added
]
=
fld
.
parent
->
emplace
(
fld
.
name
,
std
::
move
(
x
));
if
(
!
added
)
{
emplace_error
(
sec
::
runtime_error
,
"field already defined: "
+
to_string
(
fld
.
name
));
return
false
;
}
if
(
!
fld
.
type
.
empty
())
{
std
::
string
key
;
key
+=
'@'
;
key
.
insert
(
key
.
end
(),
fld
.
name
.
begin
(),
fld
.
name
.
end
());
key
+=
"-type"
;
if
(
fld
.
parent
->
contains
(
key
))
{
emplace_error
(
sec
::
runtime_error
,
"type of variant field already defined."
);
return
false
;
}
put
(
*
fld
.
parent
,
key
,
fld
.
type
);
}
return
true
;
},
[
&
x
](
config_value
::
list
*
ls
)
{
ls
->
emplace_back
(
std
::
move
(
x
));
return
true
;
});
return
visit
(
f
,
st_
.
top
());
}
}
// namespace caf
libcaf_core/src/type_id.cpp
0 → 100644
View file @
59ed7e08
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/type_id.hpp"
#include "caf/detail/meta_object.hpp"
namespace
caf
{
string_view
query_type_name
(
type_id_t
type
)
{
if
(
auto
ptr
=
detail
::
global_meta_object
(
type
))
return
ptr
->
type_name
;
return
{};
}
type_id_t
query_type_id
(
string_view
name
)
{
auto
objects
=
detail
::
global_meta_objects
();
for
(
size_t
index
=
0
;
index
<
objects
.
size
();
++
index
)
if
(
objects
[
index
].
type_name
==
name
)
return
static_cast
<
type_id_t
>
(
index
);
return
invalid_type_id
;
}
}
// namespace caf
libcaf_core/test/inspector-tests.hpp
0 → 100644
View file @
59ed7e08
// This header includes various types for testing save and load inspectors.
#pragma once
#include "caf/optional.hpp"
#include "caf/type_id.hpp"
#include "caf/variant.hpp"
#include "nasty.hpp"
namespace
{
struct
point_3d
;
struct
line
;
struct
duration
;
struct
person
;
class
foobar
;
struct
dummy_message
;
struct
fallback_dummy_message
;
struct
basics
;
}
// namespace
#define CAF_TEST_SET_TYPE_NAME(type) \
namespace caf { \
template <> \
struct type_name<type> { \
static constexpr string_view value = #type; \
}; \
}
CAF_TEST_SET_TYPE_NAME
(
point_3d
)
CAF_TEST_SET_TYPE_NAME
(
line
)
CAF_TEST_SET_TYPE_NAME
(
duration
)
CAF_TEST_SET_TYPE_NAME
(
person
)
CAF_TEST_SET_TYPE_NAME
(
foobar
)
CAF_TEST_SET_TYPE_NAME
(
dummy_message
)
CAF_TEST_SET_TYPE_NAME
(
fallback_dummy_message
)
CAF_TEST_SET_TYPE_NAME
(
basics
)
CAF_TEST_SET_TYPE_NAME
(
nasty
)
namespace
{
struct
point_3d
{
int32_t
x
;
int32_t
y
;
int32_t
z
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
point_3d
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"x"
,
x
.
x
),
f
.
field
(
"y"
,
x
.
y
),
f
.
field
(
"z"
,
x
.
z
));
}
struct
line
{
point_3d
p1
;
point_3d
p2
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
line
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"p1"
,
x
.
p1
),
f
.
field
(
"p2"
,
x
.
p2
));
}
struct
duration
{
std
::
string
unit
;
double
count
;
};
[[
maybe_unused
]]
bool
valid_time_unit
(
const
std
::
string
&
unit
)
{
return
unit
==
"seconds"
||
unit
==
"minutes"
;
}
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
duration
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"unit"
,
x
.
unit
).
fallback
(
"seconds"
).
invariant
(
valid_time_unit
),
f
.
field
(
"count"
,
x
.
count
));
}
struct
person
{
std
::
string
name
;
caf
::
optional
<
std
::
string
>
phone
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
person
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"name"
,
x
.
name
),
f
.
field
(
"phone"
,
x
.
phone
));
}
class
foobar
{
public:
foobar
()
=
default
;
foobar
(
const
foobar
&
)
=
default
;
foobar
&
operator
=
(
const
foobar
&
)
=
default
;
foobar
(
std
::
string
foo
,
std
::
string
bar
)
:
foo_
(
std
::
move
(
foo
)),
bar_
(
std
::
move
(
bar
))
{
// nop
}
const
std
::
string
&
foo
()
{
return
foo_
;
}
void
foo
(
std
::
string
value
)
{
foo_
=
std
::
move
(
value
);
}
const
std
::
string
&
bar
()
{
return
bar_
;
}
void
bar
(
std
::
string
value
)
{
bar_
=
std
::
move
(
value
);
}
private:
std
::
string
foo_
;
std
::
string
bar_
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
foobar
&
x
)
{
auto
get_foo
=
[
&
x
]()
->
decltype
(
auto
)
{
return
x
.
foo
();
};
auto
set_foo
=
[
&
x
](
std
::
string
value
)
{
x
.
foo
(
std
::
move
(
value
));
return
true
;
};
auto
get_bar
=
[
&
x
]()
->
decltype
(
auto
)
{
return
x
.
bar
();
};
auto
set_bar
=
[
&
x
](
std
::
string
value
)
{
x
.
bar
(
std
::
move
(
value
));
return
true
;
};
return
f
.
object
(
x
).
fields
(
f
.
field
(
"foo"
,
get_foo
,
set_foo
),
f
.
field
(
"bar"
,
get_bar
,
set_bar
));
}
struct
dummy_message
{
caf
::
variant
<
std
::
string
,
double
>
content
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
dummy_message
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"content"
,
x
.
content
));
}
struct
fallback_dummy_message
{
caf
::
variant
<
std
::
string
,
double
>
content
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
fallback_dummy_message
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"content"
,
x
.
content
).
fallback
(
42.0
));
}
struct
basics
{
struct
tag
{};
tag
v1
;
int32_t
v2
;
int32_t
v3
[
4
];
dummy_message
v4
[
2
];
std
::
array
<
int32_t
,
2
>
v5
;
std
::
tuple
<
int32_t
,
dummy_message
>
v6
;
std
::
map
<
std
::
string
,
int32_t
>
v7
;
std
::
vector
<
std
::
list
<
std
::
pair
<
std
::
string
,
std
::
array
<
int32_t
,
3
>>>>
v8
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
basics
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"v1"
,
x
.
v1
),
f
.
field
(
"v2"
,
x
.
v2
),
f
.
field
(
"v3"
,
x
.
v3
),
f
.
field
(
"v4"
,
x
.
v4
),
f
.
field
(
"v5"
,
x
.
v5
),
f
.
field
(
"v6"
,
x
.
v6
),
f
.
field
(
"v7"
,
x
.
v7
),
f
.
field
(
"v8"
,
x
.
v8
));
}
}
// namespace
libcaf_core/test/load_inspector.cpp
View file @
59ed7e08
...
...
@@ -33,153 +33,13 @@
#include "caf/type_id.hpp"
#include "caf/variant.hpp"
#include "
nasty
.hpp"
#include "
inspector-tests
.hpp"
using
namespace
caf
;
namespace
{
using
string_list
=
std
::
vector
<
std
::
string
>
;
struct
point_3d
{
static
inline
string_view
tname
=
"point_3d"
;
int32_t
x
;
int32_t
y
;
int32_t
z
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
point_3d
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"x"
,
x
.
x
),
f
.
field
(
"y"
,
x
.
y
),
f
.
field
(
"z"
,
x
.
z
));
}
struct
line
{
static
inline
string_view
tname
=
"line"
;
point_3d
p1
;
point_3d
p2
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
line
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"p1"
,
x
.
p1
),
f
.
field
(
"p2"
,
x
.
p2
));
}
struct
duration
{
static
inline
string_view
tname
=
"duration"
;
std
::
string
unit
;
double
count
;
};
bool
valid_time_unit
(
const
std
::
string
&
unit
)
{
return
unit
==
"seconds"
||
unit
==
"minutes"
;
}
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
duration
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"unit"
,
x
.
unit
).
fallback
(
"seconds"
).
invariant
(
valid_time_unit
),
f
.
field
(
"count"
,
x
.
count
));
}
struct
person
{
static
inline
string_view
tname
=
"person"
;
std
::
string
name
;
optional
<
std
::
string
>
phone
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
person
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"name"
,
x
.
name
),
f
.
field
(
"phone"
,
x
.
phone
));
}
class
foobar
{
public:
static
inline
string_view
tname
=
"foobar"
;
const
std
::
string
&
foo
()
{
return
foo_
;
}
void
foo
(
std
::
string
value
)
{
foo_
=
std
::
move
(
value
);
}
const
std
::
string
&
bar
()
{
return
bar_
;
}
void
bar
(
std
::
string
value
)
{
bar_
=
std
::
move
(
value
);
}
private:
std
::
string
foo_
;
std
::
string
bar_
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
foobar
&
x
)
{
auto
get_foo
=
[
&
x
]()
->
decltype
(
auto
)
{
return
x
.
foo
();
};
auto
set_foo
=
[
&
x
](
std
::
string
value
)
{
x
.
foo
(
std
::
move
(
value
));
return
true
;
};
auto
get_bar
=
[
&
x
]()
->
decltype
(
auto
)
{
return
x
.
bar
();
};
auto
set_bar
=
[
&
x
](
std
::
string
value
)
{
x
.
bar
(
std
::
move
(
value
));
return
true
;
};
return
f
.
object
(
x
).
fields
(
f
.
field
(
"foo"
,
get_foo
,
set_foo
),
f
.
field
(
"bar"
,
get_bar
,
set_bar
));
}
struct
dummy_message
{
static
inline
string_view
tname
=
"dummy_message"
;
variant
<
std
::
string
,
double
>
content
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
dummy_message
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"content"
,
x
.
content
));
}
struct
fallback_dummy_message
{
static
inline
string_view
tname
=
"fallback_dummy_message"
;
variant
<
std
::
string
,
double
>
content
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
fallback_dummy_message
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"content"
,
x
.
content
).
fallback
(
42.0
));
}
struct
basics
{
static
inline
string_view
tname
=
"basics"
;
struct
tag
{
static
inline
string_view
tname
=
"tag"
;
};
tag
v1
;
int32_t
v2
;
int32_t
v3
[
4
];
dummy_message
v4
[
2
];
std
::
array
<
int32_t
,
2
>
v5
;
std
::
tuple
<
int32_t
,
dummy_message
>
v6
;
std
::
map
<
std
::
string
,
int32_t
>
v7
;
std
::
vector
<
std
::
list
<
std
::
pair
<
std
::
string
,
std
::
array
<
int32_t
,
3
>>>>
v8
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
basics
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"v1"
,
x
.
v1
),
f
.
field
(
"v2"
,
x
.
v2
),
f
.
field
(
"v3"
,
x
.
v3
),
f
.
field
(
"v4"
,
x
.
v4
),
f
.
field
(
"v5"
,
x
.
v5
),
f
.
field
(
"v6"
,
x
.
v6
),
f
.
field
(
"v7"
,
x
.
v7
),
f
.
field
(
"v8"
,
x
.
v8
));
}
struct
testee
:
load_inspector_base
<
testee
>
{
struct
testee
:
deserializer
{
std
::
string
log
;
bool
load_field_failed
(
string_view
,
sec
code
)
{
...
...
@@ -194,9 +54,10 @@ struct testee : load_inspector_base<testee> {
log
.
insert
(
log
.
end
(),
indent
,
' '
);
}
template
<
class
T
>
auto
object
(
T
&
)
{
return
object_t
<
testee
>
{
T
::
tname
,
this
};
using
deserializer
::
object
;
bool
fetch_next_object_type
(
type_id_t
&
)
override
{
return
false
;
}
template
<
class
T
>
...
...
@@ -204,7 +65,12 @@ struct testee : load_inspector_base<testee> {
return
object_t
<
testee
>
{
"optional"
,
this
};
}
bool
begin_object
(
string_view
object_name
)
{
template
<
class
...
Ts
>
auto
object
(
variant
<
Ts
...
>&
)
{
return
object_t
<
testee
>
{
"variant"
,
this
};
}
bool
begin_object
(
string_view
object_name
)
override
{
new_line
();
indent
+=
2
;
log
+=
"begin object "
;
...
...
@@ -212,14 +78,14 @@ struct testee : load_inspector_base<testee> {
return
ok
;
}
bool
end_object
()
{
bool
end_object
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end object"
;
return
ok
;
}
bool
begin_field
(
string_view
name
)
{
bool
begin_field
(
string_view
name
)
override
{
new_line
();
indent
+=
2
;
log
+=
"begin field "
;
...
...
@@ -227,7 +93,7 @@ struct testee : load_inspector_base<testee> {
return
ok
;
}
bool
begin_field
(
string_view
name
,
bool
&
is_present
)
{
bool
begin_field
(
string_view
name
,
bool
&
is_present
)
override
{
new_line
();
indent
+=
2
;
log
+=
"begin optional field "
;
...
...
@@ -237,7 +103,7 @@ struct testee : load_inspector_base<testee> {
}
bool
begin_field
(
string_view
name
,
span
<
const
type_id_t
>
,
size_t
&
type_index
)
{
size_t
&
type_index
)
override
{
new_line
();
indent
+=
2
;
log
+=
"begin variant field "
;
...
...
@@ -247,7 +113,7 @@ struct testee : load_inspector_base<testee> {
}
bool
begin_field
(
string_view
name
,
bool
&
is_present
,
span
<
const
type_id_t
>
,
size_t
&
)
{
size_t
&
)
override
{
new_line
();
indent
+=
2
;
log
+=
"begin optional variant field "
;
...
...
@@ -256,14 +122,14 @@ struct testee : load_inspector_base<testee> {
return
ok
;
}
bool
end_field
()
{
bool
end_field
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end field"
;
return
ok
;
}
bool
begin_tuple
(
size_t
size
)
{
bool
begin_tuple
(
size_t
size
)
override
{
new_line
();
indent
+=
2
;
log
+=
"begin tuple of size "
;
...
...
@@ -271,14 +137,28 @@ struct testee : load_inspector_base<testee> {
return
ok
;
}
bool
end_tuple
()
{
bool
end_tuple
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end tuple"
;
return
ok
;
}
bool
begin_sequence
(
size_t
&
size
)
{
bool
begin_key_value_pair
()
override
{
new_line
();
indent
+=
2
;
log
+=
"begin key-value pair"
;
return
ok
;
}
bool
end_key_value_pair
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end key-value pair"
;
return
ok
;
}
bool
begin_sequence
(
size_t
&
size
)
override
{
size
=
0
;
new_line
();
indent
+=
2
;
...
...
@@ -287,15 +167,38 @@ struct testee : load_inspector_base<testee> {
return
ok
;
}
bool
end_sequence
()
{
bool
end_sequence
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end sequence"
;
return
ok
;
}
bool
begin_associative_array
(
size_t
&
size
)
override
{
size
=
0
;
new_line
();
indent
+=
2
;
log
+=
"begin associative array of size "
;
log
+=
std
::
to_string
(
size
);
return
ok
;
}
bool
end_associative_array
()
override
{
indent
-=
2
;
new_line
();
log
+=
"end associative array"
;
return
ok
;
}
bool
value
(
bool
&
x
)
override
{
new_line
();
log
+=
"bool value"
;
x
=
false
;
return
ok
;
}
template
<
class
T
>
std
::
enable_if_t
<
std
::
is_arithmetic
<
T
>::
value
,
bool
>
value
(
T
&
x
)
{
bool
primitive_
value
(
T
&
x
)
{
new_line
();
auto
tn
=
type_name_v
<
T
>
;
log
.
insert
(
log
.
end
(),
tn
.
begin
(),
tn
.
end
());
...
...
@@ -304,10 +207,67 @@ struct testee : load_inspector_base<testee> {
return
ok
;
}
bool
value
(
std
::
string
&
x
)
{
bool
value
(
int8_t
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
uint8_t
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
int16_t
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
uint16_t
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
int32_t
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
uint32_t
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
int64_t
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
uint64_t
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
float
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
double
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
long
double
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
std
::
string
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
std
::
u16string
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
std
::
u32string
&
x
)
override
{
return
primitive_value
(
x
);
}
bool
value
(
span
<
byte
>
xs
)
override
{
new_line
();
log
+=
"std::string value"
;
x
.
clear
();
log
+=
"caf::span<caf::byte> value"
;
for
(
auto
&
x
:
xs
)
x
=
byte
{
0
};
return
ok
;
}
};
...
...
@@ -566,7 +526,7 @@ CAF_TEST(load inspectors support all basic STL types) {
CAF_CHECK_EQUAL
(
f
.
log
,
R"_(
begin object basics
begin field v1
begin object
tag
begin object
anonymous
end object
end field
begin field v2
...
...
@@ -611,8 +571,8 @@ begin object basics
end tuple
end field
begin field v7
begin
sequence
of size 0
end
sequence
begin
associative array
of size 0
end
associative array
end field
begin field v8
begin sequence of size 0
...
...
libcaf_core/test/save_inspector.cpp
View file @
59ed7e08
...
...
@@ -29,159 +29,12 @@
#include "caf/message.hpp"
#include "caf/serializer.hpp"
#include "nasty.hpp"
namespace
{
struct
point_3d
;
struct
line
;
struct
duration
;
struct
person
;
class
foobar
;
struct
dummy_message
;
struct
basics
;
}
// namespace
#define CAF_TYPE_NAME(type) \
namespace caf { \
template <> \
struct type_name<type> { \
static constexpr string_view value = #type; \
}; \
}
CAF_TYPE_NAME
(
point_3d
)
CAF_TYPE_NAME
(
line
)
CAF_TYPE_NAME
(
duration
)
CAF_TYPE_NAME
(
person
)
CAF_TYPE_NAME
(
foobar
)
CAF_TYPE_NAME
(
dummy_message
)
CAF_TYPE_NAME
(
basics
)
CAF_TYPE_NAME
(
nasty
)
#include "inspector-tests.hpp"
using
namespace
caf
;
namespace
{
using
string_list
=
std
::
vector
<
std
::
string
>
;
struct
point_3d
{
int32_t
x
;
int32_t
y
;
int32_t
z
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
point_3d
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"x"
,
x
.
x
),
f
.
field
(
"y"
,
x
.
y
),
f
.
field
(
"z"
,
x
.
z
));
}
struct
line
{
point_3d
p1
;
point_3d
p2
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
line
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"p1"
,
x
.
p1
),
f
.
field
(
"p2"
,
x
.
p2
));
}
struct
duration
{
std
::
string
unit
;
double
count
;
};
bool
valid_time_unit
(
const
std
::
string
&
unit
)
{
return
unit
==
"seconds"
||
unit
==
"minutes"
;
}
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
duration
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"unit"
,
x
.
unit
).
fallback
(
"seconds"
).
invariant
(
valid_time_unit
),
f
.
field
(
"count"
,
x
.
count
));
}
struct
person
{
std
::
string
name
;
optional
<
std
::
string
>
phone
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
person
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"name"
,
x
.
name
),
f
.
field
(
"phone"
,
x
.
phone
));
}
class
foobar
{
public:
const
std
::
string
&
foo
()
{
return
foo_
;
}
void
foo
(
std
::
string
value
)
{
foo_
=
std
::
move
(
value
);
}
const
std
::
string
&
bar
()
{
return
bar_
;
}
void
bar
(
std
::
string
value
)
{
bar_
=
std
::
move
(
value
);
}
private:
std
::
string
foo_
;
std
::
string
bar_
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
foobar
&
x
)
{
auto
get_foo
=
[
&
x
]()
->
decltype
(
auto
)
{
return
x
.
foo
();
};
auto
set_foo
=
[
&
x
](
std
::
string
value
)
{
x
.
foo
(
std
::
move
(
value
));
return
true
;
};
auto
get_bar
=
[
&
x
]()
->
decltype
(
auto
)
{
return
x
.
bar
();
};
auto
set_bar
=
[
&
x
](
std
::
string
value
)
{
x
.
bar
(
std
::
move
(
value
));
return
true
;
};
return
f
.
object
(
x
).
fields
(
f
.
field
(
"foo"
,
get_foo
,
set_foo
),
f
.
field
(
"bar"
,
get_bar
,
set_bar
));
}
struct
dummy_message
{
variant
<
std
::
string
,
double
>
content
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
dummy_message
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"content"
,
x
.
content
));
}
struct
basics
{
struct
tag
{};
tag
v1
;
int32_t
v2
;
int32_t
v3
[
4
];
dummy_message
v4
[
2
];
std
::
array
<
int32_t
,
2
>
v5
;
std
::
tuple
<
int32_t
,
dummy_message
>
v6
;
std
::
map
<
std
::
string
,
int32_t
>
v7
;
std
::
vector
<
std
::
list
<
std
::
pair
<
std
::
string
,
std
::
array
<
int32_t
,
3
>>>>
v8
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
basics
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"v1"
,
x
.
v1
),
f
.
field
(
"v2"
,
x
.
v2
),
f
.
field
(
"v3"
,
x
.
v3
),
f
.
field
(
"v4"
,
x
.
v4
),
f
.
field
(
"v5"
,
x
.
v5
),
f
.
field
(
"v6"
,
x
.
v6
),
f
.
field
(
"v7"
,
x
.
v7
),
f
.
field
(
"v8"
,
x
.
v8
));
}
struct
testee
:
serializer
{
std
::
string
log
;
...
...
@@ -292,6 +145,22 @@ struct testee : serializer {
return
ok
;
}
bool
begin_key_value_pair
()
override
{
new_line
();
indent
+=
2
;
log
+=
"begin key-value pair"
;
return
ok
;
}
bool
end_key_value_pair
()
override
{
if
(
indent
<
2
)
CAF_FAIL
(
"begin/end mismatch"
);
indent
-=
2
;
new_line
();
log
+=
"end key-value pair"
;
return
ok
;
}
bool
begin_sequence
(
size_t
size
)
override
{
new_line
();
indent
+=
2
;
...
...
@@ -309,6 +178,23 @@ struct testee : serializer {
return
ok
;
}
bool
begin_associative_array
(
size_t
size
)
override
{
new_line
();
indent
+=
2
;
log
+=
"begin associative array of size "
;
log
+=
std
::
to_string
(
size
);
return
ok
;
}
bool
end_associative_array
()
override
{
if
(
indent
<
2
)
CAF_FAIL
(
"begin/end mismatch"
);
indent
-=
2
;
new_line
();
log
+=
"end associative array"
;
return
ok
;
}
bool
value
(
bool
)
override
{
new_line
();
log
+=
"bool value"
;
...
...
@@ -778,20 +664,20 @@ begin object basics
end tuple
end field
begin field v7
begin
sequence
of size 3
begin
tuple of size 2
begin
associative array
of size 3
begin
key-value pair
std::string value
int32_t value
end
tuple
begin
tuple of size 2
end
key-value pair
begin
key-value pair
std::string value
int32_t value
end
tuple
begin
tuple of size 2
end
key-value pair
begin
key-value pair
std::string value
int32_t value
end
tuple
end
sequence
end
key-value pair
end
associative array
end field
begin field v8
begin sequence of size 2
...
...
libcaf_core/test/settings_writer.cpp
0 → 100644
View file @
59ed7e08
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2020 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE settings_writer
#include "caf/settings_writer.hpp"
#include "caf/test/dsl.hpp"
#include "inspector-tests.hpp"
using
namespace
caf
;
using
namespace
std
::
literals
::
string_literals
;
namespace
{
using
i64
=
int64_t
;
constexpr
i64
operator
""
_i64
(
unsigned
long
long
int
x
)
{
return
static_cast
<
int64_t
>
(
x
);
}
using
i64_list
=
std
::
vector
<
i64
>
;
struct
fixture
{
settings
xs
;
template
<
class
T
>
void
set
(
const
T
&
value
)
{
settings_writer
writer
{
&
xs
};
if
(
!
inspect_object
(
writer
,
value
))
CAF_FAIL
(
"failed two write to settings: "
<<
writer
.
get_error
());
}
template
<
class
T
>
optional
<
T
>
get
(
const
settings
&
cfg
,
string_view
key
)
{
if
(
auto
ptr
=
get_if
<
T
>
(
&
cfg
,
key
))
return
*
ptr
;
return
none
;
}
template
<
class
T
>
optional
<
T
>
get
(
string_view
key
)
{
return
get
<
T
>
(
xs
,
key
);
}
};
}
// namespace
CAF_TEST_FIXTURE_SCOPE
(
settings_writer_tests
,
fixture
)
CAF_TEST
(
structs
become
dictionaries
)
{
set
(
foobar
{
"hello"
,
"world"
});
CAF_CHECK_EQUAL
(
get
<
std
::
string
>
(
"foo"
),
"hello"
s
);
CAF_CHECK_EQUAL
(
get
<
std
::
string
>
(
"bar"
),
"world"
s
);
}
CAF_TEST
(
nested
structs
become
nested
dictionaries
)
{
set
(
line
{{
10
,
20
,
30
},
{
70
,
60
,
50
}});
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"p1.x"
),
10
_i64
);
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"p1.y"
),
20
_i64
);
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"p1.z"
),
30
_i64
);
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"p2.x"
),
70
_i64
);
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"p2.y"
),
60
_i64
);
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"p2.z"
),
50
_i64
);
}
CAF_TEST
(
empty
types
and
maps
become
dictionaries
)
{
basics
tst
;
tst
.
v2
=
42
;
for
(
size_t
index
=
0
;
index
<
4
;
++
index
)
tst
.
v3
[
index
]
=
-
static_cast
<
int32_t
>
(
index
+
1
);
for
(
size_t
index
=
0
;
index
<
2
;
++
index
)
tst
.
v4
[
index
]
=
dummy_message
{{
static_cast
<
double
>
(
index
)}};
for
(
size_t
index
=
0
;
index
<
2
;
++
index
)
tst
.
v5
[
index
]
=
static_cast
<
int32_t
>
(
index
+
1
)
*
10
;
tst
.
v6
=
std
::
make_tuple
(
42
,
dummy_message
{{
"foobar"
s
}});
tst
.
v7
[
"one"
]
=
1
;
tst
.
v7
[
"two"
]
=
2
;
tst
.
v7
[
"three"
]
=
3
;
set
(
tst
);
CAF_MESSAGE
(
xs
);
CAF_CHECK_EQUAL
(
get
<
settings
>
(
"v1"
),
settings
{});
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"v2"
),
42
_i64
);
CAF_CHECK_EQUAL
(
get
<
i64_list
>
(
"v3"
),
i64_list
({
-
1
,
-
2
,
-
3
,
-
4
}));
if
(
auto
v4
=
get
<
config_value
::
list
>
(
"v4"
);
CAF_CHECK_EQUAL
(
v4
->
size
(),
2u
))
{
if
(
auto
v1
=
v4
->
front
();
CAF_CHECK
(
holds_alternative
<
settings
>
(
v1
)))
{
auto
&
v1_xs
=
caf
::
get
<
settings
>
(
v1
);
CAF_CHECK_EQUAL
(
get
<
double
>
(
v1_xs
,
"content"
),
0.0
);
CAF_CHECK_EQUAL
(
get
<
std
::
string
>
(
v1_xs
,
"@content-type"
),
to_string
(
type_name_v
<
double
>
));
}
if
(
auto
v2
=
v4
->
back
();
CAF_CHECK
(
holds_alternative
<
settings
>
(
v2
)))
{
auto
&
v2_xs
=
caf
::
get
<
settings
>
(
v2
);
CAF_CHECK_EQUAL
(
get
<
double
>
(
v2_xs
,
"content"
),
1.0
);
CAF_CHECK_EQUAL
(
get
<
std
::
string
>
(
v2_xs
,
"@content-type"
),
to_string
(
type_name_v
<
double
>
));
}
}
CAF_CHECK_EQUAL
(
get
<
i64_list
>
(
"v5"
),
i64_list
({
10
,
20
}));
// TODO: check v6
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"v7.one"
),
1
_i64
);
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"v7.two"
),
2
_i64
);
CAF_CHECK_EQUAL
(
get
<
i64
>
(
"v7.three"
),
3
_i64
);
CAF_CHECK_EQUAL
(
get
<
config_value
::
list
>
(
"v8"
),
config_value
::
list
());
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_test/caf/test/unit_test.hpp
View file @
59ed7e08
...
...
@@ -546,26 +546,29 @@ using caf_test_case_auto_fixture = caf::test::dummy_fixture;
} while (false)
#define CAF_CHECK(...) \
do { \
static_cast<void>(::caf::test::detail::check( \
::caf::test::engine::current_test(), __FILE__, __LINE__, #__VA_ARGS__, \
false, static_cast<bool>(__VA_ARGS__))); \
([&] { \
auto caf_check_res \
= ::caf::test::detail::check(::caf::test::engine::current_test(), \
__FILE__, __LINE__, #__VA_ARGS__, false, \
static_cast<bool>(__VA_ARGS__)); \
::caf::test::engine::last_check_file(__FILE__); \
::caf::test::engine::last_check_line(__LINE__); \
} while (false)
return caf_check_res; \
})()
#define CAF_CHECK_FUNC(func, x_expr, y_expr) \
do {
\
([&] {
\
func comparator; \
auto&& x_val___ = x_expr; \
auto&& y_val___ = y_expr; \
static_cast<void>(::caf::test::detail::check(
\
auto caf_check_res = ::caf::test::detail::check(
\
::caf::test::engine::current_test(), __FILE__, __LINE__, \
CAF_FUNC_EXPR(func, x_expr, y_expr), false, \
comparator(x_val___, y_val___), x_val___, y_val___)
);
\
comparator(x_val___, y_val___), x_val___, y_val___)
;
\
::caf::test::engine::last_check_file(__FILE__); \
::caf::test::engine::last_check_line(__LINE__); \
} while (false)
return caf_check_res; \
})()
#define CAF_CHECK_FAIL(...) \
do { \
...
...
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