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
6a41eed0
Commit
6a41eed0
authored
Aug 05, 2019
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support [a.b] nesting and relax key name parsing
parent
04ba5ea6
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
105 additions
and
5 deletions
+105
-5
libcaf_core/caf/detail/parser/read_ini.hpp
libcaf_core/caf/detail/parser/read_ini.hpp
+49
-5
libcaf_core/test/read_ini.cpp
libcaf_core/test/read_ini.cpp
+56
-0
No files found.
libcaf_core/caf/detail/parser/read_ini.hpp
View file @
6a41eed0
...
...
@@ -201,8 +201,9 @@ template <class Iterator, class Sentinel, class Consumer>
void
read_ini_section
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&&
consumer
)
{
using
std
::
swap
;
std
::
string
tmp
;
auto
alnum
=
[](
char
x
)
{
return
isalnum
(
x
)
||
x
==
'_'
;
};
auto
alnum_or_dash
=
[](
char
x
)
{
return
isalnum
(
x
)
||
x
==
'
-'
||
x
==
'_
'
;
return
isalnum
(
x
)
||
x
==
'
_'
||
x
==
'-
'
;
};
auto
emit_key
=
[
&
]
{
std
::
string
key
;
...
...
@@ -211,14 +212,15 @@ void read_ini_section(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
};
auto
g
=
make_scope_guard
([
&
]
{
if
(
ps
.
code
<=
pec
::
trailing_character
)
consumer
.
end_map
();
consumer
.
end_map
();
});
// clang-format off
start
();
// 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
(
read_key_name
,
al
phanumeric_chars
,
tmp
=
ch
)
transition
(
read_key_name
,
al
num
,
tmp
=
ch
)
}
// Reads a key of a "key=value" line.
state
(
read_key_name
)
{
...
...
@@ -244,6 +246,44 @@ void read_ini_section(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
transition
(
init
,
'\n'
)
}
fin
();
// clang-format on
}
/// Reads a nested group, e.g., "[foo.bar]" would consume "[foo.]" in read_ini
/// and then delegate to this function for parsing "bar]".
template
<
class
Iterator
,
class
Sentinel
,
class
Consumer
>
void
read_nested_group
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&&
consumer
)
{
using
std
::
swap
;
std
::
string
key
;
auto
alnum
=
[](
char
x
)
{
return
isalnum
(
x
)
||
x
==
'_'
;
};
auto
alnum_or_dash
=
[](
char
x
)
{
return
isalnum
(
x
)
||
x
==
'_'
||
x
==
'-'
;
};
auto
begin_section
=
[
&
]()
->
decltype
(
consumer
.
begin_map
())
{
consumer
.
key
(
std
::
move
(
key
));
return
consumer
.
begin_map
();
};
auto
g
=
make_scope_guard
([
&
]
{
if
(
ps
.
code
<=
pec
::
trailing_character
)
consumer
.
end_map
();
});
// clang-format off
start
();
// Scanning for first section.
state
(
init
)
{
epsilon
(
read_sub_section
,
alnum
)
}
// Read the sub section key after reading an '[xxx.'.
state
(
read_sub_section
)
{
transition
(
read_sub_section
,
alnum_or_dash
,
key
+=
ch
)
fsm_transition
(
read_nested_group
(
ps
,
begin_section
()),
done
,
'.'
)
fsm_transition
(
read_ini_section
(
ps
,
begin_section
()),
done
,
']'
)
}
term_state
(
done
)
{
// nop
}
fin
();
// clang-format on
}
/// Reads an INI formatted input.
...
...
@@ -251,8 +291,9 @@ template <class Iterator, class Sentinel, class Consumer>
void
read_ini
(
state
<
Iterator
,
Sentinel
>&
ps
,
Consumer
&&
consumer
)
{
using
std
::
swap
;
std
::
string
tmp
{
"global"
};
auto
alnum
=
[](
char
x
)
{
return
isalnum
(
x
)
||
x
==
'_'
;
};
auto
alnum_or_dash
=
[](
char
x
)
{
return
isalnum
(
x
)
||
x
==
'
-'
||
x
==
'_
'
;
return
isalnum
(
x
)
||
x
==
'
_'
||
x
==
'-
'
;
};
auto
begin_section
=
[
&
]()
->
decltype
(
consumer
.
begin_map
())
{
std
::
string
key
;
...
...
@@ -260,6 +301,7 @@ void read_ini(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
consumer
.
key
(
std
::
move
(
key
));
return
consumer
.
begin_map
();
};
// clang-format off
start
();
// Scanning for first section.
term_state
(
init
)
{
...
...
@@ -271,11 +313,12 @@ void read_ini(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
// Read the section key after reading an '['.
state
(
start_section
)
{
transition
(
start_section
,
"
\t
"
)
transition
(
read_section_name
,
al
phabetic_chars
,
tmp
=
ch
)
transition
(
read_section_name
,
al
num
,
tmp
=
ch
)
}
// Reads a section name such as "[foo]".
state
(
read_section_name
)
{
transition
(
read_section_name
,
alnum_or_dash
,
tmp
+=
ch
)
fsm_transition
(
read_nested_group
(
ps
,
begin_section
()),
return_to_global
,
'.'
)
epsilon
(
close_section
)
}
// Wait for the closing ']', preceded by any number of whitespaces.
...
...
@@ -287,6 +330,7 @@ void read_ini(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
epsilon
(
init
,
any_char
,
tmp
=
"global"
)
}
fin
();
// clang-format on
}
}
// namespace parser
...
...
libcaf_core/test/read_ini.cpp
View file @
6a41eed0
...
...
@@ -105,7 +105,12 @@ log_type make_log(Ts&&... xs) {
return
log_type
{
std
::
forward
<
Ts
>
(
xs
)...};
}
// Tests basic functionality.
const
char
*
ini0
=
R"(
[1group]
1value=321
[_foo]
_bar=11
[logger]
padding= 10
file-name = "foobar.ini" ; our file name
...
...
@@ -138,7 +143,18 @@ tcp://localhost:8080
>,<udp://remotehost?trust=false>]
)"
;
// clang-format off
const
auto
ini0_log
=
make_log
(
"key: 1group"
,
"{"
,
"key: 1value"
,
"value (integer): 321"
,
"}"
,
"key: _foo"
,
"{"
,
"key: _bar"
,
"value (integer): 11"
,
"}"
,
"key: logger"
,
"{"
,
"key: padding"
,
...
...
@@ -186,6 +202,45 @@ const auto ini0_log = make_log(
"]"
,
"}"
);
// clang-format on
// Tests nested parameters.
const
char
*
ini1
=
R"(
foo {
bar = {
value1 = 1
}
value2 = 2
}
[bar.foo]
value3 = 3
)"
;
// clang-format off
const
auto
ini1_log
=
make_log
(
"key: global"
,
"{"
,
"key: foo"
,
"{"
,
"key: bar"
,
"{"
,
"key: value1"
,
"value (integer): 1"
,
"}"
,
"key: value2"
,
"value (integer): 2"
,
"}"
,
"}"
,
"key: bar"
,
"{"
,
"key: foo"
,
"{"
,
"key: value3"
,
"value (integer): 3"
,
"}"
,
"}"
);
// clang-format on
}
// namespace <anonymous>
...
...
@@ -206,6 +261,7 @@ CAF_TEST(section with valid key-value pairs) {
CAF_CHECK_EQUAL
(
parse
(
" [ foo ] "
),
make_log
(
"key: foo"
,
"{"
,
"}"
));
CAF_CHECK_EQUAL
(
parse
(
"
\n
[a-b];foo
\n
;bar"
),
make_log
(
"key: a-b"
,
"{"
,
"}"
));
CAF_CHECK_EQUAL
(
parse
(
ini0
),
ini0_log
);
CAF_CHECK_EQUAL
(
parse
(
ini1
),
ini1_log
);
}
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