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
64324ccf
Commit
64324ccf
authored
Jun 14, 2018
by
Dominik Charousset
Committed by
Dominik Charousset
Jun 15, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Integrate new parser infrastructure
parent
042548ff
Changes
37
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
1574 additions
and
785 deletions
+1574
-785
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+3
-1
libcaf_core/caf/actor_system_config.hpp
libcaf_core/caf/actor_system_config.hpp
+41
-34
libcaf_core/caf/config_option.hpp
libcaf_core/caf/config_option.hpp
+43
-147
libcaf_core/caf/config_option_set.hpp
libcaf_core/caf/config_option_set.hpp
+132
-0
libcaf_core/caf/config_value.hpp
libcaf_core/caf/config_value.hpp
+61
-8
libcaf_core/caf/detail/algorithms.hpp
libcaf_core/caf/detail/algorithms.hpp
+43
-0
libcaf_core/caf/detail/ini_consumer.hpp
libcaf_core/caf/detail/ini_consumer.hpp
+212
-0
libcaf_core/caf/detail/move_if_not_ptr.hpp
libcaf_core/caf/detail/move_if_not_ptr.hpp
+46
-0
libcaf_core/caf/detail/parse_ini.hpp
libcaf_core/caf/detail/parse_ini.hpp
+2
-0
libcaf_core/caf/detail/parser/fsm.hpp
libcaf_core/caf/detail/parser/fsm.hpp
+10
-9
libcaf_core/caf/detail/parser/read_atom.hpp
libcaf_core/caf/detail/parser/read_atom.hpp
+4
-6
libcaf_core/caf/detail/parser/read_bool.hpp
libcaf_core/caf/detail/parser/read_bool.hpp
+3
-4
libcaf_core/caf/detail/parser/read_ini.hpp
libcaf_core/caf/detail/parser/read_ini.hpp
+49
-41
libcaf_core/caf/detail/parser/read_number.hpp
libcaf_core/caf/detail/parser/read_number.hpp
+20
-21
libcaf_core/caf/detail/parser/read_number_or_timespan.hpp
libcaf_core/caf/detail/parser/read_number_or_timespan.hpp
+8
-10
libcaf_core/caf/detail/parser/read_string.hpp
libcaf_core/caf/detail/parser/read_string.hpp
+4
-4
libcaf_core/caf/detail/parser/state.hpp
libcaf_core/caf/detail/parser/state.hpp
+2
-2
libcaf_core/caf/fwd.hpp
libcaf_core/caf/fwd.hpp
+7
-0
libcaf_core/caf/make_config_option.hpp
libcaf_core/caf/make_config_option.hpp
+60
-0
libcaf_core/caf/pec.hpp
libcaf_core/caf/pec.hpp
+19
-11
libcaf_core/caf/sec.hpp
libcaf_core/caf/sec.hpp
+2
-2
libcaf_core/src/actor_system_config.cpp
libcaf_core/src/actor_system_config.cpp
+90
-182
libcaf_core/src/config_option.cpp
libcaf_core/src/config_option.cpp
+46
-37
libcaf_core/src/config_option_set.cpp
libcaf_core/src/config_option_set.cpp
+178
-0
libcaf_core/src/config_value.cpp
libcaf_core/src/config_value.cpp
+6
-114
libcaf_core/src/ini_consumer.cpp
libcaf_core/src/ini_consumer.cpp
+169
-0
libcaf_core/src/pec.cpp
libcaf_core/src/pec.cpp
+14
-7
libcaf_core/test/config_option.cpp
libcaf_core/test/config_option.cpp
+36
-70
libcaf_core/test/config_option_set.cpp
libcaf_core/test/config_option_set.cpp
+103
-0
libcaf_core/test/config_value.cpp
libcaf_core/test/config_value.cpp
+7
-8
libcaf_core/test/ini_consumer.cpp
libcaf_core/test/ini_consumer.cpp
+93
-0
libcaf_core/test/read_atom.cpp
libcaf_core/test/read_atom.cpp
+7
-9
libcaf_core/test/read_bool.cpp
libcaf_core/test/read_bool.cpp
+14
-16
libcaf_core/test/read_ini.cpp
libcaf_core/test/read_ini.cpp
+5
-1
libcaf_core/test/read_number.cpp
libcaf_core/test/read_number.cpp
+10
-12
libcaf_core/test/read_number_or_timespan.cpp
libcaf_core/test/read_number_or_timespan.cpp
+18
-20
libcaf_core/test/read_string.cpp
libcaf_core/test/read_string.cpp
+7
-9
No files found.
libcaf_core/CMakeLists.txt
View file @
64324ccf
...
...
@@ -37,6 +37,7 @@ set(LIBCAF_CORE_SRCS
src/blocking_behavior.cpp
src/concatenated_tuple.cpp
src/config_option.cpp
src/config_option_set.cpp
src/config_value.cpp
src/decorated_tuple.cpp
src/default_attachable.cpp
...
...
@@ -47,7 +48,6 @@ set(LIBCAF_CORE_SRCS
src/downstream_messages.cpp
src/duration.cpp
src/dynamic_message_data.cpp
src/ec.cpp
src/error.cpp
src/event_based_actor.cpp
src/execution_unit.cpp
...
...
@@ -61,6 +61,7 @@ set(LIBCAF_CORE_SRCS
src/group_manager.cpp
src/group_module.cpp
src/inbound_path.cpp
src/ini_consumer.cpp
src/invoke_result_visitor.cpp
src/local_actor.cpp
src/logger.cpp
...
...
@@ -77,6 +78,7 @@ set(LIBCAF_CORE_SRCS
src/node_id.cpp
src/outbound_path.cpp
src/parse_ini.cpp
src/pec.cpp
src/pretty_type_name.cpp
src/private_thread.cpp
src/proxy_registry.cpp
...
...
libcaf_core/caf/actor_system_config.hpp
View file @
64324ccf
...
...
@@ -31,6 +31,7 @@
#include "caf/thread_hook.hpp"
#include "caf/config_value.hpp"
#include "caf/config_option.hpp"
#include "caf/config_option_set.hpp"
#include "caf/actor_factory.hpp"
#include "caf/is_typed_actor.hpp"
#include "caf/type_erased_value.hpp"
...
...
@@ -74,31 +75,37 @@ public:
using
error_renderer_map
=
hash_map
<
atom_value
,
error_renderer
>
;
using
option_ptr
=
std
::
unique_ptr
<
config_option
>
;
using
option_vector
=
std
::
vector
<
option_ptr
>
;
using
group_module_factory
=
std
::
function
<
group_module
*
()
>
;
using
group_module_factory_vector
=
std
::
vector
<
group_module_factory
>
;
using
config_map
=
std
::
map
<
std
::
string
,
config_value
::
dictionary
>
;
using
string_list
=
std
::
vector
<
std
::
string
>
;
// -- nested classes ---------------------------------------------------------
using
named_actor_config_map
=
hash_map
<
std
::
string
,
named_actor_config
>
;
class
opt_group
{
public:
opt_group
(
option_vector
&
xs
,
const
char
*
category
);
opt_group
(
config_option_set
&
xs
,
const
char
*
category
);
template
<
class
T
>
opt_group
&
add
(
T
&
storage
,
const
char
*
name
,
const
char
*
description
)
{
xs_
.
add
(
storage
,
category_
,
name
,
description
);
return
*
this
;
}
template
<
class
T
>
opt_group
&
add
(
T
&
storage
,
const
char
*
name
,
const
char
*
explana
tion
)
{
xs_
.
emplace_back
(
make_config_option
(
storage
,
cat_
,
name
,
explanation
)
);
opt_group
&
add
(
const
char
*
name
,
const
char
*
descrip
tion
)
{
xs_
.
add
<
T
>
(
category_
,
name
,
description
);
return
*
this
;
}
private:
option_vector
&
xs_
;
const
char
*
cat_
;
config_option_set
&
xs_
;
const
char
*
cat
egory
_
;
};
// -- constructors, destructors, and assignment operators --------------------
...
...
@@ -112,18 +119,29 @@ public:
actor_system_config
(
const
actor_system_config
&
)
=
delete
;
actor_system_config
&
operator
=
(
const
actor_system_config
&
)
=
delete
;
// -- properties -------------------------------------------------------------
/// @private
std
::
map
<
std
::
string
,
config_value
::
dictionary
>
content
;
/// Sets a config by using its INI name `config_name` to `config_value`.
template
<
class
T
>
actor_system_config
&
set
(
const
char
*
name
,
T
&&
value
)
{
return
set_impl
(
name
,
config_value
{
std
::
forward
<
T
>
(
value
)});
}
// -- modifiers --------------------------------------------------------------
/// Parses `args` as tuple of strings containing CLI options
/// and `ini_stream` as INI formatted input stream.
actor_system_config
&
parse
(
string_list
args
,
std
::
istream
&
ini
);
/// Parses `args` as tuple of strings containing CLI options and tries to
/// open `ini_file_cstr` as INI formatted config file. The parsers tries to
/// open `caf-application.ini` if `ini_file_cstr` is `nullptr`.
actor_system_config
&
parse
(
message
&
args
,
actor_system_config
&
parse
(
string_list
args
,
const
char
*
ini_file_cstr
=
nullptr
);
/// Parses `args` as tuple of strings containing CLI options
/// and `ini_stream` as INI formatted input stream.
actor_system_config
&
parse
(
message
&
args
,
std
::
istream
&
ini
);
/// Parses the CLI options `{argc, argv}` and
/// `ini_stream` as INI formatted input stream.
actor_system_config
&
parse
(
int
argc
,
char
**
argv
,
std
::
istream
&
ini
);
...
...
@@ -134,6 +152,11 @@ public:
actor_system_config
&
parse
(
int
argc
,
char
**
argv
,
const
char
*
ini_file_cstr
=
nullptr
);
actor_system_config
&
parse
(
message
&
args
,
const
char
*
ini_file_cstr
=
nullptr
)
CAF_DEPRECATED
;
actor_system_config
&
parse
(
message
&
args
,
std
::
istream
&
ini
)
CAF_DEPRECATED
;
/// Allows other nodes to spawn actors created by `fun`
/// dynamically by using `name` as identifier.
/// @experimental
...
...
@@ -237,12 +260,6 @@ public:
return
*
this
;
}
/// Sets a config by using its INI name `config_name` to `config_value`.
template
<
class
T
>
actor_system_config
&
set
(
const
char
*
cn
,
T
&&
x
)
{
return
set_impl
(
cn
,
config_value
{
std
::
forward
<
T
>
(
x
)});
}
// -- parser and CLI state ---------------------------------------------------
/// Stores whether the help text was printed. If set to `true`, the
...
...
@@ -385,16 +402,6 @@ public:
/// default.
std
::
string
config_file_path
;
// -- convenience functions --------------------------------------------------
template
<
class
F
>
void
for_each_option
(
F
f
)
const
{
const
option_vector
*
all_options
[]
=
{
&
options_
,
&
custom_options_
};
for
(
auto
&
opt_vec
:
all_options
)
for
(
auto
&
opt
:
*
opt_vec
)
f
(
*
opt
);
}
// -- utility for caf-run ----------------------------------------------------
// Config parameter for individual actor types.
...
...
@@ -405,7 +412,7 @@ public:
protected:
virtual
std
::
string
make_help_text
(
const
std
::
vector
<
message
::
cli_arg
>&
);
option_vector
custom_options_
;
config_option_set
custom_options_
;
private:
template
<
class
T
>
...
...
@@ -416,15 +423,15 @@ private:
&
make_type_erased_value
<
T
>
);
}
actor_system_config
&
set_impl
(
const
char
*
cn
,
config_value
cv
);
actor_system_config
&
set_impl
(
const
char
*
name
,
config_value
value
);
static
std
::
string
render_sec
(
uint8_t
,
atom_value
,
const
message
&
);
static
std
::
string
render_exit_reason
(
uint8_t
,
atom_value
,
const
message
&
);
void
extract_config_file_path
(
message
&
args
);
void
extract_config_file_path
(
string_list
&
args
);
option_vector
options_
;
config_option_set
options_
;
};
}
// namespace caf
...
...
libcaf_core/caf/config_option.hpp
View file @
64324ccf
...
...
@@ -18,179 +18,75 @@
#pragma once
#include <memory>
#include <string>
#include <vector>
#include <cstdint>
#include <cstring>
#include <functional>
#include "caf/atom.hpp"
#include "caf/config_value.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/error.hpp"
#include "caf/message.hpp"
#include "caf/static_visitor.hpp"
#include "caf/timestamp.hpp"
#include "caf/variant.hpp"
#include "caf/detail/type_traits.hpp"
namespace
caf
{
#include "caf/fwd.hpp"
extern
const
char
*
type_name_visitor_tbl
[];
namespace
caf
{
///
Helper class to generate config readers for different input types
.
///
Defines a configuration option for the application
.
class
config_option
{
public:
using
config_reader_sink
=
std
::
function
<
bool
(
size_t
,
config_value
&
,
optional
<
std
::
ostream
&>
)
>
;
// -- member types -----------------------------------------------------------
/// Custom vtable-like struct for delegating to type-specific functions.
struct
vtbl_type
{
error
(
*
check
)(
const
config_value
&
);
void
(
*
store
)(
void
*
,
const
config_value
&
);
};
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
,
timespan
>
;
// -- constructors, destructors, and assignment operators --------------------
config_option
(
const
char
*
cat
,
const
char
*
nm
,
const
char
*
expl
);
/// Constructs a config option.
config_option
(
std
::
string
category
,
const
char
*
name
,
std
::
string
description
,
bool
is_flag
,
const
vtbl_type
&
vtbl
,
void
*
storage
=
nullptr
);
virtual
~
config_option
()
;
config_option
(
config_option
&&
)
=
default
;
inline
const
char
*
name
()
const
{
return
name_
.
c_str
();
}
config_option
&
operator
=
(
config_option
&&
)
=
default
;
inline
char
short_name
()
const
{
return
short_name_
;
}
// -- properties -------------------------------------------------------------
inline
const
char
*
category
()
cons
t
{
inline
const
std
::
string
&
category
()
const
noexcep
t
{
return
category_
;
}
inline
const
char
*
explanation
()
const
{
return
explanation_
;
/// Returns the
inline
const
std
::
string
&
long_name
()
const
noexcept
{
return
long_name_
;
}
/// Returns the full name for this config option as "<category>.<long name>".
std
::
string
full_name
()
const
;
/// Returns the held value as string.
virtual
std
::
string
to_string
()
const
=
0
;
/// Returns a sink function for config readers.
virtual
config_reader_sink
to_sink
()
=
0
;
/// Returns a CLI argument parser.
virtual
message
::
cli_arg
to_cli_arg
(
bool
use_caf_prefix
=
false
)
=
0
;
/// Returns a human-readable type name for the visited type.
class
type_name_visitor
:
public
static_visitor
<
const
char
*>
{
public:
template
<
class
T
>
const
char
*
operator
()(
const
T
&
)
const
{
static
constexpr
bool
is_int
=
std
::
is_integral
<
T
>::
value
&&
!
std
::
is_same
<
bool
,
T
>::
value
;
static
constexpr
std
::
integral_constant
<
bool
,
is_int
>
tk
{};
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
)];
}
template
<
class
U
>
const
char
*
operator
()(
const
std
::
vector
<
U
>&
)
{
return
"a list"
;
}
template
<
class
K
,
class
V
>
const
char
*
operator
()(
const
std
::
map
<
K
,
V
>&
)
{
return
"a dictionary"
;
}
const
char
*
operator
()(
const
timespan
&
)
{
return
"a timespan"
;
}
private:
// Catches non-integer types.
template
<
class
T
>
static
constexpr
int
idx
(
std
::
false_type
)
{
return
detail
::
tl_index_of
<
legal_types
,
T
>::
value
;
}
// Catches integer types.
template
<
class
T
>
static
constexpr
int
idx
(
std
::
true_type
)
{
using
squashed
=
detail
::
squashed_int_t
<
T
>
;
return
detail
::
tl_index_of
<
legal_types
,
squashed
>::
value
;
}
};
protected:
void
report_type_error
(
size_t
ln
,
config_value
&
x
,
const
char
*
expected
,
optional
<
std
::
ostream
&>
out
);
private:
const
char
*
category_
;
std
::
string
name_
;
const
char
*
explanation_
;
char
short_name_
;
};
template
<
class
T
>
class
config_option_impl
:
public
config_option
{
public:
config_option_impl
(
T
&
ref
,
const
char
*
ctg
,
const
char
*
nm
,
const
char
*
xp
)
:
config_option
(
ctg
,
nm
,
xp
),
ref_
(
ref
)
{
// nop
inline
const
std
::
string
&
short_names
()
const
noexcept
{
return
short_names_
;
}
std
::
string
to_string
()
const
override
{
return
de
ep_to_string
(
ref_
)
;
inline
const
std
::
string
&
description
()
const
noexcept
{
return
de
scription_
;
}
message
::
cli_arg
to_cli_arg
(
bool
use_caf_prefix
)
override
{
std
::
string
argname
;
if
(
use_caf_prefix
)
argname
=
"caf#"
;
if
(
strcmp
(
category
(),
"global"
)
!=
0
)
{
argname
+=
category
();
argname
+=
"."
;
}
argname
+=
name
();
if
(
short_name
()
!=
'\0'
)
{
argname
+=
','
;
argname
+=
short_name
();
}
return
{
std
::
move
(
argname
),
explanation
(),
ref_
};
inline
bool
is_flag
()
const
noexcept
{
return
is_flag_
;
}
config_reader_sink
to_sink
()
override
{
return
[
=
](
size_t
ln
,
config_value
&
x
,
optional
<
std
::
ostream
&>
errors
)
{
auto
res
=
get_if
<
T
>
(
&
x
);
if
(
res
)
{
ref_
=
*
res
;
return
true
;
}
type_name_visitor
tnv
;
report_type_error
(
ln
,
x
,
tnv
(
ref_
),
errors
);
return
false
;
};
}
/// Returns the full name for this config option as "<category>.<long name>".
std
::
string
full_name
()
const
;
private:
T
&
ref_
;
};
/// Checks whether `x` holds a legal value for this option.
error
check
(
const
config_value
&
x
)
const
;
/// Stores `x` in this option unless it is stateless.
/// @pre `check(x) == none`.
void
store
(
const
config_value
&
x
)
const
;
template
<
class
T
>
std
::
unique_ptr
<
config_option
>
make_config_option
(
T
&
storage
,
const
char
*
category
,
const
char
*
name
,
const
char
*
explanation
)
{
auto
ptr
=
new
config_option_impl
<
T
>
(
storage
,
category
,
name
,
explanation
);
return
std
::
unique_ptr
<
config_option
>
{
ptr
};
}
private:
std
::
string
category_
;
std
::
string
long_name_
;
std
::
string
short_names_
;
std
::
string
description_
;
bool
is_flag_
;
vtbl_type
vtbl_
;
mutable
void
*
value_
;
};
}
// namespace caf
libcaf_core/caf/config_option_set.hpp
0 → 100644
View file @
64324ccf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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 <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "caf/config_option.hpp"
#include "caf/fwd.hpp"
#include "caf/make_config_option.hpp"
#include "caf/pec.hpp"
namespace
caf
{
/// A set of `config_option` objects that parses CLI arguments into a
/// `config_value::dictionary`.
class
config_option_set
{
public:
// -- member types -----------------------------------------------------------
/// An iterator over CLI arguments.
using
argument_iterator
=
std
::
vector
<
std
::
string
>::
const_iterator
;
/// The result of `parse` member functions.
using
parse_result
=
std
::
pair
<
pec
,
argument_iterator
>
;
/// List of config options.
using
option_vector
=
std
::
vector
<
config_option
>
;
/// Pointer to a config option.
using
option_pointer
=
const
config_option
*
;
/// An iterator over ::config_option unique pointers.
using
iterator
=
option_vector
::
iterator
;
/// Maps string keys to arbitrary (config) values.
using
dictionary
=
std
::
map
<
std
::
string
,
config_value
>
;
/// Categorized settings.
using
config_map
=
std
::
map
<
std
::
string
,
dictionary
>
;
// -- constructors, destructors, and assignment operators --------------------
config_option_set
();
// -- properties -------------------------------------------------------------
/// Returns the first `config_option` that matches the CLI name.
/// @param name Config option name formatted as
/// `<prefix>#<category>.<long-name>`. Users can omit `<prefix>`
/// for options that have an empty prefix and `<category>`
/// if the category is "global".
option_pointer
cli_long_name_lookup
(
const
std
::
string
&
name
)
const
;
/// Returns the first `config_option` that matches the CLI short option name.
option_pointer
cli_short_name_lookup
(
char
short_name
)
const
;
/// Returns the first `config_option` that matches category and long name.
option_pointer
qualified_name_lookup
(
const
std
::
string
&
category
,
const
std
::
string
&
long_name
)
const
;
/// Returns the first `config_option` that matches the qualified name.
/// @param name Config option name formatted as `<category>.<long-name>`.
option_pointer
qualified_name_lookup
(
const
std
::
string
&
name
)
const
;
/// Returns the number of stored config options.
inline
size_t
size
()
const
noexcept
{
return
opts_
.
size
();
}
/// Returns an iterator to the first ::config_option object.
inline
iterator
begin
()
noexcept
{
return
opts_
.
begin
();
}
/// Returns the past-the-end iterator.
inline
iterator
end
()
noexcept
{
return
opts_
.
end
();
}
/// Adds a config option to the set.
template
<
class
T
>
config_option_set
&
add
(
const
char
*
category
,
const
char
*
name
,
const
char
*
description
=
""
)
{
opts_
.
emplace_back
(
make_config_option
<
T
>
(
category
,
name
,
description
));
return
*
this
;
}
/// Adds a config option to the set that synchronizes its value with `ref`.
template
<
class
T
>
config_option_set
&
add
(
T
&
ref
,
const
char
*
category
,
const
char
*
name
,
const
char
*
description
=
""
)
{
opts_
.
emplace_back
(
make_config_option
<
T
>
(
ref
,
category
,
name
,
description
));
return
*
this
;
}
// -- parsing ----------------------------------------------------------------
/// Parses a given range as CLI arguments into `config`.
parse_result
parse
(
config_map
&
config
,
argument_iterator
begin
,
argument_iterator
end
)
const
;
/// Parses a given range as CLI arguments into `config`.
parse_result
parse
(
config_map
&
config
,
const
std
::
vector
<
std
::
string
>&
args
)
const
;
private:
// -- member variables -------------------------------------------------------
option_vector
opts_
;
};
}
// namespace caf
libcaf_core/caf/config_value.hpp
View file @
64324ccf
...
...
@@ -25,15 +25,11 @@
#include <vector>
#include "caf/atom.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/default_sum_type_access.hpp"
#include "caf/detail/bounds_checker.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/fwd.hpp"
#include "caf/optional.hpp"
#include "caf/string_algorithms.hpp"
#include "caf/sum_type.hpp"
#include "caf/sum_type_access.hpp"
#include "caf/timestamp.hpp"
#include "caf/variant.hpp"
...
...
@@ -44,10 +40,6 @@ namespace caf {
/// contain lists of themselves.
class
config_value
{
public:
// -- friends ----------------------------------------------------------------
friend
struct
default_sum_type_access
<
config_value
>
;
// -- member types -----------------------------------------------------------
using
integer
=
int64_t
;
...
...
@@ -452,6 +444,67 @@ T get_or(const config_value::dictionary& xs, const std::string& name,
return
default_value
;
}
/// Tries to retrieve the value associated to `name` from `xs`.
/// @relates config_value
template
<
class
T
>
optional
<
T
>
get_if
(
const
std
::
map
<
std
::
string
,
config_value
::
dictionary
>*
xs
,
const
std
::
string
&
name
)
{
// Get the category.
auto
pos
=
name
.
find
(
'.'
);
if
(
pos
==
std
::
string
::
npos
)
return
none
;
auto
i
=
xs
->
find
(
name
.
substr
(
0
,
pos
));
if
(
i
==
xs
->
end
())
return
none
;
return
get_if
<
T
>
(
&
i
->
second
,
name
.
substr
(
pos
+
1
));
}
/// Retrieves the value associated to `name` from `xs`.
/// @relates config_value
template
<
class
T
>
T
get
(
const
std
::
map
<
std
::
string
,
config_value
::
dictionary
>&
xs
,
const
std
::
string
&
name
)
{
auto
result
=
get_if
<
T
>
(
&
xs
,
name
);
if
(
result
)
return
std
::
move
(
*
result
);
CAF_RAISE_ERROR
(
"invalid type or name found"
);
}
/// Retrieves the value associated to `name` from `xs` or returns
/// `default_value`.
/// @relates config_value
template
<
class
T
>
T
get_or
(
const
std
::
map
<
std
::
string
,
config_value
::
dictionary
>&
xs
,
const
std
::
string
&
name
,
const
T
&
default_value
)
{
auto
result
=
get_if
<
T
>
(
&
xs
,
name
);
if
(
result
)
return
std
::
move
(
*
result
);
return
default_value
;
}
/// Tries to retrieve the value associated to `name` from `cfg`.
/// @relates config_value
template
<
class
T
>
optional
<
T
>
get_if
(
const
actor_system_config
*
cfg
,
const
std
::
string
&
name
)
{
return
get_if
<
T
>
(
&
content
(
*
cfg
),
name
);
}
/// Retrieves the value associated to `name` from `cfg`.
/// @relates config_value
template
<
class
T
>
T
get
(
const
actor_system_config
&
cfg
,
const
std
::
string
&
name
)
{
return
get
<
T
>
(
content
(
cfg
),
name
);
}
/// Retrieves the value associated to `name` from `cfg` or returns
/// `default_value`.
/// @relates config_value
template
<
class
T
>
T
get_or
(
const
actor_system_config
&
cfg
,
const
std
::
string
&
name
,
const
T
&
default_value
)
{
return
get_or
(
content
(
cfg
),
name
,
default_value
);
}
/// @relates config_value
bool
operator
<
(
const
config_value
&
x
,
const
config_value
&
y
);
...
...
libcaf_core/caf/detail/algorithms.hpp
View file @
64324ccf
...
...
@@ -85,6 +85,49 @@ container_view<F, Container> make_container_view(Container& x) {
return
{
x
};
}
/// Like `std::find`, but takes a range instead of an iterator pair and returns
/// a pointer to the found object on success instead of returning an iterator.
template
<
class
T
>
typename
T
::
value_type
*
ptr_find
(
T
&
xs
,
const
typename
T
::
value_type
&
x
)
{
for
(
auto
&
y
:
xs
)
if
(
y
==
x
)
return
&
y
;
return
nullptr
;
}
/// Like `std::find`, but takes a range instead of an iterator pair and returns
/// a pointer to the found object on success instead of returning an iterator.
template
<
class
T
>
const
typename
T
::
value_type
*
ptr_find
(
const
T
&
xs
,
const
typename
T
::
value_type
&
x
)
{
for
(
auto
&
y
:
xs
)
if
(
y
==
x
)
return
&
y
;
return
nullptr
;
}
/// Like `std::find_if`, but takes a range instead of an iterator pair and
/// returns a pointer to the found object on success instead of returning an
/// iterator.
template
<
class
T
,
class
Predicate
>
typename
T
::
value_type
*
ptr_find_if
(
T
&
xs
,
Predicate
pred
)
{
for
(
auto
&
x
:
xs
)
if
(
pred
(
x
))
return
&
x
;
return
nullptr
;
}
/// Like `std::find_if`, but takes a range instead of an iterator pair and
/// returns a pointer to the found object on success instead of returning an
/// iterator.
template
<
class
T
,
class
Predicate
>
const
typename
T
::
value_type
*
ptr_find_if
(
const
T
&
xs
,
Predicate
pred
)
{
for
(
auto
&
x
:
xs
)
if
(
pred
(
x
))
return
&
x
;
return
nullptr
;
}
}
// namespace detail
}
// namespace caf
libcaf_core/caf/detail/ini_consumer.hpp
0 → 100644
View file @
64324ccf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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 <map>
#include <string>
#include "caf/config_option_set.hpp"
#include "caf/config_value.hpp"
namespace
caf
{
namespace
detail
{
class
ini_consumer
;
class
ini_list_consumer
;
class
ini_map_consumer
;
class
abstract_ini_consumer
{
public:
// -- constructors, destructors, and assignment operators --------------------
explicit
abstract_ini_consumer
(
abstract_ini_consumer
*
parent
=
nullptr
);
virtual
~
abstract_ini_consumer
();
// -- properties -------------------------------------------------------------
virtual
void
value_impl
(
config_value
&&
x
)
=
0
;
template
<
class
T
>
void
value
(
T
&&
x
)
{
value_impl
(
config_value
{
std
::
forward
<
T
>
(
x
)});
}
inline
abstract_ini_consumer
*
parent
()
{
return
parent_
;
}
ini_map_consumer
begin_map
();
ini_list_consumer
begin_list
();
protected:
// -- member variables -------------------------------------------------------
abstract_ini_consumer
*
parent_
;
};
class
ini_map_consumer
:
public
abstract_ini_consumer
{
public:
// -- member types -----------------------------------------------------------
using
super
=
abstract_ini_consumer
;
using
map_type
=
config_value
::
dictionary
;
using
iterator
=
map_type
::
iterator
;
// -- constructors, destructors, and assignment operators --------------------
ini_map_consumer
(
abstract_ini_consumer
*
ptr
);
ini_map_consumer
(
ini_map_consumer
&&
other
);
~
ini_map_consumer
()
override
;
// -- properties -------------------------------------------------------------
void
end_map
();
void
key
(
std
::
string
name
);
void
value_impl
(
config_value
&&
x
)
override
;
private:
// -- member variables -------------------------------------------------------
map_type
xs_
;
iterator
i_
;
};
class
ini_list_consumer
:
public
abstract_ini_consumer
{
public:
// -- member types -----------------------------------------------------------
using
super
=
abstract_ini_consumer
;
// -- constructors, destructors, and assignment operators --------------------
ini_list_consumer
(
abstract_ini_consumer
*
ptr
);
ini_list_consumer
(
ini_list_consumer
&&
other
);
// -- properties -------------------------------------------------------------
void
end_list
();
void
value_impl
(
config_value
&&
x
)
override
;
private:
// -- member variables -------------------------------------------------------
config_value
::
list
xs_
;
};
/// Consumes a single value from an INI parser.
class
ini_value_consumer
:
public
abstract_ini_consumer
{
public:
// -- member types -----------------------------------------------------------
using
super
=
abstract_ini_consumer
;
// -- constructors, destructors, and assignment operators --------------------
explicit
ini_value_consumer
(
abstract_ini_consumer
*
parent
=
nullptr
);
// -- properties -------------------------------------------------------------
void
value_impl
(
config_value
&&
x
)
override
;
// -- member variables -------------------------------------------------------
config_value
result
;
};
/// Consumes a config category.
class
ini_category_consumer
:
public
abstract_ini_consumer
{
public:
// -- member types -----------------------------------------------------------
using
super
=
abstract_ini_consumer
;
// -- constructors, destructors, and assignment operators --------------------
ini_category_consumer
(
ini_consumer
*
parent
,
std
::
string
category
);
ini_category_consumer
(
ini_category_consumer
&&
)
=
default
;
// -- properties -------------------------------------------------------------
void
end_map
();
void
key
(
std
::
string
name
);
void
value_impl
(
config_value
&&
x
)
override
;
private:
// -- properties -------------------------------------------------------------
ini_consumer
*
dparent
();
// -- member variables -------------------------------------------------------
std
::
string
category_
;
config_value
::
dictionary
xs_
;
std
::
string
current_key
;
};
/// Consumes a series of dictionaries forming a application configuration.
class
ini_consumer
:
public
abstract_ini_consumer
{
public:
// -- friends ----------------------------------------------------------------
friend
class
ini_category_consumer
;
// -- member types -----------------------------------------------------------
using
super
=
abstract_ini_consumer
;
using
config_map
=
std
::
map
<
std
::
string
,
config_value
::
dictionary
>
;
// -- constructors, destructors, and assignment operators --------------------
ini_consumer
(
config_option_set
&
options
,
config_map
&
cfg
);
ini_consumer
(
ini_consumer
&&
)
=
default
;
// -- properties -------------------------------------------------------------
ini_category_consumer
begin_map
();
void
key
(
std
::
string
name
);
void
value_impl
(
config_value
&&
x
)
override
;
private:
// -- member variables -------------------------------------------------------
config_option_set
&
options_
;
config_map
&
cfg_
;
std
::
string
current_key
;
std
::
vector
<
error
>
warnings_
;
};
}
// namespace detail
}
// namespace caf
libcaf_core/caf/detail/move_if_not_ptr.hpp
0 → 100644
View file @
64324ccf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* *
* 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 <type_traits>
#include "caf/detail/type_traits.hpp"
namespace
caf
{
namespace
detail
{
/// Moves the value from `x` if it is not a pointer (e.g., `optional` or
/// `expected`), returns `*x` otherwise.
template
<
class
T
>
T
&
move_if_not_ptr
(
T
*
x
)
{
return
*
x
;
}
/// Moves the value from `x` if it is not a pointer (e.g., `optional` or
/// `expected`), returns `*x` otherwise.
template
<
class
T
,
class
E
=
enable_if_t
<!
std
::
is_pointer
<
T
>
::
value
>>
T
&&
move_if_not_ptr
(
T
&
x
)
{
return
std
::
move
(
*
x
);
}
}
// namespace detail
}
// namespace caf
libcaf_core/caf/detail/parse_ini.hpp
View file @
64324ccf
...
...
@@ -30,6 +30,8 @@
namespace
caf
{
namespace
detail
{
struct
parse_ini_t
{
/// Denotes an optional error output stream
using
opt_err
=
optional
<
std
::
ostream
&>
;
...
...
libcaf_core/caf/detail/parser/fsm.hpp
View file @
64324ccf
...
...
@@ -21,6 +21,7 @@
#include <cstring>
#include "caf/detail/pp.hpp"
#include "caf/pec.hpp"
namespace
caf
{
namespace
detail
{
...
...
@@ -55,8 +56,8 @@ extern const char octal_chars[9];
}
// namespace caf
#define CAF_FSM_EVAL_MISMATCH_EC \
if (mismatch_ec ==
ec::unexpected_character)
\
ps.code = ch != '\n' ? mismatch_ec :
ec::unexpected_newline;
\
if (mismatch_ec ==
caf::pec::unexpected_character)
\
ps.code = ch != '\n' ? mismatch_ec :
caf::pec::unexpected_newline;
\
else \
ps.code = mismatch_ec; \
return;
...
...
@@ -67,17 +68,17 @@ extern const char octal_chars[9];
goto s_init; \
s_unexpected_eof: \
__attribute__((unused)); \
ps.code =
ec::unexpected_eof;
\
ps.code =
caf::pec::unexpected_eof;
\
return; \
{ \
static constexpr
ec mismatch_ec =
ec::unexpected_character
static constexpr
auto mismatch_ec = caf::p
ec::unexpected_character
/// Defines a non-terminal state in the FSM.
#define state(name) \
CAF_FSM_EVAL_MISMATCH_EC \
} \
{ \
static constexpr
ec mismatch_ec = ec::unexpected_character;
\
static constexpr
auto mismatch_ec = caf::pec::unexpected_character;
\
s_##name : __attribute__((unused)); \
if (ch == '\0') \
goto s_unexpected_eof; \
...
...
@@ -88,7 +89,7 @@ extern const char octal_chars[9];
CAF_FSM_EVAL_MISMATCH_EC \
} \
{ \
static constexpr
ec mismatch_ec = ec::trailing_character;
\
static constexpr
auto mismatch_ec = caf::pec::trailing_character;
\
s_##name : __attribute__((unused)); \
if (ch == '\0') \
goto s_fin; \
...
...
@@ -99,7 +100,7 @@ extern const char octal_chars[9];
CAF_FSM_EVAL_MISMATCH_EC \
} \
s_fin: \
ps.code =
ec::success;
\
ps.code =
caf::pec::success;
\
return;
#define CAF_TRANSITION_IMPL1(target) \
...
...
@@ -181,7 +182,7 @@ extern const char octal_chars[9];
#define CAF_FSM_TRANSITION_IMPL2(fsm_call, target) \
ps.next(); \
fsm_call; \
if (ps.code >
ec::trailing_character)
\
if (ps.code >
caf::pec::trailing_character)
\
return; \
ch = ps.current(); \
goto s_##target;
...
...
@@ -218,7 +219,7 @@ extern const char octal_chars[9];
#define CAF_FSM_EPSILON_IMPL2(fsm_call, target) \
fsm_call; \
if (ps.code >
ec::trailing_character)
\
if (ps.code >
caf::pec::trailing_character)
\
return; \
ch = ps.current(); \
goto s_##target;
...
...
libcaf_core/caf/detail/parser/read_atom.hpp
View file @
64324ccf
...
...
@@ -23,13 +23,11 @@
#include <string>
#include "caf/atom.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/detail/parser/ec.hpp"
#include "caf/detail/parser/fsm.hpp"
#include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp"
namespace
caf
{
namespace
detail
{
...
...
@@ -52,7 +50,7 @@ void read_atom(state<Iterator, Sentinel>& ps, Consumer& consumer) {
return
true
;
};
auto
g
=
caf
::
detail
::
make_scope_guard
([
&
]
{
if
(
ps
.
code
<=
ec
::
trailing_character
)
if
(
ps
.
code
<=
p
ec
::
trailing_character
)
consumer
.
value
(
atom
(
buf
));
});
start
();
...
...
@@ -62,7 +60,7 @@ void read_atom(state<Iterator, Sentinel>& ps, Consumer& consumer) {
}
state
(
read_chars
)
{
transition
(
done
,
'\''
)
transition
(
read_chars
,
is_legal
,
append
(
ch
),
ec
::
too_many_characters
)
transition
(
read_chars
,
is_legal
,
append
(
ch
),
p
ec
::
too_many_characters
)
}
term_state
(
done
)
{
transition
(
done
,
"
\t
"
)
...
...
libcaf_core/caf/detail/parser/read_bool.hpp
View file @
64324ccf
...
...
@@ -21,12 +21,11 @@
#include <cstdint>
#include <string>
#include "caf/detail/scope_guard.hpp"
#include "caf/detail/parser/ec.hpp"
#include "caf/detail/parser/fsm.hpp"
#include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp"
namespace
caf
{
namespace
detail
{
...
...
@@ -37,7 +36,7 @@ template <class Iterator, class Sentinel, class Consumer>
void
read_bool
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
consumer
)
{
bool
res
=
false
;
auto
g
=
make_scope_guard
([
&
]
{
if
(
ps
.
code
<=
ec
::
trailing_character
)
if
(
ps
.
code
<=
p
ec
::
trailing_character
)
consumer
.
value
(
res
);
});
start
();
...
...
libcaf_core/caf/detail/parser/read_ini.hpp
View file @
64324ccf
...
...
@@ -22,13 +22,13 @@
#include <stack>
#include "caf/detail/parser/ec.hpp"
#include "caf/detail/parser/fsm.hpp"
#include "caf/detail/parser/read_atom.hpp"
#include "caf/detail/parser/read_bool.hpp"
#include "caf/detail/parser/read_number_or_timespan.hpp"
#include "caf/detail/parser/read_string.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp"
namespace
caf
{
namespace
detail
{
...
...
@@ -52,7 +52,7 @@ namespace parser {
//
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
>
void
read_ini_comment
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
)
{
void
read_ini_comment
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
&
)
{
start
();
term_state
(
init
)
{
transition
(
done
,
'\n'
)
...
...
@@ -65,7 +65,7 @@ void read_ini_comment(state<Iterator, Sentinel>& ps, Consumer&) {
}
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
>
void
read_ini_value
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
consumer
);
void
read_ini_value
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
&
consumer
);
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
>
void
read_ini_list
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&&
consumer
)
{
...
...
@@ -136,7 +136,7 @@ void read_ini_map(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
}
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
>
void
read_ini_value
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
consumer
)
{
void
read_ini_value
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
&
consumer
)
{
start
();
state
(
init
)
{
fsm_epsilon
(
read_string
(
ps
,
consumer
),
done
,
'"'
)
...
...
@@ -155,57 +155,26 @@ void read_ini_value(state<Iterator, Sentinel>& ps, Consumer& consumer) {
/// Reads an INI formatted input.
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
>
void
read_ini
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
consumer
)
{
void
read_ini
_section
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
&
consumer
)
{
using
std
::
swap
;
std
::
string
tmp
;
auto
alnum_or_dash
=
[](
char
x
)
{
return
isalnum
(
x
)
||
x
==
'-'
||
x
==
'_'
;
};
bool
in_section
=
false
;
auto
emit_key
=
[
&
]
{
std
::
string
key
;
swap
(
tmp
,
key
);
consumer
.
key
(
std
::
move
(
key
));
};
auto
begin_section
=
[
&
]
{
if
(
in_section
)
consumer
.
end_map
();
else
in_section
=
true
;
emit_key
();
consumer
.
begin_map
();
};
auto
g
=
make_scope_guard
([
&
]
{
if
(
ps
.
code
<=
ec
::
trailing_character
&&
in_section
)
consumer
.
end_map
();
if
(
ps
.
code
<=
pec
::
trailing_character
)
consumer
.
end_map
();
});
start
();
//
Scanning for first section
.
//
Dispatches to read sections, comments, or key/value pairs
.
term_state
(
init
)
{
transition
(
init
,
"
\t\n
"
)
fsm_epsilon
(
read_ini_comment
(
ps
,
consumer
),
init
,
';'
)
transition
(
start_section
,
'['
)
}
// Read the section key after reading an '['.
state
(
start_section
)
{
transition
(
start_section
,
"
\t
"
)
transition
(
read_section_name
,
alphabetic_chars
,
tmp
=
ch
)
}
// Reads a section name such as "[foo]".
state
(
read_section_name
)
{
transition
(
read_section_name
,
alnum_or_dash
,
tmp
+=
ch
)
epsilon
(
close_section
)
}
// Wait for the closing ']', preceded by any number of whitespaces.
state
(
close_section
)
{
transition
(
close_section
,
"
\t
"
)
transition
(
dispatch
,
']'
,
begin_section
())
}
// Dispatches to read sections, comments, or key/value pairs.
term_state
(
dispatch
)
{
transition
(
dispatch
,
"
\t\n
"
)
transition
(
read_section_name
,
'['
)
fsm_epsilon
(
read_ini_comment
(
ps
,
consumer
),
dispatch
,
';'
)
transition
(
read_key_name
,
alphanumeric_chars
,
tmp
=
ch
)
}
// Reads a key of a "key=value" line.
...
...
@@ -226,8 +195,47 @@ void read_ini(state<Iterator, Sentinel>& ps, Consumer& consumer) {
// Waits for end-of-line after reading a value
term_state
(
await_eol
)
{
transition
(
await_eol
,
"
\t
"
)
fsm_epsilon
(
read_ini_comment
(
ps
,
consumer
),
dispatch
,
';'
)
transition
(
dispatch
,
'\n'
)
fsm_epsilon
(
read_ini_comment
(
ps
,
consumer
),
init
,
';'
)
transition
(
init
,
'\n'
)
}
fin
();
}
/// Reads an INI formatted input.
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
>
void
read_ini
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&&
consumer
)
{
using
std
::
swap
;
std
::
string
tmp
;
auto
alnum_or_dash
=
[](
char
x
)
{
return
isalnum
(
x
)
||
x
==
'-'
||
x
==
'_'
;
};
auto
begin_section
=
[
&
]()
->
decltype
(
consumer
.
begin_map
())
{
std
::
string
key
;
swap
(
tmp
,
key
);
consumer
.
key
(
std
::
move
(
key
));
return
consumer
.
begin_map
();
};
start
();
// Scanning for first section.
term_state
(
init
)
{
transition
(
init
,
"
\t\n
"
)
fsm_epsilon
(
read_ini_comment
(
ps
,
consumer
),
init
,
';'
)
transition
(
start_section
,
'['
)
}
// Read the section key after reading an '['.
state
(
start_section
)
{
transition
(
start_section
,
"
\t
"
)
transition
(
read_section_name
,
alphabetic_chars
,
tmp
=
ch
)
}
// Reads a section name such as "[foo]".
state
(
read_section_name
)
{
transition
(
read_section_name
,
alnum_or_dash
,
tmp
+=
ch
)
epsilon
(
close_section
)
}
// Wait for the closing ']', preceded by any number of whitespaces.
state
(
close_section
)
{
transition
(
close_section
,
"
\t
"
)
fsm_transition
(
read_ini_section
(
ps
,
begin_section
()),
init
,
']'
)
}
fin
();
}
...
...
libcaf_core/caf/detail/parser/read_number.hpp
View file @
64324ccf
...
...
@@ -20,15 +20,14 @@
#include <cstdint>
#include "caf/detail/scope_guard.hpp"
#include "caf/detail/parser/add_ascii.hpp"
#include "caf/detail/parser/ec.hpp"
#include "caf/detail/parser/fsm.hpp"
#include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/is_digit.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/parser/sub_ascii.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp"
namespace
caf
{
namespace
detail
{
...
...
@@ -53,7 +52,7 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
int64_t
int_res
=
0
;
// Computes the result on success.
auto
g
=
caf
::
detail
::
make_scope_guard
([
&
]
{
if
(
ps
.
code
<=
ec
::
trailing_character
)
{
if
(
ps
.
code
<=
p
ec
::
trailing_character
)
{
if
(
result_type
==
integer
)
{
consumer
.
value
(
int_res
);
return
;
...
...
@@ -63,11 +62,11 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
exp
+=
dec_exp
;
// 2) Check whether exponent is in valid range.
if
(
exp
<
-
max_double_exponent
)
{
ps
.
code
=
ec
::
exponent_underflow
;
ps
.
code
=
p
ec
::
exponent_underflow
;
return
;
}
if
(
exp
>
max_double_exponent
)
{
ps
.
code
=
ec
::
exponent_overflow
;
ps
.
code
=
p
ec
::
exponent_overflow
;
return
;
}
// 3) Scale result.
...
...
@@ -140,13 +139,13 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
epsilon
(
pos_bin
)
}
term_state
(
pos_bin
)
{
transition
(
pos_bin
,
"01"
,
add_ascii
<
2
>
(
int_res
,
ch
),
ec
::
integer_overflow
)
transition
(
pos_bin
,
"01"
,
add_ascii
<
2
>
(
int_res
,
ch
),
p
ec
::
integer_overflow
)
}
state
(
start_neg_bin
)
{
epsilon
(
neg_bin
)
}
term_state
(
neg_bin
)
{
transition
(
neg_bin
,
"01"
,
sub_ascii
<
2
>
(
int_res
,
ch
),
ec
::
integer_underflow
)
transition
(
neg_bin
,
"01"
,
sub_ascii
<
2
>
(
int_res
,
ch
),
p
ec
::
integer_underflow
)
}
// Octal integers.
state
(
start_pos_oct
)
{
...
...
@@ -154,14 +153,14 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
}
term_state
(
pos_oct
)
{
transition
(
pos_oct
,
octal_chars
,
add_ascii
<
8
>
(
int_res
,
ch
),
ec
::
integer_overflow
)
p
ec
::
integer_overflow
)
}
state
(
start_neg_oct
)
{
epsilon
(
neg_oct
)
}
term_state
(
neg_oct
)
{
transition
(
neg_oct
,
octal_chars
,
sub_ascii
<
8
>
(
int_res
,
ch
),
ec
::
integer_underflow
)
p
ec
::
integer_underflow
)
}
// Hexal integers.
state
(
start_pos_hex
)
{
...
...
@@ -169,32 +168,32 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
}
term_state
(
pos_hex
)
{
transition
(
pos_hex
,
hexadecimal_chars
,
add_ascii
<
16
>
(
int_res
,
ch
),
ec
::
integer_overflow
)
p
ec
::
integer_overflow
)
}
state
(
start_neg_hex
)
{
epsilon
(
neg_hex
)
}
term_state
(
neg_hex
)
{
transition
(
neg_hex
,
hexadecimal_chars
,
sub_ascii
<
16
>
(
int_res
,
ch
),
ec
::
integer_underflow
)
p
ec
::
integer_underflow
)
}
// Reads the integer part of the mantissa or a positive decimal integer.
term_state
(
pos_dec
)
{
transition
(
pos_dec
,
decimal_chars
,
add_ascii
<
10
>
(
int_res
,
ch
),
ec
::
integer_overflow
)
p
ec
::
integer_overflow
)
transition
(
has_e
,
"eE"
,
ch_res
(
positive_double
))
transition
(
trailing_dot
,
'.'
,
ch_res
(
positive_double
))
}
// Reads the integer part of the mantissa or a negative decimal integer.
term_state
(
neg_dec
)
{
transition
(
neg_dec
,
decimal_chars
,
sub_ascii
<
10
>
(
int_res
,
ch
),
ec
::
integer_underflow
)
p
ec
::
integer_underflow
)
transition
(
has_e
,
"eE"
,
ch_res
(
negative_double
))
transition
(
trailing_dot
,
'.'
,
ch_res
(
negative_double
))
}
// ".", "+.", etc. aren't valid numbers, so this state isn't terminal.
state
(
leading_dot
)
{
transition
(
after_dot
,
decimal_chars
,
rd_decimal
(
ch
),
ec
::
exponent_underflow
)
transition
(
after_dot
,
decimal_chars
,
rd_decimal
(
ch
),
p
ec
::
exponent_underflow
)
}
// "1." is a valid number, so a trailing dot is a terminal state.
term_state
(
trailing_dot
)
{
...
...
@@ -202,7 +201,7 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
}
// Read the decimal part of a mantissa.
term_state
(
after_dot
)
{
transition
(
after_dot
,
decimal_chars
,
rd_decimal
(
ch
),
ec
::
exponent_underflow
)
transition
(
after_dot
,
decimal_chars
,
rd_decimal
(
ch
),
p
ec
::
exponent_underflow
)
transition
(
has_e
,
"eE"
)
}
// "...e", "...e+", and "...e-" aren't valid numbers, so these states are not
...
...
@@ -211,25 +210,25 @@ void read_number(state<Iterator, Sentinel>& ps, Consumer& consumer) {
transition
(
has_plus_after_e
,
'+'
)
transition
(
has_minus_after_e
,
'-'
)
transition
(
pos_exp
,
decimal_chars
,
add_ascii
<
10
>
(
exp
,
ch
),
ec
::
exponent_overflow
)
p
ec
::
exponent_overflow
)
}
state
(
has_plus_after_e
)
{
transition
(
pos_exp
,
decimal_chars
,
add_ascii
<
10
>
(
exp
,
ch
),
ec
::
exponent_overflow
)
p
ec
::
exponent_overflow
)
}
state
(
has_minus_after_e
)
{
transition
(
neg_exp
,
decimal_chars
,
sub_ascii
<
10
>
(
exp
,
ch
),
ec
::
exponent_underflow
)
p
ec
::
exponent_underflow
)
}
// Read a positive exponent.
term_state
(
pos_exp
)
{
transition
(
pos_exp
,
decimal_chars
,
add_ascii
<
10
>
(
exp
,
ch
),
ec
::
exponent_overflow
)
p
ec
::
exponent_overflow
)
}
// Read a negative exponent.
term_state
(
neg_exp
)
{
transition
(
neg_exp
,
decimal_chars
,
sub_ascii
<
10
>
(
exp
,
ch
),
ec
::
exponent_underflow
)
p
ec
::
exponent_underflow
)
}
fin
();
}
...
...
libcaf_core/caf/detail/parser/read_number_or_timespan.hpp
View file @
64324ccf
...
...
@@ -22,18 +22,16 @@
#include <cstdint>
#include <string>
#include "caf/none.hpp"
#include "caf/optional.hpp"
#include "caf/timestamp.hpp"
#include "caf/variant.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/detail/parser/ec.hpp"
#include "caf/detail/parser/fsm.hpp"
#include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/read_number.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/none.hpp"
#include "caf/optional.hpp"
#include "caf/pec.hpp"
#include "caf/timestamp.hpp"
#include "caf/variant.hpp"
namespace
caf
{
namespace
detail
{
...
...
@@ -60,7 +58,7 @@ void read_number_or_timespan(state<Iterator, Sentinel>& ps,
auto
has_dbl
=
[
&
]
{
return
holds_alternative
<
double
>
(
ic
.
interim
);
};
auto
get_int
=
[
&
]
{
return
get
<
int64_t
>
(
ic
.
interim
);
};
auto
g
=
make_scope_guard
([
&
]
{
if
(
ps
.
code
<=
ec
::
trailing_character
)
{
if
(
ps
.
code
<=
p
ec
::
trailing_character
)
{
if
(
res
!=
none
)
{
consumer
.
value
(
*
res
);
}
else
if
(
!
holds_alternative
<
none_t
>
(
ic
.
interim
))
{
...
...
@@ -80,7 +78,7 @@ void read_number_or_timespan(state<Iterator, Sentinel>& ps,
epsilon_if
(
has_dbl
(),
has_double
)
}
term_state
(
has_double
)
{
error_transition
(
ec
::
fractional_timespan
,
"unms"
)
error_transition
(
p
ec
::
fractional_timespan
,
"unms"
)
}
term_state
(
has_integer
)
{
transition
(
have_u
,
'u'
)
...
...
libcaf_core/caf/detail/parser/read_string.hpp
View file @
64324ccf
...
...
@@ -23,10 +23,10 @@
#include "caf/detail/scope_guard.hpp"
#include "caf/detail/parser/ec.hpp"
#include "caf/detail/parser/fsm.hpp"
#include "caf/detail/parser/is_char.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/pec.hpp"
namespace
caf
{
namespace
detail
{
...
...
@@ -38,7 +38,7 @@ template <class Iterator, class Sentinel, class Consumer>
void
read_string
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&
consumer
)
{
std
::
string
res
;
auto
g
=
caf
::
detail
::
make_scope_guard
([
&
]
{
if
(
ps
.
code
<=
ec
::
trailing_character
)
if
(
ps
.
code
<=
p
ec
::
trailing_character
)
consumer
.
value
(
std
::
move
(
res
));
});
start
();
...
...
@@ -49,7 +49,7 @@ void read_string(state<Iterator, Sentinel>& ps, Consumer& consumer) {
state
(
read_chars
)
{
transition
(
escape
,
'\\'
)
transition
(
done
,
'"'
)
error_transition
(
ec
::
unexpected_newline
,
'\n'
)
error_transition
(
p
ec
::
unexpected_newline
,
'\n'
)
transition
(
read_chars
,
any_char
,
res
+=
ch
)
}
state
(
escape
)
{
...
...
@@ -58,7 +58,7 @@ void read_string(state<Iterator, Sentinel>& ps, Consumer& consumer) {
transition
(
read_chars
,
't'
,
res
+=
'\t'
)
transition
(
read_chars
,
'\\'
,
res
+=
'\\'
)
transition
(
read_chars
,
'"'
,
res
+=
'"'
)
error_transition
(
ec
::
illegal_escape_sequence
)
error_transition
(
p
ec
::
illegal_escape_sequence
)
}
term_state
(
done
)
{
transition
(
done
,
"
\t
"
)
...
...
libcaf_core/caf/detail/parser/state.hpp
View file @
64324ccf
...
...
@@ -20,7 +20,7 @@
#include <cstdint>
#include "caf/
detail/parser/
ec.hpp"
#include "caf/
p
ec.hpp"
namespace
caf
{
namespace
detail
{
...
...
@@ -30,7 +30,7 @@ template <class Iterator, class Sentinel = Iterator>
struct
state
{
Iterator
i
;
Sentinel
e
;
ec
code
;
p
ec
code
;
int32_t
line
=
1
;
int32_t
column
=
1
;
...
...
libcaf_core/caf/fwd.hpp
View file @
64324ccf
...
...
@@ -19,6 +19,7 @@
#pragma once
#include <cstdint>
#include <map>
#include <memory>
#include <tuple>
...
...
@@ -138,6 +139,12 @@ struct prohibit_top_level_spawn_marker;
enum
class
stream_priority
;
enum
class
atom_value
:
uint64_t
;
// -- functions ----------------------------------------------------------------
/// @relates actor_system_config
const
std
::
map
<
std
::
string
,
std
::
map
<
std
::
string
,
config_value
>>&
content
(
const
actor_system_config
&
);
// -- aliases ------------------------------------------------------------------
using
actor_id
=
uint64_t
;
...
...
libcaf_core/caf/make_config_option.hpp
0 → 100644
View file @
64324ccf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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_option.hpp"
#include "caf/config_value.hpp"
#include "caf/pec.hpp"
namespace
caf
{
/// Creates a config option that synchronizes with `storage`.
template
<
class
T
>
config_option
make_config_option
(
const
char
*
category
,
const
char
*
name
,
const
char
*
description
)
{
config_option
::
vtbl_type
vtbl
{
[](
const
config_value
&
x
)
->
error
{
if
(
holds_alternative
<
T
>
(
x
))
return
none
;
return
make_error
(
pec
::
type_mismatch
);
},
nullptr
};
return
{
category
,
name
,
description
,
std
::
is_same
<
T
,
bool
>::
value
,
vtbl
};
}
/// Creates a config option that synchronizes with `storage`.
template
<
class
T
>
config_option
make_config_option
(
T
&
storage
,
const
char
*
category
,
const
char
*
name
,
const
char
*
description
)
{
config_option
::
vtbl_type
vtbl
{
[](
const
config_value
&
x
)
->
error
{
if
(
holds_alternative
<
T
>
(
x
))
return
none
;
return
make_error
(
pec
::
type_mismatch
);
},
[](
void
*
ptr
,
const
config_value
&
x
)
{
*
static_cast
<
T
*>
(
ptr
)
=
get
<
T
>
(
x
);
}
};
return
{
category
,
name
,
description
,
std
::
is_same
<
T
,
bool
>::
value
,
vtbl
,
&
storage
};
}
}
// namespace caf
libcaf_core/caf/
detail/parser/
ec.hpp
→
libcaf_core/caf/
p
ec.hpp
View file @
64324ccf
...
...
@@ -23,14 +23,14 @@
#include "caf/fwd.hpp"
namespace
caf
{
namespace
detail
{
namespace
parser
{
enum
class
ec
:
uint8_t
{
/// PEC stands for "Parser Error Code". This enum contains error codes used by
/// various CAF parsers.
enum
class
pec
:
uint8_t
{
/// Not-an-error.
success
,
success
=
0
,
/// Parser succeeded but found trailing character(s).
trailing_character
,
trailing_character
=
1
,
/// Parser stopped after reaching the end while still expecting input.
unexpected_eof
,
/// Parser stopped after reading an unexpected character.
...
...
@@ -38,7 +38,7 @@ enum class ec : uint8_t {
/// Parsed integer exceeds the number of available bits of a `timespan`.
timespan_overflow
,
/// Tried constructing a `timespan` with from a floating point number.
fractional_timespan
,
fractional_timespan
=
5
,
/// Too many characters for an atom.
too_many_characters
,
/// Unrecognized character after escaping `\`.
...
...
@@ -48,19 +48,27 @@ enum class ec : uint8_t {
/// Parsed positive integer exceeds the number of available bits.
integer_overflow
,
/// Parsed negative integer exceeds the number of available bits.
integer_underflow
,
integer_underflow
=
10
,
/// Exponent of parsed double is less than the minimum supported exponent.
exponent_underflow
,
/// Exponent of parsed double is greater than the maximum supported exponent.
exponent_overflow
,
/// Parsed type does not match the expected type.
type_mismatch
,
/// Stopped at an unrecognized option name.
not_an_option
,
/// Stopped at an unparseable argument.
illegal_argument
=
15
,
/// Stopped because an argument was omitted.
missing_argument
,
/// Stopped because the key of a category was taken.
illegal_category
,
};
error
make_error
(
ec
code
);
error
make_error
(
p
ec
code
);
const
char
*
to_string
(
ec
x
);
error
make_error
(
pec
code
,
size_t
line
,
size_t
column
);
const
char
*
to_string
(
pec
x
);
}
// namespace parser
}
// namespace detail
}
// namespace caf
libcaf_core/caf/sec.hpp
View file @
64324ccf
...
...
@@ -27,8 +27,8 @@
namespace
caf
{
/// SEC stands for "System Error Code". This enum contains
///
error codes used internally by CAF
.
/// SEC stands for "System Error Code". This enum contains
error codes for
///
::actor_system and its modules
.
enum
class
sec
:
uint8_t
{
/// No error.
none
=
0
,
...
...
libcaf_core/src/actor_system_config.cpp
View file @
64324ccf
This diff is collapsed.
Click to expand it.
libcaf_core/src/config_option.cpp
View file @
64324ccf
...
...
@@ -20,6 +20,28 @@
#include <iostream>
#include "caf/config.hpp"
#include "caf/error.hpp"
using
std
::
move
;
using
std
::
string
;
namespace
{
string
get_long_name
(
const
char
*
name
)
{
auto
i
=
strchr
(
name
,
','
);
return
i
!=
nullptr
?
string
{
name
,
i
}
:
string
{
name
};
}
string
get_short_names
(
const
char
*
name
)
{
auto
substr
=
strchr
(
name
,
','
);
if
(
substr
!=
nullptr
)
return
++
substr
;
return
string
{};
}
}
// namespace <anonymous>
namespace
caf
{
const
char
*
type_name_visitor_tbl
[]
{
...
...
@@ -39,49 +61,36 @@ const char* type_name_visitor_tbl[] {
"a duration"
};
config_option
::
config_option
(
const
char
*
cat
,
const
char
*
nm
,
const
char
*
expl
)
:
category_
(
cat
),
name_
(
nm
),
explanation_
(
expl
),
short_name_
(
'\0'
)
{
auto
last
=
name_
.
end
();
auto
comma
=
std
::
find
(
name_
.
begin
(),
last
,
','
);
if
(
comma
!=
last
)
{
auto
i
=
comma
;
++
i
;
if
(
i
!=
last
)
short_name_
=
*
i
;
name_
.
erase
(
comma
,
last
);
}
config_option
::
config_option
(
string
category
,
const
char
*
name
,
string
description
,
bool
is_flag
,
const
vtbl_type
&
vtbl
,
void
*
value
)
:
category_
(
move
(
category
)),
long_name_
(
get_long_name
(
name
)),
short_names_
(
get_short_names
(
name
)),
description_
(
move
(
description
)),
is_flag_
(
is_flag
),
vtbl_
(
vtbl
),
value_
(
value
)
{
// nop
}
config_option
::~
config_option
()
{
// nop
string
config_option
::
full_name
()
const
{
std
::
string
result
=
category
();
result
+=
'.'
;
result
+=
long_name_
;
return
result
;
}
std
::
string
config_option
::
full_name
()
const
{
std
::
string
res
=
category
();
res
+=
'.'
;
auto
name_begin
=
name
();
const
char
*
name_end
=
strchr
(
name
(),
','
);
if
(
name_end
!=
nullptr
)
res
.
insert
(
res
.
end
(),
name_begin
,
name_end
);
else
res
+=
name
();
return
res
;
error
config_option
::
check
(
const
config_value
&
x
)
const
{
CAF_ASSERT
(
vtbl_
.
check
!=
nullptr
);
return
vtbl_
.
check
(
x
);
}
void
config_option
::
report_type_error
(
size_t
ln
,
config_value
&
x
,
const
char
*
expected
,
optional
<
std
::
ostream
&>
out
)
{
if
(
!
out
)
return
;
/*
type_name_visitor tnv;
*out << "error in line " << ln << ": expected "
<< expected << " found "
<< visit(tnv, x) << '\n';
*/
void
config_option
::
store
(
const
config_value
&
x
)
const
{
if
(
value_
!=
nullptr
)
{
CAF_ASSERT
(
vtbl_
.
store
!=
nullptr
);
vtbl_
.
store
(
value_
,
x
);
}
}
}
// namespace caf
libcaf_core/src/config_option_set.cpp
0 → 100644
View file @
64324ccf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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. *
******************************************************************************/
#include "caf/config_option_set.hpp"
#include "caf/config_option.hpp"
#include "caf/config_value.hpp"
#include "caf/detail/algorithms.hpp"
#include "caf/expected.hpp"
using
std
::
string
;
namespace
caf
{
config_option_set
::
config_option_set
()
{
// nop
}
auto
config_option_set
::
parse
(
config_map
&
config
,
argument_iterator
first
,
argument_iterator
last
)
const
->
std
::
pair
<
pec
,
argument_iterator
>
{
// Sanity check.
if
(
first
==
last
)
return
{
pec
::
success
,
last
};
// Parses an argument.
using
iter
=
string
::
const_iterator
;
auto
consume
=
[
&
](
const
config_option
&
opt
,
iter
arg_begin
,
iter
arg_end
)
{
// Extract option name and category.
auto
opt_name
=
opt
.
long_name
();
string
opt_ctg
=
opt
.
category
();
// Try inserting a new submap into the config or fill existing one.
auto
&
submap
=
config
[
opt_ctg
];
// Flags only consume the current element.
if
(
opt
.
is_flag
())
{
if
(
arg_begin
!=
arg_end
)
return
pec
::
illegal_argument
;
config_value
cfg_true
{
true
};
opt
.
store
(
cfg_true
);
submap
[
opt_name
]
=
cfg_true
;
}
else
{
if
(
arg_begin
==
arg_end
)
return
pec
::
missing_argument
;
auto
val
=
config_value
::
parse
(
arg_begin
,
arg_end
);
if
(
!
val
)
return
pec
::
illegal_argument
;
if
(
opt
.
check
(
*
val
)
!=
none
)
return
pec
::
type_mismatch
;
opt
.
store
(
*
val
);
submap
[
opt_name
]
=
std
::
move
(
*
val
);
}
return
pec
::
success
;
};
// We loop over the first N-1 values, because we always consider two
// arguments at once.
for
(
auto
i
=
first
;
i
!=
last
;)
{
if
(
i
->
size
()
<
2
)
return
{
pec
::
not_an_option
,
i
};
if
(
*
i
==
"--"
)
return
{
pec
::
success
,
std
::
next
(
first
)};
if
(
i
->
compare
(
0
,
2
,
"--"
)
==
0
)
{
// Long options use the syntax "--<name>=<value>" and consume only a
// single argument.
auto
assign_op
=
i
->
find
(
'='
);
//std::find(i->begin(), i->end(), '=');
auto
name
=
i
->
substr
(
2
,
assign_op
-
2
);
auto
opt
=
cli_long_name_lookup
(
name
);
if
(
opt
==
nullptr
)
return
{
pec
::
not_an_option
,
i
};
auto
code
=
consume
(
*
opt
,
i
->
begin
()
+
assign_op
+
1
,
i
->
end
());
if
(
code
!=
pec
::
success
)
return
{
code
,
i
};
++
i
;
}
else
if
(
i
->
front
()
==
'-'
)
{
// Short options have three possibilities.
auto
opt
=
cli_short_name_lookup
((
*
i
)[
1
]);
if
(
opt
==
nullptr
)
return
{
pec
::
not_an_option
,
i
};
if
(
opt
->
is_flag
())
{
// 1) "-f" for flags, consumes one argument
auto
code
=
consume
(
*
opt
,
i
->
begin
()
+
2
,
i
->
end
());
if
(
code
!=
pec
::
success
)
return
{
code
,
i
};
++
i
;
}
else
{
if
(
i
->
size
()
==
2
)
{
// 2) "-k <value>", consumes both arguments
auto
j
=
std
::
next
(
i
);
if
(
j
==
last
)
{
return
{
pec
::
missing_argument
,
j
};
}
auto
code
=
consume
(
*
opt
,
j
->
begin
(),
j
->
end
());
if
(
code
!=
pec
::
success
)
return
{
code
,
i
};
std
::
advance
(
i
,
2
);
}
else
{
// 3) "-k<value>" (no space), consumes one argument
auto
code
=
consume
(
*
opt
,
i
->
begin
()
+
2
,
i
->
end
());
if
(
code
!=
pec
::
success
)
return
{
code
,
i
};
++
i
;
}
}
}
else
{
// No leading '-' found on current position.
return
{
pec
::
not_an_option
,
i
};
}
}
return
{
pec
::
success
,
last
};
}
config_option_set
::
parse_result
config_option_set
::
parse
(
config_map
&
config
,
const
std
::
vector
<
string
>&
args
)
const
{
return
parse
(
config
,
args
.
begin
(),
args
.
end
());
}
config_option_set
::
option_pointer
config_option_set
::
cli_long_name_lookup
(
const
string
&
name
)
const
{
// We accept "caf#" prefixes for backward compatibility, but ignore them.
size_t
offset
=
name
.
compare
(
0
,
4
,
"caf#"
)
!=
0
?
0u
:
4u
;
// Extract category and long name.
string
category
;
string
long_name
;
auto
sep
=
name
.
find
(
'.'
,
offset
);
if
(
sep
==
string
::
npos
)
{
category
=
"global"
;
if
(
offset
==
0
)
long_name
=
name
;
else
long_name
=
name
.
substr
(
offset
);
}
else
{
category
=
name
.
substr
(
offset
,
sep
);
long_name
=
name
.
substr
(
sep
+
1
);
}
// Scan all options for a match.
return
detail
::
ptr_find_if
(
opts_
,
[
&
](
const
config_option
&
opt
)
{
return
opt
.
category
()
==
category
&&
opt
.
long_name
()
==
long_name
;
});
}
config_option_set
::
option_pointer
config_option_set
::
cli_short_name_lookup
(
char
short_name
)
const
{
return
detail
::
ptr_find_if
(
opts_
,
[
&
](
const
config_option
&
opt
)
{
return
opt
.
short_names
().
find
(
short_name
)
!=
string
::
npos
;
});
}
config_option_set
::
option_pointer
config_option_set
::
qualified_name_lookup
(
const
std
::
string
&
category
,
const
std
::
string
&
long_name
)
const
{
return
detail
::
ptr_find_if
(
opts_
,
[
&
](
const
config_option
&
opt
)
{
return
opt
.
category
()
==
category
&&
opt
.
long_name
()
==
long_name
;
});
}
config_option_set
::
option_pointer
config_option_set
::
qualified_name_lookup
(
const
std
::
string
&
name
)
const
{
auto
sep
=
name
.
find
(
'.'
);
if
(
sep
==
string
::
npos
)
return
nullptr
;
return
qualified_name_lookup
(
name
.
substr
(
0
,
sep
),
name
.
substr
(
sep
+
1
));
}
}
// namespace caf
libcaf_core/src/config_value.cpp
View file @
64324ccf
...
...
@@ -19,10 +19,11 @@
#include "caf/config_value.hpp"
#include "caf/detail/
parser/ec
.hpp"
#include "caf/detail/
ini_consumer
.hpp"
#include "caf/detail/parser/read_ini.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/expected.hpp"
#include "caf/pec.hpp"
namespace
caf
{
...
...
@@ -49,133 +50,24 @@ config_value::~config_value() {
// -- parsing ------------------------------------------------------------------
namespace
{
struct
abstract_consumer
{
virtual
~
abstract_consumer
()
{
// nop
}
template
<
class
T
>
void
value
(
T
&&
x
)
{
value_impl
(
config_value
{
std
::
forward
<
T
>
(
x
)});
}
virtual
void
value_impl
(
config_value
&&
x
)
=
0
;
};
struct
list_consumer
;
struct
map_consumer
:
abstract_consumer
{
using
map_type
=
config_value
::
dictionary
;
using
iterator
=
map_type
::
iterator
;
map_consumer
begin_map
()
{
return
{
this
};
}
void
end_map
()
{
parent
->
value_impl
(
config_value
{
std
::
move
(
xs
)});
}
list_consumer
begin_list
();
void
key
(
std
::
string
name
)
{
i
=
xs
.
emplace_hint
(
xs
.
end
(),
std
::
make_pair
(
std
::
move
(
name
),
config_value
{}));
}
void
value_impl
(
config_value
&&
x
)
override
{
i
->
second
=
std
::
move
(
x
);
}
map_consumer
(
abstract_consumer
*
ptr
)
:
i
(
xs
.
end
()),
parent
(
ptr
)
{
// nop
}
map_consumer
(
map_consumer
&&
other
)
:
xs
(
std
::
move
(
other
.
xs
)),
i
(
xs
.
end
()),
parent
(
other
.
parent
)
{
// nop
}
map_type
xs
;
iterator
i
;
abstract_consumer
*
parent
;
};
struct
list_consumer
:
abstract_consumer
{
void
end_list
()
{
parent
->
value_impl
(
config_value
{
std
::
move
(
xs
)});
}
map_consumer
begin_map
()
{
return
{
this
};
}
list_consumer
begin_list
()
{
return
{
this
};
}
void
value_impl
(
config_value
&&
x
)
override
{
xs
.
emplace_back
(
std
::
move
(
x
));
}
list_consumer
(
abstract_consumer
*
ptr
)
:
parent
(
ptr
)
{
// nop
}
list_consumer
(
list_consumer
&&
other
)
:
xs
(
std
::
move
(
other
.
xs
)),
parent
(
other
.
parent
)
{
// nop
}
config_value
::
list
xs
;
abstract_consumer
*
parent
;
};
list_consumer
map_consumer
::
begin_list
()
{
return
{
this
};
}
struct
consumer
:
abstract_consumer
{
config_value
result
;
map_consumer
begin_map
()
{
return
{
this
};
}
list_consumer
begin_list
()
{
return
{
this
};
}
void
value_impl
(
config_value
&&
x
)
override
{
result
=
std
::
move
(
x
);
}
};
}
// namespace <anonymous>
expected
<
config_value
>
config_value
::
parse
(
std
::
string
::
const_iterator
first
,
std
::
string
::
const_iterator
last
)
{
using
namespace
detail
;
auto
i
=
first
;
// Sanity check.
if
(
i
==
last
)
return
make_error
(
p
arser
::
ec
::
unexpected_eof
);
return
make_error
(
pec
::
unexpected_eof
);
// Skip to beginning of the argument.
while
(
isspace
(
*
i
))
if
(
++
i
==
last
)
return
make_error
(
p
arser
::
ec
::
unexpected_eof
);
return
make_error
(
pec
::
unexpected_eof
);
// Dispatch to parser.
parser
::
state
<
std
::
string
::
const_iterator
>
res
;
consumer
f
;
detail
::
ini_value_
consumer
f
;
res
.
i
=
i
;
res
.
e
=
last
;
parser
::
read_ini_value
(
res
,
f
);
if
(
res
.
code
==
detail
::
parser
::
ec
::
success
)
if
(
res
.
code
==
p
ec
::
success
)
return
std
::
move
(
f
.
result
);
// Assume an unescaped string unless the first character clearly indicates
// otherwise.
...
...
libcaf_core/src/ini_consumer.cpp
0 → 100644
View file @
64324ccf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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. *
******************************************************************************/
#include "caf/detail/ini_consumer.hpp"
#include "caf/pec.hpp"
namespace
caf
{
namespace
detail
{
// -- abstract_ini_consumer ----------------------------------------------------
abstract_ini_consumer
::
abstract_ini_consumer
(
abstract_ini_consumer
*
parent
)
:
parent_
(
parent
)
{
// nop
}
abstract_ini_consumer
::~
abstract_ini_consumer
()
{
// nop
}
ini_map_consumer
abstract_ini_consumer
::
begin_map
()
{
return
{
this
};
}
ini_list_consumer
abstract_ini_consumer
::
begin_list
()
{
return
{
this
};
}
// -- map_consumer -------------------------------------------------------------
ini_map_consumer
::
ini_map_consumer
(
abstract_ini_consumer
*
parent
)
:
super
(
parent
),
i_
(
xs_
.
end
())
{
CAF_ASSERT
(
parent
!=
nullptr
);
}
ini_map_consumer
::
ini_map_consumer
(
ini_map_consumer
&&
other
)
:
super
(
other
.
parent
())
{
}
ini_map_consumer
::~
ini_map_consumer
()
{
// nop
}
void
ini_map_consumer
::
end_map
()
{
parent_
->
value_impl
(
config_value
{
std
::
move
(
xs_
)});
}
void
ini_map_consumer
::
key
(
std
::
string
name
)
{
i_
=
xs_
.
emplace
(
std
::
move
(
name
),
config_value
{}).
first
;
}
void
ini_map_consumer
::
value_impl
(
config_value
&&
x
)
{
CAF_ASSERT
(
i_
!=
xs_
.
end
());
i_
->
second
=
std
::
move
(
x
);
}
// -- ini_list_consumer --------------------------------------------------------
ini_list_consumer
::
ini_list_consumer
(
abstract_ini_consumer
*
parent
)
:
super
(
parent
)
{
CAF_ASSERT
(
parent
!=
nullptr
);
}
ini_list_consumer
::
ini_list_consumer
(
ini_list_consumer
&&
other
)
:
super
(
other
.
parent
()),
xs_
(
std
::
move
(
other
.
xs_
))
{
// nop
}
void
ini_list_consumer
::
end_list
()
{
parent_
->
value_impl
(
config_value
{
std
::
move
(
xs_
)});
}
void
ini_list_consumer
::
value_impl
(
config_value
&&
x
)
{
xs_
.
emplace_back
(
std
::
move
(
x
));
}
// -- ini_value_consumer -------------------------------------------------------
ini_value_consumer
::
ini_value_consumer
(
abstract_ini_consumer
*
parent
)
:
super
(
parent
)
{
// nop
}
void
ini_value_consumer
::
value_impl
(
config_value
&&
x
)
{
result
=
std
::
move
(
x
);
}
// -- ini_category_consumer ----------------------------------------------------
ini_category_consumer
::
ini_category_consumer
(
ini_consumer
*
parent
,
std
::
string
category
)
:
super
(
parent
),
category_
(
std
::
move
(
category
))
{
CAF_ASSERT
(
parent
!=
nullptr
);
}
void
ini_category_consumer
::
end_map
()
{
parent_
->
value_impl
(
config_value
{
std
::
move
(
xs_
)});
}
void
ini_category_consumer
::
key
(
std
::
string
name
)
{
current_key
=
std
::
move
(
name
);
}
void
ini_category_consumer
::
value_impl
(
config_value
&&
x
)
{
// See whether there's an config_option associated to this category and key.
auto
opt
=
dparent
()
->
options_
.
qualified_name_lookup
(
category_
,
current_key
);
if
(
opt
==
nullptr
)
{
// Simply store in config if no option was found.
xs_
.
emplace
(
std
::
move
(
current_key
),
std
::
move
(
x
));
}
else
{
// Perform a type check to see whether this is a valid input.
if
(
opt
->
check
(
x
)
==
none
)
{
opt
->
store
(
x
);
xs_
.
emplace
(
std
::
move
(
current_key
),
std
::
move
(
x
));
}
else
{
dparent
()
->
warnings_
.
emplace_back
(
make_error
(
pec
::
type_mismatch
));
}
}
}
ini_consumer
*
ini_category_consumer
::
dparent
()
{
// Safe, because our constructor only accepts ini_consumer parents.
return
static_cast
<
ini_consumer
*>
(
parent
());
}
// -- ini_consumer -------------------------------------------------------------
ini_consumer
::
ini_consumer
(
config_option_set
&
options
,
config_map
&
cfg
)
:
options_
(
options
),
cfg_
(
cfg
)
{
// nop
}
ini_category_consumer
ini_consumer
::
begin_map
()
{
return
{
this
,
current_key
};
}
void
ini_consumer
::
key
(
std
::
string
name
)
{
current_key
=
std
::
move
(
name
);
}
void
ini_consumer
::
value_impl
(
config_value
&&
x
)
{
auto
dict
=
get_if
<
config_value
::
dictionary
>
(
&
x
);
if
(
dict
!=
nullptr
&&
!
dict
->
empty
())
cfg_
.
emplace
(
std
::
move
(
current_key
),
std
::
move
(
*
dict
));
}
}
// namespace detail
}
// namespace caf
libcaf_core/src/ec.cpp
→
libcaf_core/src/
p
ec.cpp
View file @
64324ccf
...
...
@@ -16,9 +16,10 @@
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/
detail/parser/
ec.hpp"
#include "caf/
p
ec.hpp"
#include "caf/error.hpp"
#include "caf/make_message.hpp"
namespace
{
...
...
@@ -37,22 +38,28 @@ constexpr const char* tbl[] = {
"exponent_underflow"
,
"exponent_overflow"
,
"type_mismatch"
,
"not_an_option"
,
"illegal_argument"
,
"missing_argument"
,
"illegal_category"
,
};
}
// namespace <anonymous>
namespace
caf
{
namespace
detail
{
namespace
parser
{
error
make_error
(
ec
code
)
{
error
make_error
(
p
ec
code
)
{
return
{
static_cast
<
uint8_t
>
(
code
),
atom
(
"parser"
)};
}
const
char
*
to_string
(
ec
x
)
{
error
make_error
(
pec
code
,
size_t
line
,
size_t
column
)
{
return
{
static_cast
<
uint8_t
>
(
code
),
atom
(
"parser"
),
make_message
(
static_cast
<
uint32_t
>
(
line
),
static_cast
<
uint32_t
>
(
column
))};
}
const
char
*
to_string
(
pec
x
)
{
return
tbl
[
static_cast
<
uint8_t
>
(
x
)];
}
}
// namespace parser
}
// namespace detail
}
// namespace caf
libcaf_core/test/config_option.cpp
View file @
64324ccf
...
...
@@ -16,23 +16,12 @@
* 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
#pragma clang diagnostic ignored "-Wsign-conversion"
#pragma clang diagnostic ignored "-Wfloat-equal"
#pragma clang diagnostic ignored "-Wconstant-conversion"
#elif defined(CAF_GCC)
#pragma GCC diagnostic ignored "-Woverflow"
#endif
using
namespace
caf
;
using
std
::
string
;
...
...
@@ -42,7 +31,6 @@ 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
int64_t
overflow
()
{
...
...
@@ -55,36 +43,39 @@ constexpr int64_t underflow() {
}
template
<
class
T
>
optional
<
T
>
read
(
config_value
test_value
)
{
T
output_value
{};
auto
co
=
make_config_option
(
output_value
,
category
,
name
,
explanation
);
auto
f
=
co
->
to_sink
();
if
(
f
(
line
,
test_value
,
none
))
return
output_value
;
optional
<
T
>
read
(
const
std
::
string
&
arg
)
{
auto
co
=
make_config_option
<
T
>
(
category
,
name
,
explanation
);
auto
res
=
config_value
::
parse
(
arg
);
if
(
res
&&
holds_alternative
<
T
>
(
*
res
))
{
CAF_CHECK_EQUAL
(
co
.
check
(
*
res
),
none
);
return
get
<
T
>
(
*
res
);
}
return
none
;
}
// Unsigned integers.
template
<
class
T
>
void
check_integer_options
(
std
::
true_type
)
{
using
std
::
to_string
;
// Run tests for positive integers.
T
xzero
=
0
;
T
xmax
=
std
::
numeric_limits
<
T
>::
max
();
CAF_CHECK_EQUAL
(
read
<
T
>
(
config_value
{
xzero
}
),
xzero
);
CAF_CHECK_EQUAL
(
read
<
T
>
(
config_value
{
xmax
}
),
xmax
);
CAF_CHECK_EQUAL
(
read
<
T
>
(
config_value
{
overflow
<
T
>
()}
),
none
);
CAF_CHECK_EQUAL
(
read
<
T
>
(
to_string
(
xzero
)
),
xzero
);
CAF_CHECK_EQUAL
(
read
<
T
>
(
to_string
(
xmax
)
),
xmax
);
CAF_CHECK_EQUAL
(
read
<
T
>
(
to_string
(
overflow
<
T
>
())
),
none
);
}
// Signed integers.
template
<
class
T
>
void
check_integer_options
(
std
::
false_type
)
{
using
std
::
to_string
;
// Run tests for positive integers.
std
::
true_type
tk
;
check_integer_options
<
T
>
(
tk
);
// Run tests for negative integers.
auto
xmin
=
std
::
numeric_limits
<
T
>::
min
();
CAF_CHECK_EQUAL
(
read
<
T
>
(
config_value
{
xmin
}
),
xmin
);
CAF_CHECK_EQUAL
(
read
<
T
>
(
config_value
{
underflow
<
T
>
()}
),
none
);
CAF_CHECK_EQUAL
(
read
<
T
>
(
to_string
(
xmin
)
),
xmin
);
CAF_CHECK_EQUAL
(
read
<
T
>
(
to_string
(
underflow
<
T
>
())
),
none
);
}
// only works with an integral types and double
...
...
@@ -104,10 +95,10 @@ T unbox(optional<T> x) {
}
// namespace <anonymous>
CAF_TEST
(
type_bool
)
{
CAF_CHECK_EQUAL
(
read
<
bool
>
(
config_value
{
true
}
),
true
);
CAF_CHECK_EQUAL
(
read
<
bool
>
(
config_value
{
false
}
),
false
);
CAF_CHECK_EQUAL
(
read
<
bool
>
(
config_value
{
0
}
),
none
);
CAF_CHECK_EQUAL
(
read
<
bool
>
(
config_value
{
1
}
),
none
);
CAF_CHECK_EQUAL
(
read
<
bool
>
(
"true"
),
true
);
CAF_CHECK_EQUAL
(
read
<
bool
>
(
"false"
),
false
);
CAF_CHECK_EQUAL
(
read
<
bool
>
(
"0"
),
none
);
CAF_CHECK_EQUAL
(
read
<
bool
>
(
"1"
),
none
);
}
CAF_TEST
(
type
int8_t
)
{
...
...
@@ -135,66 +126,41 @@ CAF_TEST(type uint32_t) {
}
CAF_TEST
(
type
uint64_t
)
{
CAF_CHECK_EQUAL
(
unbox
(
read
<
uint64_t
>
(
config_value
{
0
}
)),
0u
);
CAF_CHECK_EQUAL
(
read
<
uint64_t
>
(
config_value
{
-
1
}
),
none
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
uint64_t
>
(
"0"
)),
0u
);
CAF_CHECK_EQUAL
(
read
<
uint64_t
>
(
"-1"
),
none
);
}
CAF_TEST
(
type
int64_t
)
{
CAF_CHECK_EQUAL
(
unbox
(
read
<
int64_t
>
(
config_value
{
-
1
}
)),
-
1
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
int64_t
>
(
config_value
{
0
}
)),
0
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
int64_t
>
(
config_value
{
1
}
)),
1
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
int64_t
>
(
"-1"
)),
-
1
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
int64_t
>
(
"0"
)),
0
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
int64_t
>
(
"1"
)),
1
);
}
CAF_TEST
(
type
float
)
{
CAF_CHECK_EQUAL
(
unbox
(
read
<
float
>
(
config_value
{
-
1.0
}
)),
-
1.0
f
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
float
>
(
config_value
{
-
0.1
}
)),
-
0.1
f
);
CAF_CHECK_EQUAL
(
read
<
float
>
(
config_value
{
0
}
),
none
);
CAF_CHECK_EQUAL
(
read
<
float
>
(
config_value
{
"0.1"
}
),
none
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
float
>
(
"-1.0"
)),
-
1.0
f
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
float
>
(
"-0.1"
)),
-
0.1
f
);
CAF_CHECK_EQUAL
(
read
<
float
>
(
"0"
),
none
);
CAF_CHECK_EQUAL
(
read
<
float
>
(
"
\"
0.1
\"
"
),
none
);
}
CAF_TEST
(
type
double
)
{
CAF_CHECK_EQUAL
(
unbox
(
read
<
double
>
(
config_value
{
-
1.0
}
)),
-
1.0
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
double
>
(
config_value
{
-
0.1
}
)),
-
0.1
);
CAF_CHECK_EQUAL
(
read
<
double
>
(
config_value
{
0
}
),
none
);
CAF_CHECK_EQUAL
(
read
<
double
>
(
config_value
{
"0.1"
}
),
none
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
double
>
(
"-1.0"
)),
-
1.0
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
double
>
(
"-0.1"
)),
-
0.1
);
CAF_CHECK_EQUAL
(
read
<
double
>
(
"0"
),
none
);
CAF_CHECK_EQUAL
(
read
<
double
>
(
"
\"
0.1
\"
"
),
none
);
}
CAF_TEST
(
type
string
)
{
CAF_CHECK_EQUAL
(
unbox
(
read
<
string
>
(
config_value
{
"foo"
})),
"foo"
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
string
>
(
"
\"
foo
\"
"
)),
"foo"
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
string
>
(
"foo"
)),
"foo"
);
}
CAF_TEST
(
type
atom
)
{
auto
foo
=
atom
(
"foo"
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
atom_value
>
(
config_value
{
foo
})),
foo
);
CAF_CHECK_EQUAL
(
read
<
atom_value
>
(
config_value
{
"bar"
}),
none
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
atom_value
>
(
"'foo'"
)),
atom
(
"foo"
));
CAF_CHECK_EQUAL
(
read
<
atom_value
>
(
"bar"
),
none
);
}
CAF_TEST
(
type
timespan
)
{
timespan
dur
{
500
};
CAF_CHECK_EQUAL
(
unbox
(
read
<
timespan
>
(
config_value
{
dur
})),
dur
);
}
template
<
class
T
>
std
::
string
name_of
()
{
T
x
{};
config_option
::
type_name_visitor
v
;
return
v
(
x
);
}
CAF_TEST
(
type_names
)
{
CAF_CHECK_EQUAL
((
name_of
<
std
::
map
<
int
,
int
>>
()),
"a dictionary"
);
CAF_CHECK_EQUAL
(
name_of
<
atom_value
>
(),
"an atom_value"
);
CAF_CHECK_EQUAL
(
name_of
<
bool
>
(),
"a boolean"
);
CAF_CHECK_EQUAL
(
name_of
<
double
>
(),
"a double"
);
CAF_CHECK_EQUAL
(
name_of
<
float
>
(),
"a float"
);
CAF_CHECK_EQUAL
(
name_of
<
int16_t
>
(),
"a 16-bit integer"
);
CAF_CHECK_EQUAL
(
name_of
<
int32_t
>
(),
"a 32-bit integer"
);
CAF_CHECK_EQUAL
(
name_of
<
int64_t
>
(),
"a 64-bit integer"
);
CAF_CHECK_EQUAL
(
name_of
<
int8_t
>
(),
"an 8-bit integer"
);
CAF_CHECK_EQUAL
(
name_of
<
std
::
vector
<
int
>>
(),
"a list"
);
CAF_CHECK_EQUAL
(
name_of
<
string
>
(),
"a string"
);
CAF_CHECK_EQUAL
(
name_of
<
uint16_t
>
(),
"a 16-bit unsigned integer"
);
CAF_CHECK_EQUAL
(
name_of
<
uint32_t
>
(),
"a 32-bit unsigned integer"
);
CAF_CHECK_EQUAL
(
name_of
<
uint64_t
>
(),
"a 64-bit unsigned integer"
);
CAF_CHECK_EQUAL
(
name_of
<
uint8_t
>
(),
"an 8-bit unsigned integer"
);
CAF_CHECK_EQUAL
(
unbox
(
read
<
timespan
>
(
"500ns"
)),
dur
);
}
libcaf_core/test/config_option_set.cpp
0 → 100644
View file @
64324ccf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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. *
******************************************************************************/
#include <map>
#include <string>
#include <vector>
#include "caf/config.hpp"
#define CAF_SUITE config_option_set
#include "caf/test/dsl.hpp"
#include "caf/config_option_set.hpp"
using
std
::
string
;
using
std
::
vector
;
using
namespace
caf
;
namespace
{
struct
fixture
{
config_option_set
opts
;
};
}
// namespace <anonymous>
CAF_TEST_FIXTURE_SCOPE
(
config_option_set_tests
,
fixture
)
CAF_TEST
(
lookup
)
{
opts
.
add
<
int
>
(
"global"
,
"opt1,1"
,
"test option 1"
)
.
add
<
float
>
(
"test"
,
"opt2,2"
,
"test option 2"
)
.
add
<
bool
>
(
"test"
,
"flag,fl3"
,
"test flag"
);
CAF_CHECK_EQUAL
(
opts
.
size
(),
3u
);
CAF_MESSAGE
(
"lookup by long name"
);
CAF_CHECK_NOT_EQUAL
(
opts
.
cli_long_name_lookup
(
"opt1"
),
nullptr
);
CAF_CHECK_NOT_EQUAL
(
opts
.
cli_long_name_lookup
(
"global.opt1"
),
nullptr
);
CAF_CHECK_NOT_EQUAL
(
opts
.
cli_long_name_lookup
(
"test.opt2"
),
nullptr
);
CAF_CHECK_NOT_EQUAL
(
opts
.
cli_long_name_lookup
(
"test.flag"
),
nullptr
);
CAF_MESSAGE
(
"lookup by short name"
);
CAF_CHECK_NOT_EQUAL
(
opts
.
cli_short_name_lookup
(
'1'
),
nullptr
);
CAF_CHECK_NOT_EQUAL
(
opts
.
cli_short_name_lookup
(
'2'
),
nullptr
);
CAF_CHECK_NOT_EQUAL
(
opts
.
cli_short_name_lookup
(
'f'
),
nullptr
);
CAF_CHECK_NOT_EQUAL
(
opts
.
cli_short_name_lookup
(
'l'
),
nullptr
);
CAF_CHECK_NOT_EQUAL
(
opts
.
cli_short_name_lookup
(
'3'
),
nullptr
);
}
CAF_TEST
(
parse
with
ref
syncing
)
{
using
ls
=
vector
<
string
>
;
// list of strings
using
ds
=
std
::
map
<
string
,
string
>
;
// dictionary of strings
auto
foo_i
=
0
;
auto
foo_f
=
0.
f
;
auto
foo_b
=
false
;
auto
bar_s
=
string
{};
auto
bar_l
=
ls
{};
auto
bar_d
=
ds
{};
opts
.
add
<
int
>
(
foo_i
,
"foo"
,
"i,i"
,
""
)
.
add
<
float
>
(
foo_f
,
"foo"
,
"f,f"
,
""
)
.
add
<
bool
>
(
foo_b
,
"foo"
,
"b,b"
,
""
)
.
add
<
string
>
(
bar_s
,
"bar"
,
"s,s"
,
""
)
.
add
<
vector
<
string
>>
(
bar_l
,
"bar"
,
"l,l"
,
""
)
.
add
<
std
::
map
<
string
,
string
>>
(
bar_d
,
"bar"
,
"d,d"
,
""
);
std
::
map
<
std
::
string
,
config_value
::
dictionary
>
cfg
;
vector
<
string
>
args
{
"-i42"
,
"-f"
,
"1e12"
,
"-shello"
,
"--bar.l=[
\"
hello
\"
,
\"
world
\"
]"
,
"-d"
,
"{a=
\"
a
\"
,b=
\"
b
\"
}"
,
"-b"
};
CAF_MESSAGE
(
"parse arguments"
);
auto
res
=
opts
.
parse
(
cfg
,
args
);
CAF_CHECK_EQUAL
(
res
.
first
,
pec
::
success
);
if
(
res
.
second
!=
args
.
end
())
CAF_FAIL
(
"parser stopped at: "
<<
*
res
.
second
);
CAF_MESSAGE
(
"verify referenced values"
);
CAF_CHECK_EQUAL
(
foo_i
,
42
);
CAF_CHECK_EQUAL
(
foo_f
,
1e12
);
CAF_CHECK_EQUAL
(
foo_b
,
true
);
CAF_CHECK_EQUAL
(
bar_s
,
"hello"
);
CAF_CHECK_EQUAL
(
bar_l
,
ls
({
"hello"
,
"world"
}));
CAF_CHECK_EQUAL
(
bar_d
,
ds
({{
"a"
,
"a"
},
{
"b"
,
"b"
}}));
CAF_MESSAGE
(
"verify dictionary content"
);
CAF_CHECK_EQUAL
(
get
<
int
>
(
cfg
,
"foo.i"
),
42
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/config_value.cpp
View file @
64324ccf
...
...
@@ -28,8 +28,8 @@
#include "caf/atom.hpp"
#include "caf/deep_to_string.hpp"
#include "caf/detail/bounds_checker.hpp"
#include "caf/detail/parser/ec.hpp"
#include "caf/none.hpp"
#include "caf/pec.hpp"
#include "caf/variant.hpp"
using
namespace
std
;
...
...
@@ -236,11 +236,10 @@ CAF_TEST(unsuccessful parsing) {
CAF_FAIL
(
"assumed an error but got a result"
);
return
std
::
move
(
x
.
error
());
};
using
detail
::
parser
::
ec
;
CAF_CHECK_EQUAL
(
parse
(
"10msb"
),
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
parse
(
"10foo"
),
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
parse
(
"[1,"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
parse
(
"{a=,"
),
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
parse
(
"{a=1,"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
parse
(
"{a=1 b=2}"
),
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
parse
(
"10msb"
),
pec
::
trailing_character
);
CAF_CHECK_EQUAL
(
parse
(
"10foo"
),
pec
::
trailing_character
);
CAF_CHECK_EQUAL
(
parse
(
"[1,"
),
pec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
parse
(
"{a=,"
),
pec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
parse
(
"{a=1,"
),
pec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
parse
(
"{a=1 b=2}"
),
pec
::
unexpected_character
);
}
libcaf_core/test/ini_consumer.cpp
0 → 100644
View file @
64324ccf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 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. *
******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE ini_consumer
#include "caf/test/dsl.hpp"
#include "caf/detail/ini_consumer.hpp"
#include "caf/detail/parser/read_ini.hpp"
using
std
::
string
;
using
namespace
caf
;
// List-of-strings.
using
ls
=
std
::
vector
<
std
::
string
>
;
namespace
{
const
char
test_ini
[]
=
R"(
[global]
is_server=true
port=4242
nodes=["sun", "venus", ]
[logger]
file-name = "foobar.ini" ; our file name
[scheduler] ; more settings
timing = 2us ; using microsecond resolution
impl = 'foo';some atom
)"
;
struct
fixture
{
detail
::
parser
::
state
<
std
::
string
::
const_iterator
>
res
;
config_option_set
options
;
config_option_set
::
config_map
config
;
fixture
()
{
options
.
add
<
bool
>
(
"global"
,
"is_server"
)
.
add
<
uint16_t
>
(
"global"
,
"port"
)
.
add
<
ls
>
(
"global"
,
"nodes"
)
.
add
<
string
>
(
"logger"
,
"file-name"
)
.
add
<
int
>
(
"scheduler"
,
"padding"
)
.
add
<
timespan
>
(
"scheduler"
,
"timing"
)
.
add
<
atom_value
>
(
"scheduler"
,
"impl"
);
}
};
}
// namespace <anonymous>
CAF_TEST_FIXTURE_SCOPE
(
ini_consumer_tests
,
fixture
)
CAF_TEST
(
ini_value_consumer
)
{
std
::
string
str
=
R"("hello world")"
;
detail
::
ini_value_consumer
consumer
;
res
.
i
=
str
.
begin
();
res
.
e
=
str
.
end
();
detail
::
parser
::
read_ini_value
(
res
,
consumer
);
CAF_CHECK_EQUAL
(
res
.
code
,
pec
::
success
);
CAF_CHECK_EQUAL
(
get
<
string
>
(
consumer
.
result
),
"hello world"
);
}
CAF_TEST
(
ini_consumer
)
{
std
::
string
str
=
test_ini
;
detail
::
ini_consumer
consumer
{
options
,
config
};
res
.
i
=
str
.
begin
();
res
.
e
=
str
.
end
();
detail
::
parser
::
read_ini
(
res
,
consumer
);
CAF_CHECK_EQUAL
(
res
.
code
,
pec
::
success
);
CAF_CHECK_EQUAL
(
get
<
bool
>
(
config
,
"global.is_server"
),
true
);
CAF_CHECK_EQUAL
(
get
<
uint16_t
>
(
config
,
"global.port"
),
4242u
);
CAF_CHECK_EQUAL
(
get
<
ls
>
(
config
,
"global.nodes"
),
ls
({
"sun"
,
"venus"
}));
CAF_CHECK_EQUAL
(
get
<
string
>
(
config
,
"logger.file-name"
),
"foobar.ini"
);
CAF_CHECK_EQUAL
(
get
<
timespan
>
(
config
,
"scheduler.timing"
),
timespan
(
2000
));
CAF_CHECK_EQUAL
(
get
<
atom_value
>
(
config
,
"scheduler.impl"
),
atom
(
"foo"
));
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/read_atom.cpp
View file @
64324ccf
...
...
@@ -28,8 +28,6 @@
using
namespace
caf
;
using
detail
::
parser
::
ec
;
namespace
{
struct
atom_parser_consumer
{
...
...
@@ -39,7 +37,7 @@ struct atom_parser_consumer {
}
};
using
res_t
=
variant
<
ec
,
atom_value
>
;
using
res_t
=
variant
<
p
ec
,
atom_value
>
;
struct
atom_parser
{
res_t
operator
()(
std
::
string
str
)
{
...
...
@@ -48,7 +46,7 @@ struct atom_parser {
res
.
i
=
str
.
begin
();
res
.
e
=
str
.
end
();
detail
::
parser
::
read_atom
(
res
,
f
);
if
(
res
.
code
==
ec
::
success
)
if
(
res
.
code
==
p
ec
::
success
)
return
f
.
x
;
return
res
.
code
;
}
...
...
@@ -79,11 +77,11 @@ CAF_TEST(non-empty atom) {
}
CAF_TEST
(
invalid
atoms
)
{
CAF_CHECK_EQUAL
(
p
(
"'abc"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"'ab
\n
c'"
),
ec
::
unexpected_newline
);
CAF_CHECK_EQUAL
(
p
(
"abc"
),
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
p
(
"'abc' def"
),
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
p
(
"'12345678901'"
),
ec
::
too_many_characters
);
CAF_CHECK_EQUAL
(
p
(
"'abc"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"'ab
\n
c'"
),
p
ec
::
unexpected_newline
);
CAF_CHECK_EQUAL
(
p
(
"abc"
),
p
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
p
(
"'abc' def"
),
p
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
p
(
"'12345678901'"
),
p
ec
::
too_many_characters
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/read_bool.cpp
View file @
64324ccf
...
...
@@ -28,8 +28,6 @@
using
namespace
caf
;
using
detail
::
parser
::
ec
;
namespace
{
struct
bool_parser_consumer
{
...
...
@@ -39,7 +37,7 @@ struct bool_parser_consumer {
}
};
using
res_t
=
variant
<
ec
,
bool
>
;
using
res_t
=
variant
<
p
ec
,
bool
>
;
struct
bool_parser
{
res_t
operator
()(
std
::
string
str
)
{
...
...
@@ -48,7 +46,7 @@ struct bool_parser {
res
.
i
=
str
.
begin
();
res
.
e
=
str
.
end
();
detail
::
parser
::
read_bool
(
res
,
f
);
if
(
res
.
code
==
ec
::
success
)
if
(
res
.
code
==
p
ec
::
success
)
return
f
.
x
;
return
res
.
code
;
}
...
...
@@ -68,18 +66,18 @@ CAF_TEST(valid booleans) {
}
CAF_TEST
(
invalid
booleans
)
{
CAF_CHECK_EQUAL
(
p
(
""
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"t"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"tr"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"tru"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
" true"
),
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
p
(
"f"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"fa"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"fal"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"fals"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
" false"
),
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
p
(
"tr
\n
ue"
),
ec
::
unexpected_newline
);
CAF_CHECK_EQUAL
(
p
(
"trues"
),
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
p
(
""
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"t"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"tr"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"tru"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
" true"
),
p
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
p
(
"f"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"fa"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"fal"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"fals"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
" false"
),
p
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
p
(
"tr
\n
ue"
),
p
ec
::
unexpected_newline
);
CAF_CHECK_EQUAL
(
p
(
"trues"
),
p
ec
::
trailing_character
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
libcaf_core/test/read_ini.cpp
View file @
64324ccf
...
...
@@ -35,6 +35,10 @@ using log_type = std::vector<std::string>;
struct
test_consumer
{
log_type
log
;
test_consumer
()
=
default
;
test_consumer
(
const
test_consumer
&
)
=
delete
;
test_consumer
&
operator
=
(
const
test_consumer
&
)
=
delete
;
test_consumer
&
begin_map
()
{
log
.
emplace_back
(
"{"
);
return
*
this
;
...
...
@@ -83,7 +87,7 @@ struct fixture {
res
.
i
=
str
.
begin
();
res
.
e
=
str
.
end
();
detail
::
parser
::
read_ini
(
res
,
f
);
if
(
res
.
code
==
detail
::
parser
::
ec
::
success
!=
expect_success
)
if
(
res
.
code
==
p
ec
::
success
!=
expect_success
)
CAF_MESSAGE
(
"unexpected parser result state: "
<<
res
.
code
);
return
std
::
move
(
f
.
log
);
}
...
...
libcaf_core/test/read_number.cpp
View file @
64324ccf
...
...
@@ -28,8 +28,6 @@
using
namespace
caf
;
using
detail
::
parser
::
ec
;
namespace
{
struct
numbers_parser_consumer
{
...
...
@@ -43,7 +41,7 @@ struct numbers_parser_consumer {
};
struct
res_t
{
variant
<
ec
,
double
,
int64_t
>
val
;
variant
<
p
ec
,
double
,
int64_t
>
val
;
template
<
class
T
>
res_t
(
T
&&
x
)
:
val
(
std
::
forward
<
T
>
(
x
))
{
// nop
...
...
@@ -57,8 +55,8 @@ bool operator==(const res_t& x, const res_t& y) {
caf
::
test
::
equal_to
f
;
using
caf
::
get
;
using
caf
::
holds_alternative
;
if
(
holds_alternative
<
ec
>
(
x
.
val
))
return
f
(
get
<
ec
>
(
x
.
val
),
get
<
ec
>
(
y
.
val
));
if
(
holds_alternative
<
p
ec
>
(
x
.
val
))
return
f
(
get
<
pec
>
(
x
.
val
),
get
<
p
ec
>
(
y
.
val
));
if
(
holds_alternative
<
double
>
(
x
.
val
))
return
f
(
get
<
double
>
(
x
.
val
),
get
<
double
>
(
y
.
val
));
return
f
(
get
<
int64_t
>
(
x
.
val
),
get
<
int64_t
>
(
y
.
val
));
...
...
@@ -71,7 +69,7 @@ struct numbers_parser {
res
.
i
=
str
.
begin
();
res
.
e
=
str
.
end
();
detail
::
parser
::
read_number
(
res
,
f
);
if
(
res
.
code
==
ec
::
success
)
if
(
res
.
code
==
p
ec
::
success
)
return
f
.
x
;
return
res
.
code
;
}
...
...
@@ -126,7 +124,7 @@ CAF_TEST(octal numbers) {
CHECK_NUMBER
(
-
00
);
CHECK_NUMBER
(
-
0123
);
// invalid numbers
CAF_CHECK_EQUAL
(
p
(
"018"
),
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
p
(
"018"
),
p
ec
::
trailing_character
);
}
CAF_TEST
(
decimal
numbers
)
{
...
...
@@ -147,11 +145,11 @@ CAF_TEST(hexadecimal numbers) {
CHECK_NUMBER
(
-
0x123
);
CHECK_NUMBER
(
-
0xaf01
);
// invalid numbers
CAF_CHECK_EQUAL
(
p
(
"0xFG"
),
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
p
(
"0xFG"
),
p
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
p
(
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
),
ec
::
integer_overflow
);
p
ec
::
integer_overflow
);
CAF_CHECK_EQUAL
(
p
(
"-0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
),
ec
::
integer_underflow
);
p
ec
::
integer_underflow
);
}
CAF_TEST
(
floating
point
numbers
)
{
...
...
@@ -196,8 +194,8 @@ CAF_TEST(integer mantissa with negative exponent) {
CHECK_NUMBER
(
1e-5
);
CHECK_NUMBER
(
1e-6
);
// invalid numbers
CAF_CHECK_EQUAL
(
p
(
"-9.9999e-e511"
),
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
p
(
"-9.9999e-511"
),
ec
::
exponent_underflow
);
CAF_CHECK_EQUAL
(
p
(
"-9.9999e-e511"
),
p
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
p
(
"-9.9999e-511"
),
p
ec
::
exponent_underflow
);
}
CAF_TEST
(
fractional
mantissa
with
positive
exponent
)
{
...
...
libcaf_core/test/read_number_or_timespan.cpp
View file @
64324ccf
...
...
@@ -29,8 +29,6 @@
using
namespace
caf
;
using
namespace
std
::
chrono
;
using
detail
::
parser
::
ec
;
namespace
{
struct
number_or_timespan_parser_consumer
{
...
...
@@ -42,7 +40,7 @@ struct number_or_timespan_parser_consumer {
};
struct
res_t
{
variant
<
ec
,
double
,
int64_t
,
timespan
>
val
;
variant
<
p
ec
,
double
,
int64_t
,
timespan
>
val
;
template
<
class
T
>
res_t
(
T
&&
x
)
:
val
(
std
::
forward
<
T
>
(
x
))
{
// nop
...
...
@@ -60,8 +58,8 @@ bool operator==(const res_t& x, const res_t& y) {
caf
::
test
::
equal_to
f
;
using
caf
::
get
;
using
caf
::
holds_alternative
;
if
(
holds_alternative
<
ec
>
(
x
.
val
))
return
f
(
get
<
ec
>
(
x
.
val
),
get
<
ec
>
(
y
.
val
));
if
(
holds_alternative
<
p
ec
>
(
x
.
val
))
return
f
(
get
<
pec
>
(
x
.
val
),
get
<
p
ec
>
(
y
.
val
));
if
(
holds_alternative
<
double
>
(
x
.
val
))
return
f
(
get
<
double
>
(
x
.
val
),
get
<
double
>
(
y
.
val
));
if
(
holds_alternative
<
int64_t
>
(
x
.
val
))
...
...
@@ -76,7 +74,7 @@ struct number_or_timespan_parser {
res
.
i
=
str
.
begin
();
res
.
e
=
str
.
end
();
detail
::
parser
::
read_number_or_timespan
(
res
,
f
);
if
(
res
.
code
==
ec
::
success
)
if
(
res
.
code
==
p
ec
::
success
)
return
f
.
x
;
return
res
.
code
;
}
...
...
@@ -117,20 +115,20 @@ CAF_TEST(valid numbers and timespans) {
}
CAF_TEST
(
invalid
timespans
)
{
CAF_CHECK_EQUAL
(
p
(
"12.3s"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3n"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3ns"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3m"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3ms"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3n"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3ns"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3mi"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3min"
),
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"123ss"
),
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
p
(
"123m"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"123mi"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"123u"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"123n"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"12.3s"
),
p
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3n"
),
p
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3ns"
),
p
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3m"
),
p
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3ms"
),
p
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3n"
),
p
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3ns"
),
p
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3mi"
),
p
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"12.3min"
),
p
ec
::
fractional_timespan
);
CAF_CHECK_EQUAL
(
p
(
"123ss"
),
p
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
p
(
"123m"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"123mi"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"123u"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"123n"
),
p
ec
::
unexpected_eof
);
}
CAF_TEST_FIXTURE_SCOPE_END
()
...
...
libcaf_core/test/read_string.cpp
View file @
64324ccf
...
...
@@ -28,8 +28,6 @@
using
namespace
caf
;
using
detail
::
parser
::
ec
;
namespace
{
struct
string_parser_consumer
{
...
...
@@ -39,7 +37,7 @@ struct string_parser_consumer {
}
};
using
res_t
=
variant
<
ec
,
std
::
string
>
;
using
res_t
=
variant
<
p
ec
,
std
::
string
>
;
struct
string_parser
{
res_t
operator
()(
std
::
string
str
)
{
...
...
@@ -48,7 +46,7 @@ struct string_parser {
res
.
i
=
str
.
begin
();
res
.
e
=
str
.
end
();
detail
::
parser
::
read_string
(
res
,
f
);
if
(
res
.
code
==
ec
::
success
)
if
(
res
.
code
==
p
ec
::
success
)
return
f
.
x
;
return
res
.
code
;
}
...
...
@@ -93,11 +91,11 @@ CAF_TEST(string with escaped characters) {
}
CAF_TEST
(
invalid
strings
)
{
CAF_CHECK_EQUAL
(
p
(
R"("abc)"
),
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"
\"
ab
\n
c
\"
"
),
ec
::
unexpected_newline
);
CAF_CHECK_EQUAL
(
p
(
R"("foo \i bar")"
),
ec
::
illegal_escape_sequence
);
CAF_CHECK_EQUAL
(
p
(
R"(foo)"
),
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
p
(
R"("abc" def)"
),
ec
::
trailing_character
);
CAF_CHECK_EQUAL
(
p
(
R"("abc)"
),
p
ec
::
unexpected_eof
);
CAF_CHECK_EQUAL
(
p
(
"
\"
ab
\n
c
\"
"
),
p
ec
::
unexpected_newline
);
CAF_CHECK_EQUAL
(
p
(
R"("foo \i bar")"
),
p
ec
::
illegal_escape_sequence
);
CAF_CHECK_EQUAL
(
p
(
R"(foo)"
),
p
ec
::
unexpected_character
);
CAF_CHECK_EQUAL
(
p
(
R"("abc" def)"
),
p
ec
::
trailing_character
);
}
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