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
e8f069e8
Commit
e8f069e8
authored
Jun 09, 2018
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add parse function to config_value
parent
43da85a5
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
199 additions
and
0 deletions
+199
-0
libcaf_core/caf/config_value.hpp
libcaf_core/caf/config_value.hpp
+5
-0
libcaf_core/src/config_value.cpp
libcaf_core/src/config_value.cpp
+152
-0
libcaf_core/test/config_value.cpp
libcaf_core/test/config_value.cpp
+42
-0
No files found.
libcaf_core/caf/config_value.hpp
View file @
e8f069e8
...
...
@@ -98,6 +98,11 @@ public:
~
config_value
();
// -- parsing ----------------------------------------------------------------
/// Tries to parse a value from `str`.
static
expected
<
config_value
>
parse
(
const
std
::
string
&
str
);
// -- properties -------------------------------------------------------------
/// Converts the value to a list with one element. Does nothing if the value
...
...
libcaf_core/src/config_value.cpp
View file @
e8f069e8
...
...
@@ -19,7 +19,10 @@
#include "caf/config_value.hpp"
#include "caf/detail/parser/ec.hpp"
#include "caf/detail/parser/read_ini.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/expected.hpp"
namespace
caf
{
...
...
@@ -38,10 +41,159 @@ const char* type_names[] {
}
// namespace <anonymous>
// -- constructors, destructors, and assignment operators ----------------------
config_value
::~
config_value
()
{
// nop
}
// -- 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
(
const
std
::
string
&
str
)
{
using
namespace
detail
;
auto
i
=
str
.
begin
();
auto
e
=
str
.
end
();
// Sanity check.
if
(
i
==
e
)
return
make_error
(
parser
::
ec
::
unexpected_eof
);
// Skip to beginning of the argument.
while
(
isspace
(
*
i
))
if
(
++
i
==
e
)
return
make_error
(
parser
::
ec
::
unexpected_eof
);
// Dispatch to parser.
parser
::
state
<
std
::
string
::
const_iterator
>
res
;
consumer
f
;
res
.
i
=
i
;
res
.
e
=
e
;
parser
::
read_ini_value
(
res
,
f
);
if
(
res
.
code
==
detail
::
parser
::
ec
::
success
)
return
std
::
move
(
f
.
result
);
// Assume an unescaped string unless the first character clearly indicates
// otherwise.
switch
(
*
i
)
{
case
'['
:
case
'{'
:
case
'"'
:
case
'\''
:
return
make_error
(
res
.
code
);
default:
if
(
isdigit
(
*
i
))
return
make_error
(
res
.
code
);
return
config_value
{
str
};
}
}
// -- properties ---------------------------------------------------------------
void
config_value
::
convert_to_list
()
{
if
(
holds_alternative
<
list
>
(
data_
))
return
;
...
...
libcaf_core/test/config_value.cpp
View file @
e8f069e8
...
...
@@ -189,3 +189,45 @@ CAF_TEST(heterogeneous dictionary) {
string_list
nodes
{
"sun"
,
"venus"
,
"mercury"
,
"earth"
,
"mars"
};
CAF_CHECK_EQUAL
(
get
<
string_list
>
(
xs
,
"nodes.preload"
),
nodes
);
}
CAF_TEST
(
successful
parsing
)
{
auto
parse
=
[](
const
std
::
string
&
str
)
{
auto
x
=
config_value
::
parse
(
str
);
if
(
!
x
)
CAF_FAIL
(
"cannot parse"
<<
str
<<
": assumed a result but got an error"
);
return
std
::
move
(
*
x
);
};
using
di
=
std
::
map
<
string
,
int
>
;
// Dictionary-of-integers.
using
ls
=
std
::
vector
<
string
>
;
// List-of-strings.
using
li
=
std
::
vector
<
int
>
;
// List-of-integers.
using
lli
=
std
::
vector
<
li
>
;
// List-of-list-of-integers.
using
std
::
chrono
::
milliseconds
;
CAF_CHECK_EQUAL
(
get
<
int64_t
>
(
parse
(
"123"
)),
123
);
CAF_CHECK_EQUAL
(
get
<
int64_t
>
(
parse
(
"+123"
)),
123
);
CAF_CHECK_EQUAL
(
get
<
int64_t
>
(
parse
(
"-1"
)),
-
1
);
CAF_CHECK_EQUAL
(
get
<
double
>
(
parse
(
"1."
)),
1.
);
CAF_CHECK_EQUAL
(
get
<
atom_value
>
(
parse
(
"'abc'"
)),
atom
(
"abc"
));
CAF_CHECK_EQUAL
(
get
<
string
>
(
parse
(
"
\"
abc
\"
"
)),
"abc"
);
CAF_CHECK_EQUAL
(
get
<
string
>
(
parse
(
"abc"
)),
"abc"
);
CAF_CHECK_EQUAL
(
get
<
li
>
(
parse
(
"[1, 2, 3]"
)),
li
({
1
,
2
,
3
}));
CAF_CHECK_EQUAL
(
get
<
ls
>
(
parse
(
"[abc, def, ghi]"
)),
ls
({
"abc"
,
"def"
,
"ghi"
}));
CAF_CHECK_EQUAL
(
get
<
lli
>
(
parse
(
"[[1, 2], [3]]"
)),
lli
({
li
{
1
,
2
},
li
{
3
}}));
CAF_CHECK_EQUAL
(
get
<
timespan
>
(
parse
(
"10ms"
)),
milliseconds
(
10
));
CAF_CHECK_EQUAL
(
get
<
di
>
(
parse
(
"{a=1,b=2}"
)),
di
({{
"a"
,
1
},
{
"b"
,
2
}}));
}
CAF_TEST
(
unsuccessful
parsing
)
{
auto
parse
=
[](
const
std
::
string
&
str
)
{
auto
x
=
config_value
::
parse
(
str
);
if
(
x
)
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
);
}
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