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
e8444968
Commit
e8444968
authored
Oct 12, 2015
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add support for binary literals in INI parser
parent
841d5d89
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
61 additions
and
58 deletions
+61
-58
libcaf_core/src/parse_ini.cpp
libcaf_core/src/parse_ini.cpp
+54
-54
libcaf_core/test/parse_ini.cpp
libcaf_core/test/parse_ini.cpp
+7
-4
No files found.
libcaf_core/src/parse_ini.cpp
View file @
e8444968
...
@@ -24,16 +24,23 @@
...
@@ -24,16 +24,23 @@
#include <iostream>
#include <iostream>
#include <algorithm>
#include <algorithm>
#include "caf/string_algorithms.hpp"
namespace
caf
{
namespace
caf
{
void
detail
::
parse_ini
(
std
::
istream
&
raw_data
,
std
::
ostream
&
errors
,
void
detail
::
parse_ini
(
std
::
istream
&
input
,
std
::
ostream
&
errors
,
config_consumer
consumer
)
{
config_consumer
consumer
)
{
std
::
string
group
;
std
::
string
group
;
std
::
string
line
;
std
::
string
line
;
size_t
ln
=
0
;
// line number
size_t
ln
=
0
;
// line number
while
(
getline
(
raw_data
,
line
))
{
auto
print
=
[
&
](
const
char
*
category
,
const
char
*
str
)
{
errors
<<
category
<<
" in line "
<<
ln
<<
": "
<<
str
<<
std
::
endl
;
};
auto
print_error
=
[
&
](
const
char
*
str
)
{
print
(
"error"
,
str
);
};
auto
print_warning
=
[
&
](
const
char
*
str
)
{
print
(
"warning"
,
str
);
};
while
(
std
::
getline
(
input
,
line
))
{
++
ln
;
++
ln
;
// get begin-of-line (bol) and end-of-line (eol), ignoring whitespaces
// get begin-of-line (bol) and end-of-line (eol), ignoring whitespaces
auto
eol
=
find_if_not
(
line
.
rbegin
(),
line
.
rend
(),
::
isspace
).
base
();
auto
eol
=
find_if_not
(
line
.
rbegin
(),
line
.
rend
(),
::
isspace
).
base
();
...
@@ -44,8 +51,7 @@ void detail::parse_ini(std::istream& raw_data, std::ostream& errors,
...
@@ -44,8 +51,7 @@ void detail::parse_ini(std::istream& raw_data, std::ostream& errors,
// do we read a group name?
// do we read a group name?
if
(
*
bol
==
'['
)
{
if
(
*
bol
==
'['
)
{
if
(
*
(
eol
-
1
)
!=
']'
)
if
(
*
(
eol
-
1
)
!=
']'
)
errors
<<
"error in line "
<<
ln
<<
": missing ] at end of line"
print_error
(
"missing ] at end of line"
);
<<
std
::
endl
;
else
else
group
.
assign
(
bol
+
1
,
eol
-
1
);
group
.
assign
(
bol
+
1
,
eol
-
1
);
// skip further processing of this line
// skip further processing of this line
...
@@ -53,23 +59,21 @@ void detail::parse_ini(std::istream& raw_data, std::ostream& errors,
...
@@ -53,23 +59,21 @@ void detail::parse_ini(std::istream& raw_data, std::ostream& errors,
}
}
// do we have a group name yet? (prohibit ungrouped values)
// do we have a group name yet? (prohibit ungrouped values)
if
(
group
.
empty
())
{
if
(
group
.
empty
())
{
errors
<<
"error in line "
<<
ln
<<
": value outside of a group"
print_error
(
"value outside of a group"
);
<<
std
::
endl
;
continue
;
continue
;
}
}
// position of the equal sign
// position of the equal sign
auto
eqs
=
find
(
bol
,
eol
,
'='
);
auto
eqs
=
find
(
bol
,
eol
,
'='
);
if
(
eqs
==
eol
)
{
if
(
eqs
==
eol
)
{
errors
<<
"error in line "
<<
ln
<<
": no '=' found"
<<
std
::
endl
;
print_error
(
"no '=' found"
)
;
continue
;
continue
;
}
}
if
(
bol
==
eqs
)
{
if
(
bol
==
eqs
)
{
errors
<<
"error in line "
<<
ln
<<
": line starting with '='"
print_error
(
"line starting with '='"
);
<<
std
::
endl
;
continue
;
continue
;
}
}
if
((
eqs
+
1
)
==
eol
)
{
if
((
eqs
+
1
)
==
eol
)
{
errors
<<
"error in line "
<<
ln
<<
": line ends with '='"
<<
std
::
endl
;
print_error
(
"line ends with '='"
)
;
continue
;
continue
;
}
}
// our keys have the format "<group>.<config-name>"
// our keys have the format "<group>.<config-name>"
...
@@ -82,7 +86,9 @@ void detail::parse_ini(std::istream& raw_data, std::ostream& errors,
...
@@ -82,7 +86,9 @@ void detail::parse_ini(std::istream& raw_data, std::ostream& errors,
// auto-detect what we are dealing with
// auto-detect what we are dealing with
constexpr
const
char
*
true_str
=
"true"
;
constexpr
const
char
*
true_str
=
"true"
;
constexpr
const
char
*
false_str
=
"false"
;
constexpr
const
char
*
false_str
=
"false"
;
auto
icase_eq
=
[](
char
x
,
char
y
)
{
return
tolower
(
x
)
==
tolower
(
y
);
};
auto
icase_eq
=
[](
char
x
,
char
y
)
{
return
tolower
(
x
)
==
tolower
(
y
);
};
if
(
std
::
equal
(
bov
,
eol
,
true_str
,
icase_eq
))
{
if
(
std
::
equal
(
bov
,
eol
,
true_str
,
icase_eq
))
{
consumer
(
std
::
move
(
key
),
true
);
consumer
(
std
::
move
(
key
),
true
);
}
else
if
(
std
::
equal
(
bov
,
eol
,
false_str
,
icase_eq
))
{
}
else
if
(
std
::
equal
(
bov
,
eol
,
false_str
,
icase_eq
))
{
...
@@ -91,18 +97,18 @@ void detail::parse_ini(std::istream& raw_data, std::ostream& errors,
...
@@ -91,18 +97,18 @@ void detail::parse_ini(std::istream& raw_data, std::ostream& errors,
// end-of-string iterator
// end-of-string iterator
auto
eos
=
eol
-
1
;
auto
eos
=
eol
-
1
;
if
(
bov
==
eos
)
{
if
(
bov
==
eos
)
{
errors
<<
"error in line "
<<
ln
<<
": stray '
\"
'"
<<
std
::
endl
;
print_error
(
"stray '
\"
'"
)
;
continue
;
continue
;
}
}
if
(
*
eos
!=
'"'
)
{
if
(
*
eos
!=
'"'
)
{
errors
<<
"error in line "
<<
ln
print_error
(
"string not terminated by '
\"
'"
);
<<
": string not terminated by '
\"
'"
<<
std
::
endl
;
continue
;
continue
;
}
}
// found a string, remove first and last char from string,
// found a string, remove first and last char from string,
// start escaping string sequence
// start escaping string sequence
auto
last_char_backslash
=
false
;
auto
last_char_backslash
=
false
;
std
::
string
result
;
std
::
string
result
;
result
.
reserve
(
static_cast
<
size_t
>
(
std
::
distance
(
bov
,
eos
)));
// skip leading " and iterate up to the trailing "
// skip leading " and iterate up to the trailing "
++
bov
;
++
bov
;
for
(;
bov
!=
eos
;
++
bov
)
{
for
(;
bov
!=
eos
;
++
bov
)
{
...
@@ -124,57 +130,51 @@ void detail::parse_ini(std::istream& raw_data, std::ostream& errors,
...
@@ -124,57 +130,51 @@ void detail::parse_ini(std::istream& raw_data, std::ostream& errors,
result
+=
*
bov
;
result
+=
*
bov
;
}
}
}
}
if
(
last_char_backslash
)
{
if
(
last_char_backslash
)
errors
<<
"warning in line "
<<
ln
print_warning
(
"trailing quotation mark escaped"
);
<<
": trailing quotation mark escaped"
<<
std
::
endl
;
}
consumer
(
std
::
move
(
key
),
std
::
move
(
result
));
consumer
(
std
::
move
(
key
),
std
::
move
(
result
));
}
else
{
}
else
{
bool
is_neg
=
*
bov
==
'-'
;
bool
is_neg
=
*
bov
==
'-'
;
if
(
is_neg
&&
++
bov
==
eol
)
{
if
(
is_neg
&&
++
bov
==
eol
)
{
errors
<<
"error in line "
<<
ln
<<
": '-' is not a number"
print_error
(
"'-' is not a number"
);
<<
std
::
endl
;
continue
;
continue
;
}
}
auto
set_ival
=
[
&
](
int
base
)
->
bool
{
auto
set_ival
=
[
&
](
int
base
,
int
prefix_len
,
const
char
*
err
)
{
char
*
e
;
char
*
e
;
int64_t
res
=
std
::
strtoll
(
&*
bov
,
&
e
,
base
);
int64_t
res
=
std
::
strtoll
(
&*
(
bov
+
prefix_len
),
&
e
,
base
);
if
(
e
==
&*
eol
)
{
if
(
e
!=
&*
eol
)
print_error
(
err
);
else
consumer
(
std
::
move
(
key
),
is_neg
?
-
res
:
res
);
consumer
(
std
::
move
(
key
),
is_neg
?
-
res
:
res
);
return
true
;
}
return
false
;
};
};
// are we dealing with a hex?
auto
set_dval
=
[
&
]
{
const
char
*
hex_prefix
=
"0x"
;
if
(
std
::
equal
(
hex_prefix
,
hex_prefix
+
2
,
bov
))
{
if
(
!
set_ival
(
16
))
{
errors
<<
"error in line "
<<
ln
<<
": invalid hex value"
<<
std
::
endl
;
}
}
else
if
(
all_of
(
bov
,
eol
,
::
isdigit
))
{
// check for base 8 and 10
if
(
*
bov
==
'0'
)
{
if
(
!
set_ival
(
8
))
{
errors
<<
"error in line "
<<
ln
<<
": invalid oct value"
<<
std
::
endl
;
}
}
else
{
if
(
!
set_ival
(
10
))
{
errors
<<
"error in line "
<<
ln
<<
": invalid decimal value"
<<
std
::
endl
;
}
}
}
else
{
// try to parse a double value
char
*
e
;
char
*
e
;
double
res
=
std
::
strtod
(
&*
bov
,
&
e
);
double
res
=
std
::
strtod
(
&*
bov
,
&
e
);
if
(
e
==
&*
eol
)
{
if
(
e
!=
&*
eol
)
print_error
(
"invalid value"
);
else
consumer
(
std
::
move
(
key
),
is_neg
?
-
res
:
res
);
consumer
(
std
::
move
(
key
),
is_neg
?
-
res
:
res
);
}
else
{
};
errors
<<
"error in line "
<<
ln
<<
": invalid value"
<<
std
::
endl
;
if
(
*
bov
==
'0'
&&
std
::
distance
(
bov
,
eol
)
>
1
)
switch
(
*
(
bov
+
1
))
{
case
'x'
:
case
'X'
:
set_ival
(
16
,
2
,
"invalid hex value"
);
break
;
case
'b'
:
case
'B'
:
set_ival
(
2
,
2
,
"invalid binary value"
);
break
;
default:
if
(
all_of
(
bov
,
eol
,
::
isdigit
))
set_ival
(
8
,
1
,
"invalid oct value"
);
else
set_dval
();
}
}
}
else
if
(
all_of
(
bov
,
eol
,
::
isdigit
))
set_ival
(
10
,
0
,
"invalid decimal value"
);
else
set_dval
();
}
}
}
}
}
}
...
...
libcaf_core/test/parse_ini.cpp
View file @
e8444968
...
@@ -56,7 +56,7 @@ foo=-0xff
...
@@ -56,7 +56,7 @@ foo=-0xff
bar=034
bar=034
baz=-0.23
baz=-0.23
buzz=1E-34
buzz=1E-34
bazz=0b10101010110011
)__"
;
)__"
;
constexpr
const
char
*
case3
=
R"__("
constexpr
const
char
*
case3
=
R"__("
...
@@ -73,6 +73,7 @@ some-int=42
...
@@ -73,6 +73,7 @@ some-int=42
some-string="hi there!\"
some-string="hi there!\"
neg=-
neg=-
wtf=0x3733T
wtf=0x3733T
not-a-bin=0b101002
hu=0779
hu=0779
hop=--"hiho"
hop=--"hiho"
)__"
;
)__"
;
...
@@ -135,11 +136,12 @@ CAF_TEST(simple_ini) {
...
@@ -135,11 +136,12 @@ CAF_TEST(simple_ini) {
CAF_TEST
(
numbers
)
{
CAF_TEST
(
numbers
)
{
load
(
case2
);
load
(
case2
);
CAF_CHECK
(
errors
.
empty
()
);
CAF_CHECK
(
join
(
errors
,
"
\n
"
)
==
""
);
CAF_CHECK
(
value_is
(
"test.foo"
,
-
0xff
));
CAF_CHECK
(
value_is
(
"test.foo"
,
-
0xff
));
CAF_CHECK
(
value_is
(
"test.bar"
,
034
));
CAF_CHECK
(
value_is
(
"test.bar"
,
034
));
CAF_CHECK
(
value_is
(
"test.baz"
,
-
0.23
));
CAF_CHECK
(
value_is
(
"test.baz"
,
-
0.23
));
CAF_CHECK
(
value_is
(
"test.buzz"
,
1E-34
));
CAF_CHECK
(
value_is
(
"test.buzz"
,
1E-34
));
CAF_CHECK
(
value_is
(
"test.bazz"
,
10931
));
}
}
CAF_TEST
(
errors
)
{
CAF_TEST
(
errors
)
{
...
@@ -154,8 +156,9 @@ CAF_TEST(errors) {
...
@@ -154,8 +156,9 @@ CAF_TEST(errors) {
CAF_CHECK
(
has_error
(
"warning in line 12: trailing quotation mark escaped"
));
CAF_CHECK
(
has_error
(
"warning in line 12: trailing quotation mark escaped"
));
CAF_CHECK
(
has_error
(
"error in line 13: '-' is not a number"
));
CAF_CHECK
(
has_error
(
"error in line 13: '-' is not a number"
));
CAF_CHECK
(
has_error
(
"error in line 14: invalid hex value"
));
CAF_CHECK
(
has_error
(
"error in line 14: invalid hex value"
));
CAF_CHECK
(
has_error
(
"error in line 15: invalid oct value"
));
CAF_CHECK
(
has_error
(
"error in line 15: invalid binary value"
));
CAF_CHECK
(
has_error
(
"error in line 16: invalid value"
));
CAF_CHECK
(
has_error
(
"error in line 16: invalid oct value"
));
CAF_CHECK
(
has_error
(
"error in line 17: invalid value"
));
CAF_CHECK
(
values
.
size
()
==
2
);
CAF_CHECK
(
values
.
size
()
==
2
);
CAF_CHECK
(
value_is
(
"test.some-int"
,
42
));
CAF_CHECK
(
value_is
(
"test.some-int"
,
42
));
CAF_CHECK
(
value_is
(
"test.some-string"
,
"hi there!"
));
CAF_CHECK
(
value_is
(
"test.some-string"
,
"hi there!"
));
...
...
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