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
c525c605
Unverified
Commit
c525c605
authored
Oct 15, 2019
by
Joseph Noir
Committed by
GitHub
Oct 15, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #931
Fix several issues with config values
parents
11c4eaca
760b0989
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
494 additions
and
182 deletions
+494
-182
libcaf_core/caf/actor_system_config.hpp
libcaf_core/caf/actor_system_config.hpp
+11
-4
libcaf_core/caf/config_value.hpp
libcaf_core/caf/config_value.hpp
+1
-0
libcaf_core/caf/config_value_field.hpp
libcaf_core/caf/config_value_field.hpp
+6
-9
libcaf_core/caf/config_value_object_access.hpp
libcaf_core/caf/config_value_object_access.hpp
+9
-11
libcaf_core/caf/detail/config_value_field_base.hpp
libcaf_core/caf/detail/config_value_field_base.hpp
+108
-0
libcaf_core/caf/detail/config_value_field_impl.hpp
libcaf_core/caf/detail/config_value_field_impl.hpp
+45
-91
libcaf_core/caf/detail/parse.hpp
libcaf_core/caf/detail/parse.hpp
+29
-21
libcaf_core/test/actor_system_config.cpp
libcaf_core/test/actor_system_config.cpp
+220
-40
libcaf_core/test/make_config_value_field.cpp
libcaf_core/test/make_config_value_field.cpp
+65
-6
No files found.
libcaf_core/caf/actor_system_config.hpp
View file @
c525c605
...
@@ -415,14 +415,14 @@ private:
...
@@ -415,14 +415,14 @@ private:
const
settings
&
content
(
const
actor_system_config
&
cfg
);
const
settings
&
content
(
const
actor_system_config
&
cfg
);
/// Tries to retrieve the value associated to `name` from `cfg`.
/// Tries to retrieve the value associated to `name` from `cfg`.
/// @relates
config_value
/// @relates
actor_system_config
template
<
class
T
>
template
<
class
T
>
optional
<
T
>
get_if
(
const
actor_system_config
*
cfg
,
string_view
name
)
{
optional
<
T
>
get_if
(
const
actor_system_config
*
cfg
,
string_view
name
)
{
return
get_if
<
T
>
(
&
content
(
*
cfg
),
name
);
return
get_if
<
T
>
(
&
content
(
*
cfg
),
name
);
}
}
/// Retrieves the value associated to `name` from `cfg`.
/// Retrieves the value associated to `name` from `cfg`.
/// @relates
config_value
/// @relates
actor_system_config
template
<
class
T
>
template
<
class
T
>
T
get
(
const
actor_system_config
&
cfg
,
string_view
name
)
{
T
get
(
const
actor_system_config
&
cfg
,
string_view
name
)
{
return
get
<
T
>
(
content
(
cfg
),
name
);
return
get
<
T
>
(
content
(
cfg
),
name
);
...
@@ -430,7 +430,7 @@ T get(const actor_system_config& cfg, string_view name) {
...
@@ -430,7 +430,7 @@ T get(const actor_system_config& cfg, string_view name) {
/// Retrieves the value associated to `name` from `cfg` or returns
/// Retrieves the value associated to `name` from `cfg` or returns
/// `default_value`.
/// `default_value`.
/// @relates
config_value
/// @relates
actor_system_config
template
<
class
T
,
class
=
typename
std
::
enable_if
<
template
<
class
T
,
class
=
typename
std
::
enable_if
<
!
std
::
is_pointer
<
T
>
::
value
!
std
::
is_pointer
<
T
>
::
value
&&
!
std
::
is_convertible
<
T
,
string_view
>::
value
>::
type
>
&&
!
std
::
is_convertible
<
T
,
string_view
>::
value
>::
type
>
...
@@ -440,10 +440,17 @@ T get_or(const actor_system_config& cfg, string_view name, T default_value) {
...
@@ -440,10 +440,17 @@ T get_or(const actor_system_config& cfg, string_view name, T default_value) {
/// Retrieves the value associated to `name` from `cfg` or returns
/// Retrieves the value associated to `name` from `cfg` or returns
/// `default_value`.
/// `default_value`.
/// @relates
config_value
/// @relates
actor_system_config
inline
std
::
string
get_or
(
const
actor_system_config
&
cfg
,
string_view
name
,
inline
std
::
string
get_or
(
const
actor_system_config
&
cfg
,
string_view
name
,
string_view
default_value
)
{
string_view
default_value
)
{
return
get_or
(
content
(
cfg
),
name
,
default_value
);
return
get_or
(
content
(
cfg
),
name
,
default_value
);
}
}
/// Returns whether `xs` associates a value of type `T` to `name`.
/// @relates actor_system_config
template
<
class
T
>
bool
holds_alternative
(
const
actor_system_config
&
cfg
,
string_view
name
)
{
return
holds_alternative
<
T
>
(
content
(
cfg
),
name
);
}
}
// namespace caf
}
// namespace caf
libcaf_core/caf/config_value.hpp
View file @
c525c605
...
@@ -259,6 +259,7 @@ CAF_DEFAULT_CONFIG_VALUE_ACCESS(bool, "boolean");
...
@@ -259,6 +259,7 @@ CAF_DEFAULT_CONFIG_VALUE_ACCESS(bool, "boolean");
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
double
,
"real64"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
double
,
"real64"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
atom_value
,
"atom"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
atom_value
,
"atom"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
timespan
,
"timespan"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
timespan
,
"timespan"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
uri
,
"uri"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
config_value
::
list
,
"list"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
config_value
::
list
,
"list"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
config_value
::
dictionary
,
"dictionary"
);
CAF_DEFAULT_CONFIG_VALUE_ACCESS
(
config_value
::
dictionary
,
"dictionary"
);
...
...
libcaf_core/caf/config_value_field.hpp
View file @
c525c605
...
@@ -33,12 +33,6 @@ public:
...
@@ -33,12 +33,6 @@ public:
// -- observers --------------------------------------------------------------
// -- observers --------------------------------------------------------------
/// Checks whether `x` matches the type of this field.
virtual
bool
type_check
(
const
config_value
&
x
)
const
noexcept
=
0
;
/// Returns whether this field in `object` contains valid data.
virtual
bool
valid
(
const
Object
&
object
)
const
noexcept
=
0
;
/// Returns whether this field has a default value.
/// Returns whether this field has a default value.
virtual
bool
has_default
()
const
noexcept
=
0
;
virtual
bool
has_default
()
const
noexcept
=
0
;
...
@@ -48,11 +42,14 @@ public:
...
@@ -48,11 +42,14 @@ public:
/// Returns the value of this field in `object` as config value.
/// Returns the value of this field in `object` as config value.
virtual
config_value
get
(
const
Object
&
object
)
const
=
0
;
virtual
config_value
get
(
const
Object
&
object
)
const
=
0
;
/// Returns whether calling `set` with `x` would succeed.
virtual
bool
valid_input
(
const
config_value
&
x
)
const
=
0
;
// -- modifiers --------------------------------------------------------------
// -- modifiers --------------------------------------------------------------
///
Sets
this field in `object` to `x`.
///
Tries to set
this field in `object` to `x`.
/// @
pre `can_set(x)`
/// @
returns `true` on success, `false` otherwise.
virtual
void
set
(
Object
&
object
,
const
config_value
&
x
)
const
=
0
;
virtual
bool
set
(
Object
&
object
,
const
config_value
&
x
)
const
=
0
;
/// Restores the default value for this field in `object`.
/// Restores the default value for this field in `object`.
/// @pre `has_default()`
/// @pre `has_default()`
...
...
libcaf_core/caf/config_value_object_access.hpp
View file @
c525c605
...
@@ -48,17 +48,19 @@ struct config_value_object_access {
...
@@ -48,17 +48,19 @@ struct config_value_object_access {
if
(
!
dict
)
if
(
!
dict
)
return
false
;
return
false
;
for
(
auto
field
:
Trait
::
fields
())
{
for
(
auto
field
:
Trait
::
fields
())
{
auto
value
=
caf
::
get_if
(
dict
,
field
->
name
());
if
(
auto
value
=
caf
::
get_if
(
dict
,
field
->
name
()))
{
if
(
!
value
)
{
if
(
dst
)
{
if
(
!
field
->
set
(
*
dst
,
*
value
))
return
false
;
}
else
{
if
(
!
field
->
valid_input
(
*
value
))
return
false
;
}
}
else
{
if
(
!
field
->
has_default
())
if
(
!
field
->
has_default
())
return
false
;
return
false
;
if
(
dst
)
if
(
dst
)
field
->
set_default
(
*
dst
);
field
->
set_default
(
*
dst
);
}
else
if
(
field
->
type_check
(
*
value
))
{
if
(
dst
)
field
->
set
(
*
dst
,
*
value
);
}
else
{
return
false
;
}
}
}
}
return
true
;
return
true
;
...
@@ -156,10 +158,6 @@ struct config_value_object_access {
...
@@ -156,10 +158,6 @@ struct config_value_object_access {
ps
.
code
=
pec
::
unexpected_eof
;
ps
.
code
=
pec
::
unexpected_eof
;
return
;
return
;
}
}
if
(
!
fptr
->
valid
(
x
))
{
ps
.
code
=
pec
::
illegal_argument
;
return
;
}
result
[
fptr
->
name
()]
=
fptr
->
get
(
x
);
result
[
fptr
->
name
()]
=
fptr
->
get
(
x
);
}
while
(
ps
.
consume
(
','
));
}
while
(
ps
.
consume
(
','
));
if
(
!
ps
.
consume
(
'}'
))
{
if
(
!
ps
.
consume
(
'}'
))
{
...
...
libcaf_core/caf/detail/config_value_field_base.hpp
0 → 100644
View file @
c525c605
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2019 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/config_value_field.hpp"
#include "caf/detail/dispatch_parse_cli.hpp"
#include "caf/optional.hpp"
namespace
caf
{
namespace
detail
{
template
<
class
Object
,
class
Value
>
class
config_value_field_base
:
public
config_value_field
<
Object
>
{
public:
using
super
=
config_value_field
<
Object
>
;
using
object_type
=
typename
super
::
object_type
;
using
value_type
=
Value
;
using
predicate_type
=
bool
(
*
)(
const
value_type
&
);
config_value_field_base
(
string_view
name
,
optional
<
value_type
>
default_value
,
predicate_type
predicate
)
:
name_
(
name
),
default_value_
(
std
::
move
(
default_value
)),
predicate_
(
predicate
)
{
// nop
}
config_value_field_base
(
config_value_field_base
&&
)
=
default
;
bool
has_default
()
const
noexcept
override
{
return
static_cast
<
bool
>
(
default_value_
);
}
string_view
name
()
const
noexcept
override
{
return
name_
;
}
config_value
get
(
const
object_type
&
object
)
const
override
{
using
access
=
caf
::
select_config_value_access_t
<
value_type
>
;
return
config_value
{
access
::
convert
(
get_value
(
object
))};
}
bool
valid_input
(
const
config_value
&
x
)
const
override
{
if
(
!
predicate_
)
return
holds_alternative
<
value_type
>
(
x
);
if
(
auto
value
=
get_if
<
value_type
>
(
&
x
))
return
predicate_
(
*
value
);
return
false
;
}
bool
set
(
object_type
&
x
,
const
config_value
&
y
)
const
override
{
if
(
auto
value
=
get_if
<
value_type
>
(
&
y
))
{
if
(
predicate_
&&
!
predicate_
(
*
value
))
return
false
;
set_value
(
x
,
move_if_optional
(
value
));
return
true
;
}
return
false
;
}
void
set_default
(
object_type
&
x
)
const
override
{
set_value
(
x
,
*
default_value_
);
}
void
parse_cli
(
string_parser_state
&
ps
,
object_type
&
x
,
const
char
*
char_blacklist
)
const
override
{
value_type
tmp
;
dispatch_parse_cli
(
ps
,
tmp
,
char_blacklist
);
if
(
ps
.
code
<=
pec
::
trailing_character
)
{
if
(
predicate_
&&
!
predicate_
(
tmp
))
ps
.
code
=
pec
::
illegal_argument
;
else
set_value
(
x
,
std
::
move
(
tmp
));
}
}
virtual
const
value_type
&
get_value
(
const
object_type
&
object
)
const
=
0
;
virtual
void
set_value
(
object_type
&
object
,
value_type
value
)
const
=
0
;
protected:
string_view
name_
;
optional
<
value_type
>
default_value_
;
predicate_type
predicate_
;
};
}
// namespace detail
}
// namespace caf
libcaf_core/caf/detail/config_value_field_impl.hpp
View file @
c525c605
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
#include "caf/config_value.hpp"
#include "caf/config_value.hpp"
#include "caf/config_value_field.hpp"
#include "caf/config_value_field.hpp"
#include "caf/detail/config_value_field_base.hpp"
#include "caf/detail/dispatch_parse_cli.hpp"
#include "caf/detail/dispatch_parse_cli.hpp"
#include "caf/detail/parse.hpp"
#include "caf/detail/parse.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/detail/type_traits.hpp"
...
@@ -38,157 +39,110 @@ class config_value_field_impl;
...
@@ -38,157 +39,110 @@ class config_value_field_impl;
// A config value with direct access to a field via member object pointer.
// A config value with direct access to a field via member object pointer.
template
<
class
Value
,
class
Object
>
template
<
class
Value
,
class
Object
>
class
config_value_field_impl
<
Value
Object
::*>
class
config_value_field_impl
<
Value
Object
::*>
:
public
config_value_field
<
Object
>
{
:
public
config_value_field
_base
<
Object
,
Value
>
{
public:
public:
using
super
=
config_value_field_base
<
Object
,
Value
>
;
using
member_pointer
=
Value
Object
::*
;
using
member_pointer
=
Value
Object
::*
;
using
object_type
=
Object
;
using
object_type
=
Object
;
using
value_type
=
Value
;
using
value_type
=
Value
;
using
predicate_
pointer
=
bool
(
*
)(
const
value_type
&
);
using
predicate_
type
=
bool
(
*
)(
const
value_type
&
);
constexpr
config_value_field_impl
(
string_view
name
,
member_pointer
ptr
,
constexpr
config_value_field_impl
(
string_view
name
,
member_pointer
ptr
,
optional
<
value_type
>
default_value
=
none
,
optional
<
value_type
>
default_value
=
none
,
predicate_pointer
predicate
=
nullptr
)
predicate_type
predicate
=
nullptr
)
:
name_
(
name
),
:
super
(
name
,
std
::
move
(
default_value
),
predicate
),
ptr_
(
ptr
)
{
ptr_
(
ptr
),
default_value_
(
std
::
move
(
default_value
)),
predicate_
(
predicate
)
{
// nop
// nop
}
}
constexpr
config_value_field_impl
(
config_value_field_impl
&&
)
=
default
;
constexpr
config_value_field_impl
(
config_value_field_impl
&&
)
=
default
;
bool
type_check
(
const
config_value
&
x
)
const
noexcept
override
{
const
value_type
&
get_value
(
const
object_type
&
x
)
const
override
{
return
holds_alternative
<
value_type
>
(
x
);
return
x
.
*
ptr_
;
}
bool
valid
(
const
object_type
&
x
)
const
noexcept
override
{
return
predicate_
?
predicate_
(
x
.
*
ptr_
)
:
true
;
}
void
set
(
object_type
&
x
,
const
config_value
&
y
)
const
override
{
x
.
*
ptr_
=
caf
::
get
<
value_type
>
(
y
);
}
config_value
get
(
const
object_type
&
x
)
const
override
{
using
access
=
select_config_value_access_t
<
value_type
>
;
return
config_value
{
access
::
convert
(
x
.
*
ptr_
)};
}
}
void
parse_cli
(
string_parser_state
&
ps
,
object_type
&
x
,
void
set_value
(
object_type
&
x
,
value_type
y
)
const
override
{
const
char
*
char_blacklist
)
const
override
{
x
.
*
ptr_
=
std
::
move
(
y
);
detail
::
dispatch_parse_cli
(
ps
,
x
.
*
ptr_
,
char_blacklist
);
}
string_view
name
()
const
noexcept
override
{
return
name_
;
}
bool
has_default
()
const
noexcept
override
{
return
static_cast
<
bool
>
(
default_value_
);
}
void
set_default
(
object_type
&
x
)
const
override
{
x
.
*
ptr_
=
*
default_value_
;
}
}
private:
private:
string_view
name_
;
member_pointer
ptr_
;
member_pointer
ptr_
;
optional
<
value_type
>
default_value_
;
predicate_pointer
predicate_
;
};
};
template
<
class
Get
>
template
<
class
Get
>
struct
config_value_field_
base
{
struct
config_value_field_
trait
{
using
trait
=
get_callable_trait_t
<
Get
>
;
using
trait
=
get_callable_trait_t
<
Get
>
;
static_assert
(
trait
::
num_args
==
1
,
static_assert
(
trait
::
num_args
==
1
,
"Get must take exactly one argument (the object)"
);
"Get must take exactly one argument (the object)"
);
using
arg
_type
=
tl_head_t
<
typename
trait
::
arg_types
>
;
using
get_argument
_type
=
tl_head_t
<
typename
trait
::
arg_types
>
;
using
value_type
=
decay_t
<
typename
trait
::
resul
t_type
>
;
using
object_type
=
decay_t
<
get_argumen
t_type
>
;
using
type
=
config_value_field
<
decay_t
<
arg_type
>>
;
using
get_result_type
=
typename
trait
::
result_type
;
};
template
<
class
Get
>
using
value_type
=
decay_t
<
get_result_type
>
;
using
config_value_field_base_t
=
typename
config_value_field_base
<
Get
>::
type
;
}
;
// A config value with access to a field via getter and setter.
// A config value with access to a field via getter and setter.
template
<
class
Get
,
class
Set
>
template
<
class
Get
,
class
Set
>
class
config_value_field_impl
<
std
::
pair
<
Get
,
Set
>>
class
config_value_field_impl
<
std
::
pair
<
Get
,
Set
>>
:
public
config_value_field_base_t
<
Get
>
{
:
public
config_value_field_base
<
typename
config_value_field_trait
<
Get
>::
object_type
,
typename
config_value_field_trait
<
Get
>::
value_type
>
{
public:
public:
using
super
=
config_value_field_base_t
<
Get
>
;
using
trait
=
config_value_field_trait
<
Get
>
;
using
object_type
=
typename
trait
::
object_type
;
using
object_type
=
typename
super
::
objec
t_type
;
using
get_result_type
=
typename
trait
::
get_resul
t_type
;
using
get_trait
=
get_callable_trait_t
<
Get
>
;
using
value_type
=
typename
trait
::
value_type
;
using
value_type
=
decay_t
<
typename
get_trait
::
result_type
>
;
using
predicate_type
=
bool
(
*
)(
const
value_type
&
)
;
using
predicate_pointer
=
bool
(
*
)(
const
value_type
&
)
;
using
super
=
config_value_field_base
<
object_type
,
value_type
>
;
constexpr
config_value_field_impl
(
string_view
name
,
Get
getter
,
Set
setter
,
constexpr
config_value_field_impl
(
string_view
name
,
Get
getter
,
Set
setter
,
optional
<
value_type
>
default_value
=
none
,
optional
<
value_type
>
default_value
=
none
,
predicate_
pointer
predicate
=
nullptr
)
predicate_
type
predicate
=
nullptr
)
:
name_
(
nam
e
),
:
super
(
name
,
std
::
move
(
default_value
),
predicat
e
),
get_
(
std
::
move
(
getter
)),
get_
(
std
::
move
(
getter
)),
set_
(
std
::
move
(
setter
)),
set_
(
std
::
move
(
setter
))
{
default_value_
(
std
::
move
(
default_value
)),
predicate_
(
predicate
)
{
// nop
// nop
}
}
constexpr
config_value_field_impl
(
config_value_field_impl
&&
)
=
default
;
constexpr
config_value_field_impl
(
config_value_field_impl
&&
)
=
default
;
bool
type_check
(
const
config_value
&
x
)
const
noexcept
override
{
const
value_type
&
get_value
(
const
object_type
&
x
)
const
override
{
return
holds_alternative
<
value_type
>
(
x
);
bool_token
<
std
::
is_lvalue_reference
<
get_result_type
>::
value
>
token
;
}
return
get_value_impl
(
x
,
token
);
void
set
(
object_type
&
x
,
const
config_value
&
y
)
const
override
{
set_
(
x
,
caf
::
get
<
value_type
>
(
y
));
}
config_value
get
(
const
object_type
&
x
)
const
override
{
using
access
=
select_config_value_access_t
<
value_type
>
;
return
config_value
{
access
::
convert
(
get_
(
x
))};
}
bool
valid
(
const
object_type
&
x
)
const
noexcept
override
{
return
predicate_
?
predicate_
(
get_
(
x
))
:
true
;
}
}
void
parse_cli
(
string_parser_state
&
ps
,
object_type
&
x
,
void
set_value
(
object_type
&
x
,
value_type
y
)
const
override
{
const
char
*
char_blacklist
)
const
override
{
set_
(
x
,
std
::
move
(
y
));
value_type
tmp
;
detail
::
dispatch_parse_cli
(
ps
,
tmp
,
char_blacklist
);
if
(
ps
.
code
<=
pec
::
trailing_character
)
set_
(
x
,
std
::
move
(
tmp
));
}
}
string_view
name
()
const
noexcept
override
{
private:
return
name_
;
template
<
class
O
>
}
const
value_type
&
get_value_impl
(
const
O
&
x
,
std
::
true_type
)
const
{
return
get_
(
x
);
bool
has_default
()
const
noexcept
override
{
return
static_cast
<
bool
>
(
default_value_
);
}
}
void
set_default
(
object_type
&
x
)
const
override
{
template
<
class
O
>
set_
(
x
,
*
default_value_
);
const
value_type
&
get_value_impl
(
const
O
&
x
,
std
::
false_type
)
const
{
dummy_
=
get_
(
x
);
return
dummy_
;
}
}
private:
string_view
name_
;
Get
get_
;
Get
get_
;
Set
set_
;
Set
set_
;
optional
<
value_type
>
default_value_
;
mutable
value_type
dummy_
;
predicate_pointer
predicate_
;
};
};
}
// namespace detail
}
// namespace detail
...
...
libcaf_core/caf/detail/parse.hpp
View file @
c525c605
...
@@ -107,30 +107,11 @@ void parse_element(string_parser_state& ps, std::string& x,
...
@@ -107,30 +107,11 @@ void parse_element(string_parser_state& ps, std::string& x,
template
<
class
T
>
template
<
class
T
>
enable_if_t
<!
is_pair
<
T
>::
value
>
parse_element
(
string_parser_state
&
ps
,
T
&
x
,
enable_if_t
<!
is_pair
<
T
>::
value
>
parse_element
(
string_parser_state
&
ps
,
T
&
x
,
const
char
*
)
{
const
char
*
);
parse
(
ps
,
x
);
}
template
<
class
First
,
class
Second
,
size_t
N
>
template
<
class
First
,
class
Second
,
size_t
N
>
void
parse_element
(
string_parser_state
&
ps
,
std
::
pair
<
First
,
Second
>&
kvp
,
void
parse_element
(
string_parser_state
&
ps
,
std
::
pair
<
First
,
Second
>&
kvp
,
const
char
(
&
char_blacklist
)[
N
])
{
const
char
(
&
char_blacklist
)[
N
]);
static_assert
(
N
>
0
,
"empty array"
);
// TODO: consider to guard the blacklist computation with
// `if constexpr (is_same_v<First, string>)` when switching to C++17.
char
key_blacklist
[
N
+
1
];
if
(
N
>
1
)
memcpy
(
key_blacklist
,
char_blacklist
,
N
-
1
);
key_blacklist
[
N
-
1
]
=
'='
;
key_blacklist
[
N
]
=
'\0'
;
parse_element
(
ps
,
kvp
.
first
,
key_blacklist
);
if
(
ps
.
code
>
pec
::
trailing_character
)
return
;
if
(
!
ps
.
consume
(
'='
))
{
ps
.
code
=
pec
::
unexpected_character
;
return
;
}
parse_element
(
ps
,
kvp
.
second
,
char_blacklist
);
}
template
<
class
T
>
template
<
class
T
>
enable_if_tt
<
is_iterable
<
T
>>
parse
(
string_parser_state
&
ps
,
T
&
xs
)
{
enable_if_tt
<
is_iterable
<
T
>>
parse
(
string_parser_state
&
ps
,
T
&
xs
)
{
...
@@ -177,6 +158,33 @@ enable_if_tt<is_iterable<T>> parse(string_parser_state& ps, T& xs) {
...
@@ -177,6 +158,33 @@ enable_if_tt<is_iterable<T>> parse(string_parser_state& ps, T& xs) {
ps
.
code
=
ps
.
at_end
()
?
pec
::
success
:
pec
::
trailing_character
;
ps
.
code
=
ps
.
at_end
()
?
pec
::
success
:
pec
::
trailing_character
;
}
}
template
<
class
T
>
enable_if_t
<!
is_pair
<
T
>::
value
>
parse_element
(
string_parser_state
&
ps
,
T
&
x
,
const
char
*
)
{
parse
(
ps
,
x
);
}
template
<
class
First
,
class
Second
,
size_t
N
>
void
parse_element
(
string_parser_state
&
ps
,
std
::
pair
<
First
,
Second
>&
kvp
,
const
char
(
&
char_blacklist
)[
N
])
{
static_assert
(
N
>
0
,
"empty array"
);
// TODO: consider to guard the blacklist computation with
// `if constexpr (is_same_v<First, string>)` when switching to C++17.
char
key_blacklist
[
N
+
1
];
if
(
N
>
1
)
memcpy
(
key_blacklist
,
char_blacklist
,
N
-
1
);
key_blacklist
[
N
-
1
]
=
'='
;
key_blacklist
[
N
]
=
'\0'
;
parse_element
(
ps
,
kvp
.
first
,
key_blacklist
);
if
(
ps
.
code
>
pec
::
trailing_character
)
return
;
if
(
!
ps
.
consume
(
'='
))
{
ps
.
code
=
pec
::
unexpected_character
;
return
;
}
parse_element
(
ps
,
kvp
.
second
,
char_blacklist
);
}
// -- convenience functions ----------------------------------------------------
// -- convenience functions ----------------------------------------------------
template
<
class
T
>
template
<
class
T
>
...
...
libcaf_core/test/actor_system_config.cpp
View file @
c525c605
This diff is collapsed.
Click to expand it.
libcaf_core/test/make_config_value_field.cpp
View file @
c525c605
...
@@ -22,6 +22,7 @@
...
@@ -22,6 +22,7 @@
#include "caf/test/dsl.hpp"
#include "caf/test/dsl.hpp"
#include "caf/actor_system_config.hpp"
#include "caf/config_option_set.hpp"
#include "caf/config_option_set.hpp"
#include "caf/config_value_object_access.hpp"
#include "caf/config_value_object_access.hpp"
...
@@ -130,15 +131,12 @@ struct fixture {
...
@@ -130,15 +131,12 @@ struct fixture {
foobar
x
;
foobar
x
;
CAF_CHECK_EQUAL
(
foo_field
.
name
(),
"foo"
);
CAF_CHECK_EQUAL
(
foo_field
.
name
(),
"foo"
);
CAF_REQUIRE
(
foo_field
.
has_default
());
CAF_REQUIRE
(
foo_field
.
has_default
());
CAF_CHECK
(
foo_field
.
valid
(
x
));
CAF_CHECK_EQUAL
(
foo_field
.
get
(
x
),
config_value
(
0
));
CAF_CHECK_EQUAL
(
foo_field
.
get
(
x
),
config_value
(
0
));
foo_field
.
set_default
(
x
);
foo_field
.
set_default
(
x
);
CAF_CHECK_EQUAL
(
foo_field
.
get
(
x
),
config_value
(
42
));
CAF_CHECK_EQUAL
(
foo_field
.
get
(
x
),
config_value
(
42
));
CAF_CHECK
(
!
foo_field
.
type_check
(
config_value
(
1.
)));
CAF_CHECK
(
!
foo_field
.
valid_input
(
config_value
(
1.
)));
CAF_CHECK
(
foo_field
.
type_check
(
config_value
(
-
1
)));
CAF_CHECK
(
!
foo_field
.
valid_input
(
config_value
(
-
1
)));
foo_field
.
set
(
x
,
config_value
(
-
1
));
CAF_CHECK
(
!
foo_field
.
set
(
x
,
config_value
(
-
1
)));
CAF_CHECK_EQUAL
(
foo_field
.
get
(
x
),
config_value
(
-
1
));
CAF_CHECK
(
!
foo_field
.
valid
(
x
));
string_view
input
=
"123"
;
string_view
input
=
"123"
;
string_parser_state
ps
{
input
.
begin
(),
input
.
end
()};
string_parser_state
ps
{
input
.
begin
(),
input
.
end
()};
foo_field
.
parse_cli
(
ps
,
x
);
foo_field
.
parse_cli
(
ps
,
x
);
...
@@ -257,4 +255,65 @@ CAF_TEST(object access from CLI arguments - foobar_foobar) {
...
@@ -257,4 +255,65 @@ CAF_TEST(object access from CLI arguments - foobar_foobar) {
fbfb
({
123
,
"hello"
},
{
1
,
"world!"
}));
fbfb
({
123
,
"hello"
},
{
1
,
"world!"
}));
}
}
namespace
{
constexpr
const
char
*
config_text
=
R"__(
arg1 = {
foo = 42
bar = "Don't panic!"
}
arg2 = {
x = {
foo = 1
bar = "hello"
}
y = {
foo = 2
bar = "world"
}
}
)__"
;
struct
test_config
:
actor_system_config
{
test_config
()
{
opt_group
{
custom_options_
,
"global"
}
.
add
(
fb
,
"arg1,1"
,
"some foobar"
)
.
add
(
fbfb
,
"arg2,2"
,
"somme foobar-foobar"
);
}
foobar
fb
;
foobar_foobar
fbfb
;
};
}
// namespace
CAF_TEST
(
object
access
from
actor
system
config
-
file
input
)
{
test_config
cfg
;
std
::
istringstream
in
{
config_text
};
if
(
auto
err
=
cfg
.
parse
(
0
,
nullptr
,
in
))
CAF_FAIL
(
"cfg.parse failed: "
<<
cfg
.
render
(
err
));
CAF_CHECK_EQUAL
(
cfg
.
fb
.
foo
,
42
);
CAF_CHECK_EQUAL
(
cfg
.
fb
.
bar
,
"Don't panic!"
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
x
.
foo
,
1
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
y
.
foo
,
2
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
x
.
bar
,
"hello"
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
y
.
bar
,
"world"
);
}
CAF_TEST
(
object
access
from
actor
system
config
-
file
input
and
arguments
)
{
std
::
vector
<
std
::
string
>
args
{
"-2"
,
"{y = {bar = CAF, foo = 20}, x = {foo = 10, bar = hello}}"
,
};
test_config
cfg
;
std
::
istringstream
in
{
config_text
};
if
(
auto
err
=
cfg
.
parse
(
std
::
move
(
args
),
in
))
CAF_FAIL
(
"cfg.parse failed: "
<<
cfg
.
render
(
err
));
CAF_CHECK_EQUAL
(
cfg
.
fb
.
foo
,
42
);
CAF_CHECK_EQUAL
(
cfg
.
fb
.
bar
,
"Don't panic!"
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
x
.
foo
,
10
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
y
.
foo
,
20
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
x
.
bar
,
"hello"
);
CAF_CHECK_EQUAL
(
cfg
.
fbfb
.
y
.
bar
,
"CAF"
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
CAF_TEST_FIXTURE_SCOPE_END
()
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