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
16fb8828
Commit
16fb8828
authored
Dec 10, 2021
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix handling of the global category in settings
parent
46a747ac
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
78 additions
and
27 deletions
+78
-27
libcaf_core/caf/settings.hpp
libcaf_core/caf/settings.hpp
+1
-6
libcaf_core/src/settings.cpp
libcaf_core/src/settings.cpp
+53
-21
libcaf_core/test/settings.cpp
libcaf_core/test/settings.cpp
+24
-0
No files found.
libcaf_core/caf/settings.hpp
View file @
16fb8828
...
@@ -81,12 +81,7 @@ expected<T> get_as(const settings& xs, string_view name) {
...
@@ -81,12 +81,7 @@ expected<T> get_as(const settings& xs, string_view name) {
}
}
/// @private
/// @private
CAF_CORE_EXPORT
config_value
&
put_impl
(
settings
&
dict
,
CAF_CORE_EXPORT
config_value
&
put_impl
(
settings
&
dict
,
string_view
name
,
const
std
::
vector
<
string_view
>&
path
,
config_value
&
value
);
/// @private
CAF_CORE_EXPORT
config_value
&
put_impl
(
settings
&
dict
,
string_view
key
,
config_value
&
value
);
config_value
&
value
);
/// Converts `value` to a `config_value` and assigns it to `key`.
/// Converts `value` to a `config_value` and assigns it to `key`.
...
...
libcaf_core/src/settings.cpp
View file @
16fb8828
...
@@ -11,22 +11,32 @@ namespace caf {
...
@@ -11,22 +11,32 @@ namespace caf {
// note: to_string is implemented in config_value.cpp
// note: to_string is implemented in config_value.cpp
const
config_value
*
get_if
(
const
settings
*
xs
,
string_view
name
)
{
const
config_value
*
get_if
(
const
settings
*
xs
,
string_view
name
)
{
// Access the key directly unless the user specified a dot-separated path.
// The 'global' category is special in the sense that it refers back to the
auto
pos
=
name
.
find
(
'.'
);
// root. Somewhat like '::foo' in C++. This means we can just drop it here.
if
(
pos
==
std
::
string
::
npos
)
{
using
namespace
caf
::
literals
;
auto
i
=
xs
->
find
(
name
);
auto
gl
=
"global."
_sv
;
if
(
i
==
xs
->
end
())
if
(
starts_with
(
name
,
gl
))
return
nullptr
;
name
.
remove_prefix
(
gl
.
size
());
// We can't simply return the result here, because it might be a pointer.
// Climb down the tree. In each step, we resolve `xs` and `name` to the next
return
&
i
->
second
;
// level until there is no category left to resolve. At that point it's a
// trivial name lookup.
for
(;;)
{
if
(
auto
pos
=
name
.
find
(
'.'
);
pos
==
std
::
string
::
npos
)
{
if
(
auto
i
=
xs
->
find
(
name
);
i
==
xs
->
end
())
return
nullptr
;
else
return
&
i
->
second
;
}
else
{
auto
category
=
name
.
substr
(
0
,
pos
);
name
.
remove_prefix
(
pos
+
1
);
if
(
auto
i
=
xs
->
find
(
category
);
i
==
xs
->
end
()
||
!
holds_alternative
<
settings
>
(
i
->
second
))
{
return
nullptr
;
}
else
{
xs
=
std
::
addressof
(
get
<
settings
>
(
i
->
second
));
}
}
}
}
// We're dealing with a `<category>.<key>`-formatted string, extract the
// sub-settings by category and recurse.
auto
i
=
xs
->
find
(
name
.
substr
(
0
,
pos
));
if
(
i
==
xs
->
end
()
||
!
holds_alternative
<
config_value
::
dictionary
>
(
i
->
second
))
return
nullptr
;
return
get_if
(
&
get
<
config_value
::
dictionary
>
(
i
->
second
),
name
.
substr
(
pos
+
1
));
}
}
expected
<
std
::
string
>
get_or
(
const
settings
&
xs
,
string_view
name
,
expected
<
std
::
string
>
get_or
(
const
settings
&
xs
,
string_view
name
,
...
@@ -41,8 +51,7 @@ config_value& put_impl(settings& dict, const std::vector<string_view>& path,
...
@@ -41,8 +51,7 @@ config_value& put_impl(settings& dict, const std::vector<string_view>& path,
config_value
&
value
)
{
config_value
&
value
)
{
// Sanity check.
// Sanity check.
CAF_ASSERT
(
!
path
.
empty
());
CAF_ASSERT
(
!
path
.
empty
());
// TODO: We implicitly swallow the `global.` suffix as a hotfix, but we
// Like in get_if: we always drop a 'global.' suffix.
// actually should drop `global.` on the upper layers.
if
(
path
.
front
()
==
"global"
)
{
if
(
path
.
front
()
==
"global"
)
{
std
::
vector
<
string_view
>
new_path
{
path
.
begin
()
+
1
,
path
.
end
()};
std
::
vector
<
string_view
>
new_path
{
path
.
begin
()
+
1
,
path
.
end
()};
return
put_impl
(
dict
,
new_path
,
value
);
return
put_impl
(
dict
,
new_path
,
value
);
...
@@ -67,10 +76,33 @@ config_value& put_impl(settings& dict, const std::vector<string_view>& path,
...
@@ -67,10 +76,33 @@ config_value& put_impl(settings& dict, const std::vector<string_view>& path,
return
iter
->
second
;
return
iter
->
second
;
}
}
config_value
&
put_impl
(
settings
&
dict
,
string_view
key
,
config_value
&
value
)
{
config_value
&
put_impl
(
settings
&
dict
,
string_view
name
,
config_value
&
value
)
{
std
::
vector
<
string_view
>
path
;
// Like in get_if: we always drop a 'global.' suffix.
split
(
path
,
key
,
"."
);
using
namespace
caf
::
literals
;
return
put_impl
(
dict
,
path
,
value
);
auto
gl
=
"global."
_sv
;
if
(
starts_with
(
name
,
gl
))
name
.
remove_prefix
(
gl
.
size
());
// Climb down the tree, similar to get_if. Only this time, we create the
// necessary structure as we go until there is no category left to resolve. At
// that point it's a trivial insertion (override).
auto
xs
=
&
dict
;
for
(;;)
{
if
(
auto
pos
=
name
.
find
(
'.'
);
pos
==
string_view
::
npos
)
{
return
xs
->
insert_or_assign
(
name
,
std
::
move
(
value
)).
first
->
second
;
}
else
{
auto
category
=
name
.
substr
(
0
,
pos
);
name
.
remove_prefix
(
pos
+
1
);
if
(
auto
i
=
xs
->
find
(
category
);
i
==
xs
->
end
())
{
auto
j
=
xs
->
emplace
(
category
,
settings
{}).
first
;
xs
=
std
::
addressof
(
get
<
settings
>
(
j
->
second
));
}
else
if
(
!
holds_alternative
<
settings
>
(
i
->
second
))
{
i
->
second
=
settings
{};
xs
=
std
::
addressof
(
get
<
settings
>
(
i
->
second
));
}
else
{
xs
=
std
::
addressof
(
get
<
settings
>
(
i
->
second
));
}
}
}
}
}
config_value
::
list
&
put_list
(
settings
&
xs
,
std
::
string
name
)
{
config_value
::
list
&
put_list
(
settings
&
xs
,
std
::
string
name
)
{
...
...
libcaf_core/test/settings.cpp
View file @
16fb8828
...
@@ -171,4 +171,28 @@ CAF_TEST(read_config accepts the to_string output of settings) {
...
@@ -171,4 +171,28 @@ CAF_TEST(read_config accepts the to_string output of settings) {
CHECK_EQ
(
x
,
y
);
CHECK_EQ
(
x
,
y
);
}
}
SCENARIO
(
"put_missing normalizes 'global' suffixes"
)
{
GIVEN
(
"empty settings"
)
{
settings
uut
;
WHEN
(
"calling put_missing with and without 'global' suffix"
)
{
THEN
(
"put_missing drops the 'global' suffix"
)
{
put_missing
(
uut
,
"global.foo"
,
"bar"
s
);
CHECK_EQ
(
get_as
<
std
::
string
>
(
uut
,
"foo"
),
"bar"
s
);
CHECK_EQ
(
get_as
<
std
::
string
>
(
uut
,
"global.foo"
),
"bar"
s
);
}
}
}
GIVEN
(
"settings with a value for 'foo'"
)
{
settings
uut
;
uut
[
"foo"
]
=
"bar"
s
;
WHEN
(
"calling put_missing 'global.foo'"
)
{
THEN
(
"the function call results in a no-op"
)
{
put_missing
(
uut
,
"global.foo"
,
"baz"
s
);
CHECK_EQ
(
get_as
<
std
::
string
>
(
uut
,
"foo"
),
"bar"
s
);
CHECK_EQ
(
get_as
<
std
::
string
>
(
uut
,
"global.foo"
),
"bar"
s
);
}
}
}
}
END_FIXTURE_SCOPE
()
END_FIXTURE_SCOPE
()
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