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
4d3e2683
Unverified
Commit
4d3e2683
authored
Aug 15, 2019
by
Joseph Noir
Committed by
GitHub
Aug 15, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #877
Fix output of --dump-config
parents
c4b567ab
43096238
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
258 additions
and
50 deletions
+258
-50
libcaf_core/caf/actor_system_config.hpp
libcaf_core/caf/actor_system_config.hpp
+4
-0
libcaf_core/caf/config_value.hpp
libcaf_core/caf/config_value.hpp
+43
-7
libcaf_core/caf/detail/type_traits.hpp
libcaf_core/caf/detail/type_traits.hpp
+63
-9
libcaf_core/caf/settings.hpp
libcaf_core/caf/settings.hpp
+21
-19
libcaf_core/src/actor_system_config.cpp
libcaf_core/src/actor_system_config.cpp
+108
-15
libcaf_core/src/settings.cpp
libcaf_core/src/settings.cpp
+19
-0
No files found.
libcaf_core/caf/actor_system_config.hpp
View file @
4d3e2683
...
@@ -106,6 +106,10 @@ public:
...
@@ -106,6 +106,10 @@ public:
/// @private
/// @private
settings
content
;
settings
content
;
/// Extracts all parameters from the config, including entries with default
/// values.
virtual
settings
dump_content
()
const
;
/// Sets a config by using its INI name `config_name` to `config_value`.
/// Sets a config by using its INI name `config_name` to `config_value`.
template
<
class
T
>
template
<
class
T
>
actor_system_config
&
set
(
string_view
name
,
T
&&
value
)
{
actor_system_config
&
set
(
string_view
name
,
T
&&
value
)
{
...
...
libcaf_core/caf/config_value.hpp
View file @
4d3e2683
...
@@ -127,22 +127,22 @@ public:
...
@@ -127,22 +127,22 @@ public:
const
char
*
type_name
()
const
noexcept
;
const
char
*
type_name
()
const
noexcept
;
/// Returns the underlying variant.
/// Returns the underlying variant.
inline
variant_type
&
get_data
()
{
variant_type
&
get_data
()
{
return
data_
;
return
data_
;
}
}
/// Returns the underlying variant.
/// Returns the underlying variant.
inline
const
variant_type
&
get_data
()
const
{
const
variant_type
&
get_data
()
const
{
return
data_
;
return
data_
;
}
}
/// Returns a pointer to the underlying variant.
/// Returns a pointer to the underlying variant.
inline
variant_type
*
get_data_ptr
()
{
variant_type
*
get_data_ptr
()
{
return
&
data_
;
return
&
data_
;
}
}
/// Returns a pointer to the underlying variant.
/// Returns a pointer to the underlying variant.
inline
const
variant_type
*
get_data_ptr
()
const
{
const
variant_type
*
get_data_ptr
()
const
{
return
&
data_
;
return
&
data_
;
}
}
...
@@ -153,18 +153,22 @@ private:
...
@@ -153,18 +153,22 @@ private:
// -- auto conversion of related types ---------------------------------------
// -- auto conversion of related types ---------------------------------------
inline
void
set
(
bool
x
)
{
void
set
(
bool
x
)
{
data_
=
x
;
data_
=
x
;
}
}
inline
void
set
(
float
x
)
{
void
set
(
float
x
)
{
data_
=
static_cast
<
double
>
(
x
);
data_
=
static_cast
<
double
>
(
x
);
}
}
inline
void
set
(
const
char
*
x
)
{
void
set
(
const
char
*
x
)
{
data_
=
std
::
string
{
x
};
data_
=
std
::
string
{
x
};
}
}
void
set
(
string_view
x
)
{
data_
=
std
::
string
{
x
.
begin
(),
x
.
end
()};
}
template
<
class
T
>
template
<
class
T
>
detail
::
enable_if_t
<
detail
::
is_one_of
<
T
,
real
,
atom
,
timespan
,
uri
,
string
,
detail
::
enable_if_t
<
detail
::
is_one_of
<
T
,
real
,
atom
,
timespan
,
uri
,
string
,
list
,
dictionary
>::
value
>
list
,
dictionary
>::
value
>
...
@@ -172,6 +176,38 @@ private:
...
@@ -172,6 +176,38 @@ private:
data_
=
std
::
move
(
x
);
data_
=
std
::
move
(
x
);
}
}
template
<
class
T
>
detail
::
enable_if_t
<
detail
::
is_list_like
<
detail
::
decay_t
<
T
>>::
value
&&
!
std
::
is_same
<
detail
::
decay_t
<
T
>
,
list
>::
value
>
set
(
T
&&
xs
)
{
// Move values from the old list into the new list if `xs` is an rvalue.
using
namespace
detail
;
using
xs_type
=
decltype
(
xs
);
using
value_type
=
typename
decay_t
<
T
>::
value_type
;
using
fwd_type
=
conditional_t
<
std
::
is_rvalue_reference
<
xs_type
>::
value
,
value_type
&&
,
const
value_type
&>
;
auto
&
lst
=
as_list
();
lst
.
clear
();
for
(
auto
&
x
:
xs
)
lst
.
emplace_back
(
config_value
{
static_cast
<
fwd_type
>
(
x
)});
}
template
<
class
T
>
detail
::
enable_if_t
<
detail
::
is_map_like
<
detail
::
decay_t
<
T
>>::
value
&&
!
std
::
is_same
<
detail
::
decay_t
<
T
>
,
dictionary
>::
value
>
set
(
T
&&
xs
)
{
// Move values from the old list into the new list if `xs` is an rvalue.
using
namespace
detail
;
using
xs_type
=
decltype
(
xs
);
using
mapped_type
=
typename
decay_t
<
T
>::
mapped_type
;
using
fwd_type
=
conditional_t
<
std
::
is_rvalue_reference
<
xs_type
>::
value
,
mapped_type
&&
,
const
mapped_type
&>
;
auto
&
dict
=
as_dictionary
();
dict
.
clear
();
for
(
auto
&
kvp
:
xs
)
dict
.
emplace
(
kvp
.
first
,
static_cast
<
fwd_type
>
(
kvp
.
second
));
}
template
<
class
T
>
template
<
class
T
>
detail
::
enable_if_t
<
std
::
is_integral
<
T
>::
value
>
set
(
T
x
)
{
detail
::
enable_if_t
<
std
::
is_integral
<
T
>::
value
>
set
(
T
x
)
{
data_
=
static_cast
<
int64_t
>
(
x
);
data_
=
static_cast
<
int64_t
>
(
x
);
...
...
libcaf_core/caf/detail/type_traits.hpp
View file @
4d3e2683
...
@@ -33,27 +33,52 @@
...
@@ -33,27 +33,52 @@
#include "caf/detail/type_list.hpp"
#include "caf/detail/type_list.hpp"
#define CAF_HAS_MEMBER_TRAIT(name) \
#define CAF_HAS_MEMBER_TRAIT(name) \
template <class T> \
template <class T> \
struct has_##name##_member { \
class has_##name##_member { \
template <class U> \
private: \
static auto sfinae(U* x) -> decltype(x->name(), std::true_type()); \
template <class U> \
static auto sfinae(U* x) -> decltype(x->name(), std::true_type()); \
\
\
template <class U>
\
template <class U>
\
static auto sfinae(...) -> std::false_type;
\
static auto sfinae(...) -> std::false_type;
\
\
\
using type = decltype(sfinae<T>(nullptr)); \
using sfinae_type = decltype(sfinae<T>(nullptr)); \
static constexpr bool value = type::value; \
\
}
public: \
static constexpr bool value = sfinae_type::value; \
}
#define CAF_HAS_ALIAS_TRAIT(name) \
template <class T> \
class has_##name##_alias { \
private: \
template <class C> \
static std::true_type sfinae(C* ptr, typename C::name* arg = nullptr); \
\
static std::false_type sfinae(void* ptr); \
\
using sfinae_type = decltype(sfinae(static_cast<T*>(nullptr))); \
\
public: \
static constexpr bool value = sfinae_type::value; \
}
namespace
caf
{
namespace
caf
{
namespace
detail
{
namespace
detail
{
// -- backport of C++14 additions ----------------------------------------------
template
<
class
T
>
template
<
class
T
>
using
decay_t
=
typename
std
::
decay
<
T
>::
type
;
using
decay_t
=
typename
std
::
decay
<
T
>::
type
;
template
<
bool
B
,
class
T
,
class
F
>
using
conditional_t
=
typename
std
::
conditional
<
B
,
T
,
F
>::
type
;
template
<
bool
V
,
class
T
=
void
>
template
<
bool
V
,
class
T
=
void
>
using
enable_if_t
=
typename
std
::
enable_if
<
V
,
T
>::
type
;
using
enable_if_t
=
typename
std
::
enable_if
<
V
,
T
>::
type
;
// -- custom traits ------------------------------------------------------------
template
<
class
Trait
,
class
T
=
void
>
template
<
class
Trait
,
class
T
=
void
>
using
enable_if_tt
=
typename
std
::
enable_if
<
Trait
::
value
,
T
>::
type
;
using
enable_if_tt
=
typename
std
::
enable_if
<
Trait
::
value
,
T
>::
type
;
...
@@ -708,6 +733,35 @@ struct is_same_ish
...
@@ -708,6 +733,35 @@ struct is_same_ish
template
<
class
>
template
<
class
>
struct
always_false
:
std
::
false_type
{};
struct
always_false
:
std
::
false_type
{};
// -- traits to check for STL-style type aliases -------------------------------
CAF_HAS_ALIAS_TRAIT
(
value_type
);
CAF_HAS_ALIAS_TRAIT
(
key_type
);
CAF_HAS_ALIAS_TRAIT
(
mapped_type
);
// -- constexpr functions for use in enable_if & friends -----------------------
/// Checks whether T behaves like a `std::map` or a `std::unordered_map`.
template
<
class
T
>
struct
is_map_like
{
static
constexpr
bool
value
=
is_iterable
<
T
>::
value
&&
has_key_type_alias
<
T
>::
value
&&
has_mapped_type_alias
<
T
>::
value
;
};
/// Checks whether T behaves like a `std::vector` or a `std::list`.
template
<
class
T
>
struct
is_list_like
{
static
constexpr
bool
value
=
is_iterable
<
T
>::
value
&&
has_value_type_alias
<
T
>::
value
&&
!
has_key_type_alias
<
T
>::
value
&&
!
has_mapped_type_alias
<
T
>::
value
;
};
}
// namespace detail
}
// namespace detail
}
// namespace caf
}
// namespace caf
#undef CAF_HAS_MEMBER_TRAIT
#undef CAF_HAS_ALIAS_TRAIT
libcaf_core/caf/settings.hpp
View file @
4d3e2683
...
@@ -30,29 +30,18 @@ namespace caf {
...
@@ -30,29 +30,18 @@ namespace caf {
/// @relates config_value
/// @relates config_value
using
settings
=
dictionary
<
config_value
>
;
using
settings
=
dictionary
<
config_value
>
;
/// Tries to retrieve the value associated to `name` from `xs`.
/// @relates config_value
const
config_value
*
get_if
(
const
settings
*
xs
,
string_view
name
);
/// Tries to retrieve the value associated to `name` from `xs`.
/// Tries to retrieve the value associated to `name` from `xs`.
/// @relates config_value
/// @relates config_value
template
<
class
T
>
template
<
class
T
>
optional
<
T
>
get_if
(
const
settings
*
xs
,
string_view
name
)
{
optional
<
T
>
get_if
(
const
settings
*
xs
,
string_view
name
)
{
// Access the key directly unless the user specified a dot-separated path.
if
(
auto
value
=
get_if
(
xs
,
name
))
auto
pos
=
name
.
find
(
'.'
);
if
(
auto
ptr
=
get_if
<
T
>
(
value
))
if
(
pos
==
std
::
string
::
npos
)
{
return
*
ptr
;
auto
i
=
xs
->
find
(
name
);
return
none
;
if
(
i
==
xs
->
end
())
return
none
;
// We can't simply return the result here, because it might be a pointer.
auto
result
=
get_if
<
T
>
(
&
i
->
second
);
if
(
result
)
return
*
result
;
return
none
;
}
// 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
none
;
return
get_if
<
T
>
(
&
get
<
config_value
::
dictionary
>
(
i
->
second
),
name
.
substr
(
pos
+
1
));
}
}
template
<
class
T
>
template
<
class
T
>
...
@@ -92,6 +81,19 @@ config_value& put(settings& dict, string_view key, T&& value) {
...
@@ -92,6 +81,19 @@ config_value& put(settings& dict, string_view key, T&& value) {
return
put_impl
(
dict
,
key
,
tmp
);
return
put_impl
(
dict
,
key
,
tmp
);
}
}
/// Converts `value` to a `config_value` and assigns it to `key` if `value` is
/// currently missing in `xs`.
/// @param xs Dictionary of key-value pairs.
/// @param key Human-readable nested keys in the form `category.key`.
/// @param value New value for given `key`.
template
<
class
T
>
void
put_missing
(
settings
&
xs
,
string_view
key
,
T
&&
value
)
{
if
(
get_if
(
&
xs
,
key
)
!=
nullptr
)
return
;
config_value
tmp
{
std
::
forward
<
T
>
(
value
)};
put_impl
(
xs
,
key
,
tmp
);
}
/// Inserts a new list named `name` into the dictionary `xs` and returns
/// Inserts a new list named `name` into the dictionary `xs` and returns
/// a reference to it. Overrides existing entries with the same name.
/// a reference to it. Overrides existing entries with the same name.
config_value
::
list
&
put_list
(
settings
&
xs
,
std
::
string
name
);
config_value
::
list
&
put_list
(
settings
&
xs
,
std
::
string
name
);
...
...
libcaf_core/src/actor_system_config.cpp
View file @
4d3e2683
...
@@ -129,12 +129,6 @@ actor_system_config::actor_system_config()
...
@@ -129,12 +129,6 @@ actor_system_config::actor_system_config()
"schedule utility actors instead of dedicating threads"
)
"schedule utility actors instead of dedicating threads"
)
.
add
<
bool
>
(
"manual-multiplexing"
,
.
add
<
bool
>
(
"manual-multiplexing"
,
"disables background activity of the multiplexer"
)
"disables background activity of the multiplexer"
)
.
add
<
size_t
>
(
"cached-udp-buffers"
,
"maximum for cached UDP send buffers (default: 10)"
)
.
add
<
size_t
>
(
"max-pending-messages"
,
"maximum for reordering of UDP receive buffers (default: 10)"
)
.
add
<
bool
>
(
"disable-tcp"
,
"disables communication via TCP"
)
.
add
<
bool
>
(
"enable-udp"
,
"enable communication via UDP"
)
.
add
<
size_t
>
(
"workers"
,
"number of deserialization workers"
);
.
add
<
size_t
>
(
"workers"
,
"number of deserialization workers"
);
opt_group
(
custom_options_
,
"opencl"
)
opt_group
(
custom_options_
,
"opencl"
)
.
add
<
std
::
vector
<
size_t
>>
(
"device-ids"
,
"whitelist for OpenCL devices"
);
.
add
<
std
::
vector
<
size_t
>>
(
"device-ids"
,
"whitelist for OpenCL devices"
);
...
@@ -154,6 +148,73 @@ actor_system_config::actor_system_config()
...
@@ -154,6 +148,73 @@ actor_system_config::actor_system_config()
error_renderers
.
emplace
(
atom
(
"exit"
),
render_exit_reason
);
error_renderers
.
emplace
(
atom
(
"exit"
),
render_exit_reason
);
}
}
settings
actor_system_config
::
dump_content
()
const
{
settings
result
=
content
;
// -- streaming parameters
auto
&
stream_group
=
result
[
"stream"
].
as_dictionary
();
put_missing
(
stream_group
,
"desired-batch-complexity"
,
defaults
::
stream
::
desired_batch_complexity
);
put_missing
(
stream_group
,
"max-batch-delay"
,
defaults
::
stream
::
max_batch_delay
);
put_missing
(
stream_group
,
"credit-round-interval"
,
defaults
::
stream
::
credit_round_interval
);
// -- scheduler parameters
auto
&
scheduler_group
=
result
[
"scheduler"
].
as_dictionary
();
put_missing
(
scheduler_group
,
"policy"
,
defaults
::
scheduler
::
policy
);
put_missing
(
scheduler_group
,
"max-threads"
,
defaults
::
scheduler
::
max_threads
);
put_missing
(
scheduler_group
,
"max-throughput"
,
defaults
::
scheduler
::
max_throughput
);
put_missing
(
scheduler_group
,
"enable-profiling"
,
false
);
put_missing
(
scheduler_group
,
"profiling-resolution"
,
defaults
::
scheduler
::
profiling_resolution
);
put_missing
(
scheduler_group
,
"profiling-output-file"
,
std
::
string
{});
// -- work-stealing parameters
auto
&
work_stealing_group
=
result
[
"work-stealing"
].
as_dictionary
();
put_missing
(
work_stealing_group
,
"aggressive-poll-attempts"
,
defaults
::
work_stealing
::
aggressive_poll_attempts
);
put_missing
(
work_stealing_group
,
"aggressive-steal-interval"
,
defaults
::
work_stealing
::
aggressive_steal_interval
);
put_missing
(
work_stealing_group
,
"moderate-poll-attempts"
,
defaults
::
work_stealing
::
moderate_poll_attempts
);
put_missing
(
work_stealing_group
,
"moderate-steal-interval"
,
defaults
::
work_stealing
::
moderate_steal_interval
);
put_missing
(
work_stealing_group
,
"moderate-sleep-duration"
,
defaults
::
work_stealing
::
moderate_sleep_duration
);
put_missing
(
work_stealing_group
,
"relaxed-steal-interval"
,
defaults
::
work_stealing
::
relaxed_steal_interval
);
put_missing
(
work_stealing_group
,
"relaxed-sleep-duration"
,
defaults
::
work_stealing
::
relaxed_sleep_duration
);
// -- logger parameters
auto
&
logger_group
=
result
[
"logger"
].
as_dictionary
();
put_missing
(
logger_group
,
"file-name"
,
defaults
::
logger
::
file_name
);
put_missing
(
logger_group
,
"file-format"
,
defaults
::
logger
::
file_format
);
put_missing
(
logger_group
,
"file-verbosity"
,
defaults
::
logger
::
file_verbosity
);
put_missing
(
logger_group
,
"console"
,
defaults
::
logger
::
console
);
put_missing
(
logger_group
,
"console-format"
,
defaults
::
logger
::
console_format
);
put_missing
(
logger_group
,
"console-verbosity"
,
defaults
::
logger
::
console_verbosity
);
put_missing
(
logger_group
,
"component-blacklist"
,
std
::
vector
<
atom_value
>
{});
put_missing
(
logger_group
,
"inline-output"
,
false
);
// -- middleman parameters
auto
&
middleman_group
=
result
[
"middleman"
].
as_dictionary
();
put_missing
(
middleman_group
,
"app-identifiers"
,
defaults
::
middleman
::
app_identifiers
);
put_missing
(
middleman_group
,
"enable-automatic-connections"
,
false
);
put_missing
(
middleman_group
,
"max-consecutive-reads"
,
defaults
::
middleman
::
max_consecutive_reads
);
put_missing
(
middleman_group
,
"heartbeat-interval"
,
defaults
::
middleman
::
heartbeat_interval
);
put_missing
(
middleman_group
,
"workers"
,
defaults
::
middleman
::
workers
);
// -- opencl parameters
auto
&
openssl_group
=
result
[
"openssl"
].
as_dictionary
();
put_missing
(
openssl_group
,
"certificate"
,
std
::
string
{});
put_missing
(
openssl_group
,
"key"
,
std
::
string
{});
put_missing
(
openssl_group
,
"passphrase"
,
std
::
string
{});
put_missing
(
openssl_group
,
"capath"
,
std
::
string
{});
put_missing
(
openssl_group
,
"cafile"
,
std
::
string
{});
return
result
;
}
std
::
string
std
::
string
actor_system_config
::
make_help_text
(
const
std
::
vector
<
message
::
cli_arg
>&
xs
)
{
actor_system_config
::
make_help_text
(
const
std
::
vector
<
message
::
cli_arg
>&
xs
)
{
auto
is_no_caf_option
=
[](
const
message
::
cli_arg
&
arg
)
{
auto
is_no_caf_option
=
[](
const
message
::
cli_arg
&
arg
)
{
...
@@ -238,6 +299,45 @@ bool operator!=(ini_iter iter, ini_sentinel) {
...
@@ -238,6 +299,45 @@ bool operator!=(ini_iter iter, ini_sentinel) {
return
!
iter
.
ini
->
fail
();
return
!
iter
.
ini
->
fail
();
}
}
struct
indentation
{
size_t
size
;
};
indentation
operator
+
(
indentation
x
,
size_t
y
)
noexcept
{
return
{
x
.
size
+
y
};
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
indentation
indent
)
{
for
(
size_t
i
=
0
;
i
<
indent
.
size
;
++
i
)
out
.
put
(
' '
);
return
out
;
}
void
print
(
const
config_value
::
dictionary
&
xs
,
indentation
indent
)
{
using
std
::
cout
;
for
(
const
auto
&
kvp
:
xs
)
{
if
(
kvp
.
first
==
"dump-config"
)
continue
;
if
(
auto
submap
=
get_if
<
config_value
::
dictionary
>
(
&
kvp
.
second
))
{
cout
<<
indent
<<
kvp
.
first
<<
" {
\n
"
;
print
(
*
submap
,
indent
+
2
);
cout
<<
indent
<<
"}
\n
"
;
}
else
if
(
auto
lst
=
get_if
<
config_value
::
list
>
(
&
kvp
.
second
))
{
if
(
lst
->
empty
())
{
cout
<<
indent
<<
kvp
.
first
<<
" = []
\n
"
;
}
else
{
cout
<<
indent
<<
kvp
.
first
<<
" = [
\n
"
;
auto
list_indent
=
indent
+
2
;
for
(
auto
&
x
:
*
lst
)
cout
<<
list_indent
<<
to_string
(
x
)
<<
",
\n
"
;
cout
<<
indent
<<
"]
\n
"
;
}
}
else
{
cout
<<
indent
<<
kvp
.
first
<<
" = "
<<
to_string
(
kvp
.
second
)
<<
'\n'
;
}
}
};
}
// namespace <anonymous>
}
// namespace <anonymous>
error
actor_system_config
::
parse
(
string_list
args
,
std
::
istream
&
ini
)
{
error
actor_system_config
::
parse
(
string_list
args
,
std
::
istream
&
ini
)
{
...
@@ -269,16 +369,9 @@ error actor_system_config::parse(string_list args, std::istream& ini) {
...
@@ -269,16 +369,9 @@ error actor_system_config::parse(string_list args, std::istream& ini) {
bool
long_help
=
get_or
(
content
,
"long-help"
,
false
);
bool
long_help
=
get_or
(
content
,
"long-help"
,
false
);
std
::
cout
<<
custom_options_
.
help_text
(
!
long_help
)
<<
std
::
endl
;
std
::
cout
<<
custom_options_
.
help_text
(
!
long_help
)
<<
std
::
endl
;
}
}
// Generate
INI
dump if needed.
// Generate
config
dump if needed.
if
(
!
cli_helptext_printed
&&
get_or
(
content
,
"dump-config"
,
false
))
{
if
(
!
cli_helptext_printed
&&
get_or
(
content
,
"dump-config"
,
false
))
{
for
(
auto
&
category
:
content
)
{
print
(
dump_content
(),
indentation
{
0
});
if
(
auto
dict
=
get_if
<
config_value
::
dictionary
>
(
&
category
.
second
))
{
std
::
cout
<<
'['
<<
category
.
first
<<
"]
\n
"
;
for
(
auto
&
kvp
:
*
dict
)
if
(
kvp
.
first
!=
"dump-config"
)
std
::
cout
<<
kvp
.
first
<<
'='
<<
to_string
(
kvp
.
second
)
<<
'\n'
;
}
}
std
::
cout
<<
std
::
flush
;
std
::
cout
<<
std
::
flush
;
cli_helptext_printed
=
true
;
cli_helptext_printed
=
true
;
}
}
...
...
libcaf_core/src/settings.cpp
View file @
4d3e2683
...
@@ -22,6 +22,25 @@
...
@@ -22,6 +22,25 @@
namespace
caf
{
namespace
caf
{
const
config_value
*
get_if
(
const
settings
*
xs
,
string_view
name
)
{
// Access the key directly unless the user specified a dot-separated path.
auto
pos
=
name
.
find
(
'.'
);
if
(
pos
==
std
::
string
::
npos
)
{
auto
i
=
xs
->
find
(
name
);
if
(
i
==
xs
->
end
())
return
nullptr
;
// We can't simply return the result here, because it might be a pointer.
return
&
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
));
}
std
::
string
get_or
(
const
settings
&
xs
,
string_view
name
,
std
::
string
get_or
(
const
settings
&
xs
,
string_view
name
,
string_view
default_value
)
{
string_view
default_value
)
{
auto
result
=
get_if
<
std
::
string
>
(
&
xs
,
name
);
auto
result
=
get_if
<
std
::
string
>
(
&
xs
,
name
);
...
...
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