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
c99f508a
Commit
c99f508a
authored
Sep 29, 2016
by
Dominik Charousset
Committed by
GitHub
Sep 29, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #511 from actor-framework/topic/missing_types_in_config
Topic/missing types in config
parents
ff2ed53e
44c0ca24
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
350 additions
and
83 deletions
+350
-83
libcaf_core/caf/config.hpp
libcaf_core/caf/config.hpp
+1
-0
libcaf_core/caf/config_option.hpp
libcaf_core/caf/config_option.hpp
+73
-32
libcaf_core/caf/detail/parse_ini.hpp
libcaf_core/caf/detail/parse_ini.hpp
+5
-2
libcaf_core/src/actor_system_config.cpp
libcaf_core/src/actor_system_config.cpp
+6
-4
libcaf_core/src/config_option.cpp
libcaf_core/src/config_option.cpp
+23
-40
libcaf_core/src/parse_ini.cpp
libcaf_core/src/parse_ini.cpp
+2
-2
libcaf_core/test/config_option.cpp
libcaf_core/test/config_option.cpp
+235
-0
libcaf_core/test/parse_ini.cpp
libcaf_core/test/parse_ini.cpp
+5
-3
No files found.
libcaf_core/caf/config.hpp
View file @
c99f508a
...
@@ -89,6 +89,7 @@
...
@@ -89,6 +89,7 @@
_Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \
_Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \
_Pragma("clang diagnostic ignored \"-Wnested-anon-types\"") \
_Pragma("clang diagnostic ignored \"-Wnested-anon-types\"") \
_Pragma("clang diagnostic ignored \"-Wreserved-id-macro\"") \
_Pragma("clang diagnostic ignored \"-Wreserved-id-macro\"") \
_Pragma("clang diagnostic ignored \"-Wconstant-conversion\"") \
_Pragma("clang diagnostic ignored \"-Wimplicit-fallthrough\"") \
_Pragma("clang diagnostic ignored \"-Wimplicit-fallthrough\"") \
_Pragma("clang diagnostic ignored \"-Wused-but-marked-unused\"") \
_Pragma("clang diagnostic ignored \"-Wused-but-marked-unused\"") \
_Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"")
_Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"")
...
...
libcaf_core/caf/config_option.hpp
View file @
c99f508a
...
@@ -28,6 +28,7 @@
...
@@ -28,6 +28,7 @@
#include <functional>
#include <functional>
#include "caf/atom.hpp"
#include "caf/atom.hpp"
#include "caf/error.hpp"
#include "caf/message.hpp"
#include "caf/message.hpp"
#include "caf/variant.hpp"
#include "caf/variant.hpp"
#include "caf/config_value.hpp"
#include "caf/config_value.hpp"
...
@@ -38,10 +39,18 @@
...
@@ -38,10 +39,18 @@
namespace
caf
{
namespace
caf
{
extern
const
char
*
type_name_visitor_tbl
[];
/// Helper class to generate config readers for different input types.
/// Helper class to generate config readers for different input types.
class
config_option
{
class
config_option
{
public:
public:
using
config_reader_sink
=
std
::
function
<
void
(
size_t
,
config_value
&
)
>
;
using
config_reader_sink
=
std
::
function
<
void
(
size_t
,
config_value
&
,
optional
<
std
::
ostream
&>
)
>
;
using
legal_types
=
detail
::
type_list
<
bool
,
float
,
double
,
std
::
string
,
atom_value
,
int8_t
,
uint8_t
,
int16_t
,
uint16_t
,
int32_t
,
uint32_t
,
int64_t
,
uint64_t
>
;
config_option
(
const
char
*
category
,
const
char
*
name
,
const
char
*
explanation
);
config_option
(
const
char
*
category
,
const
char
*
name
,
const
char
*
explanation
);
...
@@ -76,42 +85,64 @@ public:
...
@@ -76,42 +85,64 @@ public:
virtual
message
::
cli_arg
to_cli_arg
(
bool
use_caf_prefix
=
false
)
=
0
;
virtual
message
::
cli_arg
to_cli_arg
(
bool
use_caf_prefix
=
false
)
=
0
;
/// Returns a human-readable type name for the visited type.
/// Returns a human-readable type name for the visited type.
struct
type_name_visitor
:
static_visitor
<
const
char
*>
{
class
type_name_visitor
:
public
static_visitor
<
const
char
*>
{
const
char
*
operator
()(
const
std
::
string
&
)
const
;
public:
const
char
*
operator
()(
double
)
const
;
template
<
class
T
>
const
char
*
operator
()(
int64_t
)
const
;
const
char
*
operator
()(
const
T
&
)
const
{
const
char
*
operator
()(
size_t
)
const
;
static
constexpr
bool
is_int
=
std
::
is_integral
<
T
>::
value
const
char
*
operator
()(
uint16_t
)
const
;
&&
!
std
::
is_same
<
bool
,
T
>::
value
;
const
char
*
operator
()(
bool
)
const
;
static
constexpr
std
::
integral_constant
<
bool
,
is_int
>
tk
{};
const
char
*
operator
()(
atom_value
)
const
;
static
constexpr
int
index
=
idx
<
T
>
(
tk
);
};
static_assert
(
index
>=
0
,
"illegal type in name visitor"
);
return
type_name_visitor_tbl
[
static_cast
<
size_t
>
(
index
)];
}
protected:
private:
// 32-bit platforms
template
<
class
T
>
template
<
class
T
>
static
typename
std
::
enable_if
<
sizeof
(
T
)
==
sizeof
(
uint32_t
),
bool
>::
type
static
constexpr
int
idx
(
std
::
false_type
/* is_integer */
)
{
unsigned_assign_in_range
(
T
&
,
int64_t
&
x
)
{
return
detail
::
tl_index_of
<
legal_types
,
T
>::
value
;
return
x
<=
std
::
numeric_limits
<
T
>::
max
();
}
}
// 64-bit platforms
template
<
class
T
>
template
<
class
T
>
static
typename
std
::
enable_if
<
sizeof
(
T
)
==
sizeof
(
uint64_t
),
bool
>::
type
static
constexpr
int
idx
(
std
::
true_type
/* is_integer */
)
{
unsigned_assign_in_range
(
T
&
,
int64_t
&
)
{
using
squashed
=
detail
::
squashed_int_t
<
T
>
;
return
tr
ue
;
return
detail
::
tl_index_of
<
legal_types
,
squashed
>::
val
ue
;
}
}
};
protected:
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
static
bool
assign_config_value
(
T
&
x
,
U
&
y
)
{
static
bool
assign_config_value
(
T
&
x
,
U
&
y
)
{
x
=
std
::
move
(
y
);
x
=
std
::
move
(
y
);
return
true
;
return
true
;
}
}
static
bool
assign_config_value
(
size_t
&
x
,
int64_t
&
y
);
template
<
class
T
>
static
bool
assign_config_value
(
T
&
x
,
int64_t
&
y
)
{
if
(
y
<
static_cast
<
int64_t
>
(
std
::
numeric_limits
<
T
>::
lowest
())
||
y
>
static_cast
<
int64_t
>
(
std
::
numeric_limits
<
T
>::
max
()))
return
false
;
x
=
static_cast
<
T
>
(
y
);
return
true
;
}
static
bool
assign_config_value
(
uint16_t
&
x
,
int64_t
&
y
);
static
bool
assign_config_value
(
uint64_t
&
x
,
int64_t
&
y
)
{
if
(
y
<
0
)
return
false
;
x
=
static_cast
<
uint64_t
>
(
y
);
return
true
;
}
void
report_type_error
(
size_t
line
,
config_value
&
x
,
const
char
*
expected
);
static
bool
assign_config_value
(
float
&
x
,
double
&
y
)
{
if
(
y
<
static_cast
<
double
>
(
std
::
numeric_limits
<
float
>::
lowest
())
||
y
>
static_cast
<
double
>
(
std
::
numeric_limits
<
float
>::
max
()))
return
false
;
x
=
static_cast
<
float
>
(
y
);
return
true
;
}
void
report_type_error
(
size_t
line
,
config_value
&
x
,
const
char
*
expected
,
optional
<
std
::
ostream
&>
errors
);
private:
private:
const
char
*
category_
;
const
char
*
category_
;
...
@@ -151,18 +182,23 @@ public:
...
@@ -151,18 +182,23 @@ public:
}
}
config_reader_sink
to_sink
()
override
{
config_reader_sink
to_sink
()
override
{
return
[
=
](
size_t
ln
,
config_value
&
x
)
{
return
[
=
](
size_t
ln
,
config_value
&
x
,
optional
<
std
::
ostream
&>
errors
)
{
// the INI parser accepts all integers as int64_t
// the INI parser accepts all integers as int64_t
// and all floating point numbers as doubles
using
cfg_type
=
using
cfg_type
=
typename
std
::
conditional
<
typename
std
::
conditional
<
std
::
is_integral
<
T
>::
value
&&
!
std
::
is_same
<
bool
,
T
>::
value
,
std
::
is_integral
<
T
>::
value
&&
!
std
::
is_same
<
bool
,
T
>::
value
,
int64_t
,
int64_t
,
typename
std
::
conditional
<
std
::
is_floating_point
<
T
>::
value
,
double
,
T
T
>::
type
>::
type
;
>::
type
;
if
(
get
<
cfg_type
>
(
&
x
)
&&
assign_config_value
(
ref_
,
get
<
cfg_type
>
(
x
)))
if
(
get
<
cfg_type
>
(
&
x
)
&&
assign_config_value
(
ref_
,
get
<
cfg_type
>
(
x
)))
return
;
return
;
type_name_visitor
tnv
;
type_name_visitor
tnv
;
report_type_error
(
ln
,
x
,
tnv
(
ref_
));
report_type_error
(
ln
,
x
,
tnv
(
ref_
)
,
errors
);
};
};
}
}
...
@@ -202,14 +238,19 @@ public:
...
@@ -202,14 +238,19 @@ public:
}
}
config_reader_sink
to_sink
()
override
{
config_reader_sink
to_sink
()
override
{
return
[
=
](
size_t
ln
,
config_value
&
x
)
{
return
[
=
](
size_t
ln
,
config_value
&
x
,
optional
<
std
::
ostream
&>
errors
)
{
// the INI parser accepts all integers as int64_t
// the INI parser accepts all integers as int64_t
// and all floating point numbers as doubles
using
cfg_type
=
using
cfg_type
=
typename
std
::
conditional
<
typename
std
::
conditional
<
std
::
is_integral
<
value_type
>::
value
std
::
is_integral
<
value_type
>::
value
&&
&&
!
std
::
is_same
<
bool
,
value_type
>::
value
,
!
std
::
is_same
<
bool
,
value_type
>::
value
,
int64_t
,
int64_t
,
typename
std
::
conditional
<
std
::
is_floating_point
<
value_type
>::
value
,
double
,
value_type
value_type
>::
type
>::
type
;
>::
type
;
value_type
tmp
;
value_type
tmp
;
if
(
get
<
cfg_type
>
(
&
x
)
&&
assign_config_value
(
tmp
,
get
<
cfg_type
>
(
x
)))
{
if
(
get
<
cfg_type
>
(
&
x
)
&&
assign_config_value
(
tmp
,
get
<
cfg_type
>
(
x
)))
{
...
@@ -217,7 +258,7 @@ public:
...
@@ -217,7 +258,7 @@ public:
return
;
return
;
}
}
type_name_visitor
tnv
;
type_name_visitor
tnv
;
report_type_error
(
ln
,
x
,
tnv
(
tmp
));
report_type_error
(
ln
,
x
,
tnv
(
tmp
)
,
errors
);
};
};
}
}
...
...
libcaf_core/caf/detail/parse_ini.hpp
View file @
c99f508a
...
@@ -33,8 +33,11 @@ namespace caf {
...
@@ -33,8 +33,11 @@ namespace caf {
namespace
detail
{
namespace
detail
{
struct
parse_ini_t
{
struct
parse_ini_t
{
/// Denotes an optional error output stream
using
opt_err
=
optional
<
std
::
ostream
&>
;
/// Denotes a callback for consuming configuration values.
/// Denotes a callback for consuming configuration values.
using
config_consumer
=
std
::
function
<
void
(
size_t
,
std
::
string
,
config_value
&
)
>
;
using
config_consumer
=
std
::
function
<
void
(
size_t
,
std
::
string
,
config_value
&
,
opt_err
)
>
;
/// Parse the given input stream as INI formatted data and
/// Parse the given input stream as INI formatted data and
/// calls the consumer with every key-value pair.
/// calls the consumer with every key-value pair.
...
@@ -43,7 +46,7 @@ struct parse_ini_t {
...
@@ -43,7 +46,7 @@ struct parse_ini_t {
/// @param consumer Callback consuming generated key-value pairs.
/// @param consumer Callback consuming generated key-value pairs.
void
operator
()(
std
::
istream
&
raw_data
,
void
operator
()(
std
::
istream
&
raw_data
,
config_consumer
consumer
,
config_consumer
consumer
,
opt
ional
<
std
::
ostream
&>
errors
=
none
)
const
;
opt
_err
errors
=
none
)
const
;
};
};
...
...
libcaf_core/src/actor_system_config.cpp
View file @
c99f508a
...
@@ -35,7 +35,8 @@ using option_vector = actor_system_config::option_vector;
...
@@ -35,7 +35,8 @@ using option_vector = actor_system_config::option_vector;
class
actor_system_config_reader
{
class
actor_system_config_reader
{
public:
public:
using
sink
=
std
::
function
<
void
(
size_t
,
config_value
&
)
>
;
using
sink
=
std
::
function
<
void
(
size_t
,
config_value
&
,
optional
<
std
::
ostream
&>
)
>
;
actor_system_config_reader
(
option_vector
&
xs
,
option_vector
&
ys
)
{
actor_system_config_reader
(
option_vector
&
xs
,
option_vector
&
ys
)
{
add_opts
(
xs
);
add_opts
(
xs
);
...
@@ -50,7 +51,7 @@ public:
...
@@ -50,7 +51,7 @@ public:
void
operator
()(
size_t
ln
,
std
::
string
name
,
config_value
&
cv
)
{
void
operator
()(
size_t
ln
,
std
::
string
name
,
config_value
&
cv
)
{
auto
i
=
sinks_
.
find
(
name
);
auto
i
=
sinks_
.
find
(
name
);
if
(
i
!=
sinks_
.
end
())
if
(
i
!=
sinks_
.
end
())
(
i
->
second
)(
ln
,
cv
);
(
i
->
second
)(
ln
,
cv
,
none
);
else
else
std
::
cerr
<<
"error in line "
<<
ln
std
::
cerr
<<
"error in line "
<<
ln
<<
": unrecognized parameter name
\"
"
<<
name
<<
"
\"
"
;
<<
": unrecognized parameter name
\"
"
<<
name
<<
"
\"
"
;
...
@@ -213,7 +214,8 @@ actor_system_config& actor_system_config::parse(message& args,
...
@@ -213,7 +214,8 @@ actor_system_config& actor_system_config::parse(message& args,
// (2) content of the INI file overrides hard-coded defaults
// (2) content of the INI file overrides hard-coded defaults
if
(
ini
.
good
())
{
if
(
ini
.
good
())
{
actor_system_config_reader
consumer
{
options_
,
custom_options_
};
actor_system_config_reader
consumer
{
options_
,
custom_options_
};
auto
f
=
[
&
](
size_t
ln
,
std
::
string
str
,
config_value
&
x
)
{
auto
f
=
[
&
](
size_t
ln
,
std
::
string
str
,
config_value
&
x
,
optional
<
std
::
ostream
&>
)
{
consumer
(
ln
,
std
::
move
(
str
),
x
);
consumer
(
ln
,
std
::
move
(
str
),
x
);
};
};
detail
::
parse_ini
(
ini
,
f
,
std
::
cerr
);
detail
::
parse_ini
(
ini
,
f
,
std
::
cerr
);
...
@@ -310,7 +312,7 @@ actor_system_config& actor_system_config::set(const char* cn, config_value cv) {
...
@@ -310,7 +312,7 @@ actor_system_config& actor_system_config::set(const char* cn, config_value cv) {
full_name
+=
x
->
name
();
full_name
+=
x
->
name
();
if
(
full_name
==
cn
)
{
if
(
full_name
==
cn
)
{
auto
f
=
x
->
to_sink
();
auto
f
=
x
->
to_sink
();
f
(
0
,
cv
);
f
(
0
,
cv
,
none
);
}
}
}
}
return
*
this
;
return
*
this
;
...
...
libcaf_core/src/config_option.cpp
View file @
c99f508a
...
@@ -23,6 +23,22 @@
...
@@ -23,6 +23,22 @@
namespace
caf
{
namespace
caf
{
const
char
*
type_name_visitor_tbl
[]
{
"a boolean"
,
"a float"
,
"a double"
,
"a string"
,
"an atom_value"
,
"an 8-bit integer"
,
"an 8-bit unsigned integer"
,
"a 16-bit integer"
,
"a 16-bit unsigned integer"
,
"a 32-bit integer"
,
"a 32-bit unsigned integer"
,
"a 64-bit integer"
,
"a 64-bit unsigned integer"
};
config_option
::
config_option
(
const
char
*
cat
,
const
char
*
nm
,
const
char
*
expl
)
config_option
::
config_option
(
const
char
*
cat
,
const
char
*
nm
,
const
char
*
expl
)
:
category_
(
cat
),
:
category_
(
cat
),
name_
(
nm
),
name_
(
nm
),
...
@@ -55,48 +71,15 @@ std::string config_option::full_name() const {
...
@@ -55,48 +71,15 @@ std::string config_option::full_name() const {
return
res
;
return
res
;
}
}
const
char
*
config_option
::
type_name_visitor
::
operator
()(
const
std
::
string
&
)
const
{
return
"a string"
;
}
const
char
*
config_option
::
type_name_visitor
::
operator
()(
double
)
const
{
return
"a double"
;
}
const
char
*
config_option
::
type_name_visitor
::
operator
()(
int64_t
)
const
{
return
"an integer"
;
}
const
char
*
config_option
::
type_name_visitor
::
operator
()(
size_t
)
const
{
return
"an unsigned integer"
;
}
const
char
*
config_option
::
type_name_visitor
::
operator
()(
uint16_t
)
const
{
return
"an unsigned short integer"
;
}
const
char
*
config_option
::
type_name_visitor
::
operator
()(
bool
)
const
{
return
"a boolean"
;
}
const
char
*
config_option
::
type_name_visitor
::
operator
()(
atom_value
)
const
{
return
"an atom"
;
}
bool
config_option
::
assign_config_value
(
size_t
&
x
,
int64_t
&
y
)
{
if
(
y
<
0
||
!
unsigned_assign_in_range
(
x
,
y
))
return
false
;
x
=
static_cast
<
size_t
>
(
y
);
return
true
;
}
bool
config_option
::
assign_config_value
(
uint16_t
&
x
,
int64_t
&
y
)
{
if
(
y
<
0
||
y
>
std
::
numeric_limits
<
uint16_t
>::
max
())
return
false
;
x
=
static_cast
<
uint16_t
>
(
y
);
return
true
;
}
void
config_option
::
report_type_error
(
size_t
ln
,
config_value
&
x
,
void
config_option
::
report_type_error
(
size_t
ln
,
config_value
&
x
,
const
char
*
expected
)
{
const
char
*
expected
,
optional
<
std
::
ostream
&>
out
)
{
if
(
!
out
)
return
;
type_name_visitor
tnv
;
type_name_visitor
tnv
;
std
::
cerr
<<
"error in line "
<<
ln
<<
": expected "
*
out
<<
"error in line "
<<
ln
<<
": expected "
<<
expected
<<
" found "
<<
expected
<<
" found "
<<
apply_visitor
(
tnv
,
x
)
<<
std
::
endl
;
<<
apply_visitor
(
tnv
,
x
)
<<
'\n'
;
}
}
}
// namespace caf
}
// namespace caf
libcaf_core/src/parse_ini.cpp
View file @
c99f508a
...
@@ -28,10 +28,10 @@ namespace caf {
...
@@ -28,10 +28,10 @@ namespace caf {
namespace
detail
{
namespace
detail
{
void
parse_ini_t
::
operator
()(
std
::
istream
&
input
,
config_consumer
consumer_fun
,
void
parse_ini_t
::
operator
()(
std
::
istream
&
input
,
config_consumer
consumer_fun
,
opt
ional
<
std
::
ostream
&>
errors
)
const
{
opt
_err
errors
)
const
{
// wraps a temporary into an (lvalue) config_value and calls `consumer_fun`
// wraps a temporary into an (lvalue) config_value and calls `consumer_fun`
auto
consumer
=
[
&
](
size_t
ln
,
std
::
string
name
,
config_value
x
)
{
auto
consumer
=
[
&
](
size_t
ln
,
std
::
string
name
,
config_value
x
)
{
consumer_fun
(
ln
,
std
::
move
(
name
),
x
);
consumer_fun
(
ln
,
std
::
move
(
name
),
x
,
errors
);
};
};
std
::
string
group
;
std
::
string
group
;
std
::
string
line
;
std
::
string
line
;
...
...
libcaf_core/test/config_option.cpp
0 → 100644
View file @
c99f508a
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2016 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* 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/config.hpp"
#define CAF_SUITE config_option
#include "caf/test/unit_test.hpp"
#include "caf/config_option.hpp"
#include "caf/actor_system_config.hpp"
// turn off several flags for overflows / sign conversion
#ifdef CAF_CLANG
//#elif defined(CAF_CLANG)
#pragma clang diagnostic ignored "-Wsign-conversion"
#pragma clang diagnostic ignored "-Wfloat-equal"
#pragma clang diagnostic ignored "-Wconstant-conversion"
#endif
using
namespace
caf
;
namespace
{
constexpr
const
char
*
category
=
"category"
;
constexpr
const
char
*
name
=
"name"
;
constexpr
const
char
*
explanation
=
"explanation"
;
constexpr
size_t
line
=
0
;
template
<
class
T
>
constexpr
T
zero
()
{
return
0
;
}
template
<
class
T
,
class
U
,
class
V
>
constexpr
T
overflow
()
{
// +2 is necessary as after an overflow unsigned integral numbers
// must differ from zero() in the tests
return
static_cast
<
V
>
(
std
::
numeric_limits
<
U
>::
max
())
+
2
;
}
template
<
class
T
,
class
U
>
std
::
tuple
<
T
,
std
::
string
>
run_config_option
(
const
T
&
init_value
,
const
U
&
test_value
)
{
std
::
stringstream
ostr
;
T
output_value
=
init_value
;
auto
cv
=
config_value
(
test_value
);
auto
co
=
make_config_option
(
output_value
,
category
,
name
,
explanation
);
auto
f
=
co
->
to_sink
();
f
(
line
,
cv
,
static_cast
<
std
::
ostream
&>
(
ostr
));
return
std
::
make_tuple
(
output_value
,
ostr
.
str
());
}
// only works with an integral types and double
template
<
class
T
,
class
U
>
void
check_num_general_usage
()
{
// check positive numbers
std
::
string
error_str
;
U
test_value
=
5
;
T
result
;
std
::
tie
(
result
,
error_str
)
=
run_config_option
(
zero
<
T
>
(),
test_value
);
CAF_CHECK_EQUAL
(
result
,
static_cast
<
T
>
(
test_value
));
CAF_CHECK
(
error_str
.
empty
());
// check negative numbers
test_value
=
-
5
;
std
::
tie
(
result
,
error_str
)
=
run_config_option
(
zero
<
T
>
(),
test_value
);
if
(
std
::
numeric_limits
<
T
>::
is_signed
)
{
CAF_CHECK_EQUAL
(
result
,
static_cast
<
T
>
(
test_value
));
CAF_CHECK
(
error_str
.
empty
());
}
else
{
CAF_CHECK_EQUAL
(
result
,
zero
<
T
>
());
CAF_CHECK
(
!
error_str
.
empty
());
}
// check vector<T>
test_value
=
5
;
std
::
vector
<
T
>
vec_result
;
std
::
tie
(
vec_result
,
error_str
)
=
run_config_option
(
std
::
vector
<
T
>
{},
test_value
);
CAF_CHECK
(
!
vec_result
.
empty
());
if
(
!
vec_result
.
empty
())
{
CAF_CHECK_EQUAL
(
*
vec_result
.
begin
(),
static_cast
<
T
>
(
test_value
));
}
}
// only works with an integral types (no doubles)
template
<
class
T
,
class
U
>
void
check_num_boundary_usage
()
{
std
::
string
error_str
;
T
result
;
U
boundary_check
=
overflow
<
U
,
T
,
U
>
();
std
::
tie
(
result
,
error_str
)
=
run_config_option
(
zero
<
T
>
(),
boundary_check
);
T
tmp
=
overflow
<
T
,
T
,
U
>
();
CAF_CHECK_NOT_EQUAL
(
result
,
tmp
);
CAF_CHECK_EQUAL
(
result
,
zero
<
T
>
());
CAF_CHECK
(
!
error_str
.
empty
());
}
// only works with an integral types (no doubles)
template
<
class
T
,
class
U
>
void
check_num_general_and_boundary_usage
()
{
check_num_general_usage
<
T
,
U
>
();
check_num_boundary_usage
<
T
,
U
>
();
}
// intended for atoms, strings, and bools
template
<
class
T
>
void
check_non_num_general_usage
(
const
T
&
init_value
,
const
T
&
test_value
)
{
// general check
std
::
string
error_str
;
T
result
;
std
::
tie
(
result
,
error_str
)
=
run_config_option
(
init_value
,
test_value
);
CAF_CHECK_EQUAL
(
result
,
test_value
);
// vector<T> check
std
::
vector
<
T
>
vec_result
;
std
::
tie
(
vec_result
,
error_str
)
=
run_config_option
(
std
::
vector
<
T
>
{},
test_value
);
CAF_CHECK
(
!
vec_result
.
empty
());
if
(
!
vec_result
.
empty
())
{
CAF_CHECK_EQUAL
(
*
vec_result
.
begin
(),
test_value
);
}
}
void
check_non_num_general_usage
(
bool
init_value
,
bool
test_value
)
{
// general check
std
::
string
error_str
;
bool
result
;
std
::
tie
(
result
,
error_str
)
=
run_config_option
(
init_value
,
test_value
);
CAF_CHECK_EQUAL
(
result
,
test_value
);
// vector<T> check
// emplace_back() in class cli_arg do not support <bool> until C++14
}
}
CAF_TEST
(
type_bool
)
{
check_non_num_general_usage
(
false
,
true
);
}
CAF_TEST
(
type_int8_t
)
{
check_num_general_and_boundary_usage
<
int8_t
,
int64_t
>
();
}
CAF_TEST
(
type_uint8_t
)
{
check_num_general_and_boundary_usage
<
uint8_t
,
int64_t
>
();
}
CAF_TEST
(
type_int16_t
)
{
check_num_general_and_boundary_usage
<
int16_t
,
int64_t
>
();
}
CAF_TEST
(
type_uint16_t
)
{
check_num_general_and_boundary_usage
<
uint16_t
,
int64_t
>
();
}
CAF_TEST
(
type_int32_t
)
{
check_num_general_and_boundary_usage
<
int32_t
,
int64_t
>
();
}
CAF_TEST
(
type_uint32_t
)
{
check_num_general_and_boundary_usage
<
uint32_t
,
int64_t
>
();
}
CAF_TEST
(
type_uint64_t
)
{
check_num_general_usage
<
uint64_t
,
int64_t
>
();
}
CAF_TEST
(
type_int64_t
)
{
check_num_general_usage
<
int64_t
,
int64_t
>
();
}
CAF_TEST
(
type_float
)
{
check_num_general_usage
<
float
,
double
>
();
// check boundaries
std
::
string
error_str
;
float
result
;
float
init_value
=
0
;
// *2 is required as +2 does not change the variable at this size anymore
double
boundary_check
=
static_cast
<
double
>
(
std
::
numeric_limits
<
float
>::
max
())
*
2
;
std
::
tie
(
result
,
error_str
)
=
run_config_option
(
init_value
,
boundary_check
);
float
float_inf
=
std
::
numeric_limits
<
float
>::
infinity
();
// Unit test does not compare inf values correct until now
bool
tmp
=
float_inf
==
result
;
CAF_CHECK_NOT_EQUAL
(
tmp
,
true
);
CAF_CHECK_EQUAL
(
result
,
init_value
);
CAF_CHECK_EQUAL
(
error_str
.
empty
(),
false
);
}
CAF_TEST
(
type_double
)
{
check_num_general_usage
<
double
,
double
>
();
}
CAF_TEST
(
type_string
)
{
check_non_num_general_usage
<
std
::
string
>
(
""
,
"test string"
);
}
CAF_TEST
(
type_atom
)
{
// TODO: in class cli_arg std::istringstream do not support atom_value
// check_non_num_general_usage<atom_value>(atom(""), atom("test atom"));
}
template
<
class
T
>
std
::
string
v
(
const
T
&
x
)
{
config_option
::
type_name_visitor
v
;
return
v
(
x
);
}
CAF_TEST
(
type_names
)
{
CAF_CHECK_EQUAL
(
v
(
true
),
"a boolean"
);
CAF_CHECK_EQUAL
(
v
(
atom
(
""
)),
"an atom_value"
);
CAF_CHECK_EQUAL
(
v
(
std
::
string
{}),
"a string"
);
CAF_CHECK_EQUAL
(
v
(
zero
<
float
>
()),
"a float"
);
CAF_CHECK_EQUAL
(
v
(
zero
<
double
>
()),
"a double"
);
CAF_CHECK_EQUAL
(
v
(
zero
<
int8_t
>
()),
"an 8-bit integer"
);
CAF_CHECK_EQUAL
(
v
(
zero
<
uint8_t
>
()),
"an 8-bit unsigned integer"
);
CAF_CHECK_EQUAL
(
v
(
zero
<
int16_t
>
()),
"a 16-bit integer"
);
CAF_CHECK_EQUAL
(
v
(
zero
<
uint16_t
>
()),
"a 16-bit unsigned integer"
);
CAF_CHECK_EQUAL
(
v
(
zero
<
int32_t
>
()),
"a 32-bit integer"
);
CAF_CHECK_EQUAL
(
v
(
zero
<
uint32_t
>
()),
"a 32-bit unsigned integer"
);
CAF_CHECK_EQUAL
(
v
(
zero
<
int64_t
>
()),
"a 64-bit integer"
);
CAF_CHECK_EQUAL
(
v
(
zero
<
uint64_t
>
()),
"a 64-bit unsigned integer"
);
}
libcaf_core/test/parse_ini.cpp
View file @
c99f508a
...
@@ -110,7 +110,7 @@ struct fixture {
...
@@ -110,7 +110,7 @@ struct fixture {
std
::
stringstream
ss
;
std
::
stringstream
ss
;
std
::
stringstream
err
;
std
::
stringstream
err
;
ss
<<
str
;
ss
<<
str
;
detail
::
parse_ini
(
ss
,
consumer
,
err
);
detail
::
parse_ini
(
ss
,
consumer
,
static_cast
<
std
::
ostream
&>
(
err
)
);
split
(
errors
,
err
.
str
(),
is_any_of
(
"
\n
"
),
token_compress_on
);
split
(
errors
,
err
.
str
(),
is_any_of
(
"
\n
"
),
token_compress_on
);
}
}
...
@@ -125,7 +125,8 @@ struct fixture {
...
@@ -125,7 +125,8 @@ struct fixture {
},
},
ERROR_HANDLER
ERROR_HANDLER
);
);
auto
consume
=
[
&
](
size_t
,
std
::
string
key
,
config_value
&
value
)
{
auto
consume
=
[
&
](
size_t
,
std
::
string
key
,
config_value
&
value
,
optional
<
std
::
ostream
&>
)
{
message_visitor
mv
;
message_visitor
mv
;
anon_send
(
config_server
,
put_atom
::
value
,
anon_send
(
config_server
,
put_atom
::
value
,
std
::
move
(
key
),
apply_visitor
(
mv
,
value
));
std
::
move
(
key
),
apply_visitor
(
mv
,
value
));
...
@@ -134,7 +135,8 @@ struct fixture {
...
@@ -134,7 +135,8 @@ struct fixture {
}
}
void
load
(
const
char
*
str
)
{
void
load
(
const
char
*
str
)
{
auto
consume
=
[
&
](
size_t
,
std
::
string
key
,
config_value
&
value
)
{
auto
consume
=
[
&
](
size_t
,
std
::
string
key
,
config_value
&
value
,
optional
<
std
::
ostream
&>
)
{
values
.
emplace
(
std
::
move
(
key
),
std
::
move
(
value
));
values
.
emplace
(
std
::
move
(
key
),
std
::
move
(
value
));
};
};
load_impl
(
consume
,
str
);
load_impl
(
consume
,
str
);
...
...
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