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
6962996a
Commit
6962996a
authored
Dec 13, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve on-the-fly dictionary conversions
parent
d3b18572
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
78 additions
and
10 deletions
+78
-10
libcaf_core/caf/config_value.hpp
libcaf_core/caf/config_value.hpp
+4
-1
libcaf_core/caf/config_value_reader.hpp
libcaf_core/caf/config_value_reader.hpp
+4
-0
libcaf_core/src/config_value.cpp
libcaf_core/src/config_value.cpp
+35
-7
libcaf_core/src/config_value_reader.cpp
libcaf_core/src/config_value_reader.cpp
+9
-2
libcaf_core/test/config_value.cpp
libcaf_core/test/config_value.cpp
+26
-0
No files found.
libcaf_core/caf/config_value.hpp
View file @
6962996a
...
...
@@ -130,7 +130,10 @@ public:
/// Returns the value as a list, converting it to one if needed.
list
&
as_list
();
/// Returns the value as a dictionary, converting it to one if needed.
/// Returns the value as a dictionary, converting it to one if needed. The
/// only data structure that CAF can convert to a dictionary is a list of
/// lists, where each nested list contains exactly two elements (key and
/// value). In all other cases, the conversion results in an empty dictionary.
dictionary
&
as_dictionary
();
/// Appends `x` to a list. Converts this config value to a list first by
...
...
libcaf_core/caf/config_value_reader.hpp
View file @
6962996a
...
...
@@ -23,6 +23,7 @@
#include "caf/dictionary.hpp"
#include "caf/fwd.hpp"
#include <memory>
#include <stack>
#include <vector>
...
...
@@ -169,6 +170,9 @@ private:
bool
fetch_object_type
(
const
settings
*
obj
,
type_id_t
&
type
);
stack_type
st_
;
// Stores on-the-fly converted values.
std
::
vector
<
std
::
unique_ptr
<
config_value
>>
scratch_space_
;
};
}
// namespace caf
libcaf_core/src/config_value.cpp
View file @
6962996a
...
...
@@ -129,9 +129,15 @@ config_value::list& config_value::as_list() {
}
config_value
::
dictionary
&
config_value
::
as_dictionary
()
{
if
(
!
holds_alternative
<
dictionary
>
(
*
this
))
*
this
=
dictionary
{};
return
get
<
dictionary
>
(
*
this
);
if
(
auto
dict
=
get_if
<
config_value
::
dictionary
>
(
&
data_
))
{
return
*
dict
;
}
else
if
(
auto
lifted
=
to_dictionary
())
{
data_
=
std
::
move
(
*
lifted
);
return
get
<
config_value
::
dictionary
>
(
data_
);
}
else
{
data_
=
config_value
::
dictionary
{};
return
get
<
config_value
::
dictionary
>
(
data_
);
}
}
void
config_value
::
append
(
config_value
x
)
{
...
...
@@ -366,12 +372,34 @@ expected<config_value::list> config_value::to_list() const {
expected
<
config_value
::
dictionary
>
config_value
::
to_dictionary
()
const
{
using
result_type
=
expected
<
dictionary
>
;
auto
f
=
detail
::
make_overload
(
no_conversions
<
dictionary
,
none_t
,
bool
,
integer
,
timespan
,
real
,
uri
,
list
>
(),
[](
const
std
::
string
&
x
)
{
no_conversions
<
dictionary
,
none_t
,
bool
,
integer
,
timespan
,
real
,
uri
>
(),
[](
const
list
&
x
)
{
dictionary
tmp
;
if
(
detail
::
parse
(
x
,
tmp
,
detail
::
require_opening_char
)
==
none
)
auto
lift
=
[
&
tmp
](
const
config_value
&
element
)
{
auto
ls
=
element
.
to_list
();
if
(
ls
&&
ls
->
size
()
==
2
)
return
tmp
.
emplace
(
to_string
((
*
ls
)[
0
]),
std
::
move
((
*
ls
)[
1
])).
second
;
else
return
false
;
};
if
(
std
::
all_of
(
x
.
begin
(),
x
.
end
(),
lift
))
{
return
result_type
{
std
::
move
(
tmp
)};
}
else
{
auto
err
=
make_error
(
sec
::
conversion_failed
,
"cannot convert list to dictionary unless each "
"element in the list is a key-value pair"
);
return
result_type
{
std
::
move
(
err
)};
}
},
[](
const
std
::
string
&
x
)
{
if
(
dictionary
tmp
;
detail
::
parse
(
x
,
tmp
)
==
none
)
{
return
result_type
{
std
::
move
(
tmp
)};
}
if
(
list
tmp
;
detail
::
parse
(
x
,
tmp
)
==
none
)
{
config_value
ls
{
std
::
move
(
tmp
)};
if
(
auto
res
=
ls
.
to_dictionary
())
return
res
;
}
std
::
string
msg
=
"cannot convert "
;
detail
::
print_escaped
(
msg
,
x
);
msg
+=
" to a dictionary"
;
...
...
libcaf_core/src/config_value_reader.cpp
View file @
6962996a
...
...
@@ -179,10 +179,17 @@ bool config_value_reader::begin_object(type_id_t type, string_view) {
},
[
this
](
const
config_value
*
val
)
{
if
(
auto
obj
=
get_if
<
settings
>
(
val
))
{
// Morph into an object. This value gets "consumed" by
// begin_object/end_object.
// Unbox the dictionary.
st_
.
top
()
=
obj
;
return
true
;
}
else
if
(
auto
dict
=
val
->
to_dictionary
())
{
// Replace the actual config value on the stack with the on-the-fly
// converted dictionary.
auto
ptr
=
std
::
make_unique
<
config_value
>
(
std
::
move
(
*
dict
));
const
settings
*
unboxed
=
std
::
addressof
(
get
<
settings
>
(
*
ptr
));
st_
.
top
()
=
unboxed
;
scratch_space_
.
emplace_back
(
std
::
move
(
ptr
));
return
true
;
}
else
{
emplace_error
(
sec
::
conversion_failed
,
"cannot read input as object"
);
return
false
;
...
...
libcaf_core/test/config_value.cpp
View file @
6962996a
...
...
@@ -719,6 +719,32 @@ SCENARIO("config values can parse their own to_string output") {
}
}
SCENARIO
(
"config values can convert lists of tuples to dictionaries"
)
{
GIVEN
(
"a config value containing a list of key-value pairs (lists)"
)
{
WHEN
(
"calling as_dictionary on the object"
)
{
THEN
(
"the config value lifts the key-value pair list to a dictionary"
)
{
auto
x
=
make_config_value_list
(
make_config_value_list
(
"one"
,
1
),
make_config_value_list
(
2
,
"two"
));
auto
&
dict
=
x
.
as_dictionary
();
CHECK_EQ
(
dict
.
size
(),
2u
);
CHECK_EQ
(
dict
[
"one"
],
1
);
CHECK_EQ
(
dict
[
"2"
],
"two"
s
);
}
}
}
GIVEN
(
"a config value containing a string representing a kvp list"
)
{
WHEN
(
"calling as_dictionary on the object"
)
{
THEN
(
"the config value lifts the key-value pair list to a dictionary"
)
{
auto
x
=
config_value
{
R"_([["one", 1], [2, "two"]])_"
};
auto
&
dict
=
x
.
as_dictionary
();
CHECK_EQ
(
dict
.
size
(),
2u
);
CHECK_EQ
(
dict
[
"one"
],
1
);
CHECK_EQ
(
dict
[
"2"
],
"two"
s
);
}
}
}
}
CAF_TEST
(
default_constructed
)
{
config_value
x
;
CAF_CHECK_EQUAL
(
holds_alternative
<
none_t
>
(
x
),
true
);
...
...
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