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
decfb968
Commit
decfb968
authored
Oct 09, 2015
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '1blankz7-topic/ini-parser' into develop
parents
4de52375
f9402e2a
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
439 additions
and
0 deletions
+439
-0
libcaf_core/CMakeLists.txt
libcaf_core/CMakeLists.txt
+2
-0
libcaf_core/caf/detail/parse_ini.hpp
libcaf_core/caf/detail/parse_ini.hpp
+42
-0
libcaf_core/caf/parse_config.hpp
libcaf_core/caf/parse_config.hpp
+47
-0
libcaf_core/src/parse_config.cpp
libcaf_core/src/parse_config.cpp
+77
-0
libcaf_core/src/parse_ini.cpp
libcaf_core/src/parse_ini.cpp
+169
-0
libcaf_core/test/parse_ini.cpp
libcaf_core/test/parse_ini.cpp
+102
-0
No files found.
libcaf_core/CMakeLists.txt
View file @
decfb968
...
@@ -61,6 +61,8 @@ set (LIBCAF_CORE_SRCS
...
@@ -61,6 +61,8 @@ set (LIBCAF_CORE_SRCS
src/message_data.cpp
src/message_data.cpp
src/message_handler.cpp
src/message_handler.cpp
src/node_id.cpp
src/node_id.cpp
src/parse_config.cpp
src/parse_ini.cpp
src/ref_counted.cpp
src/ref_counted.cpp
src/response_promise.cpp
src/response_promise.cpp
src/replies_to.cpp
src/replies_to.cpp
...
...
libcaf_core/caf/detail/parse_ini.hpp
0 → 100644
View file @
decfb968
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_DETAIL_PARSE_INI_HPP
#define CAF_DETAIL_PARSE_INI_HPP
#include <istream>
#include "caf/parse_config.hpp"
namespace
caf
{
namespace
detail
{
/// Parse the given input stream as INI formatted data and calls the consumer
/// with every key-value pair.
/// @param raw_data the INI formatted input stream
/// @param errors a stream of all errors which occure while parsing
/// @param consumer a function that consums the key-value pairs
void
parse_ini
(
std
::
istream
&
raw_data
,
std
::
ostream
&
errors
,
config_consumer
consumer
);
}
// namespace detail
}
// namespace caf
#endif // CAF_DETAIL_PARSE_INI_HPP
libcaf_core/caf/parse_config.hpp
0 → 100644
View file @
decfb968
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_PARSER_CONFIG_HPP
#define CAF_PARSER_CONFIG_HPP
#include <algorithm>
#include <string>
#include "caf/variant.hpp"
namespace
caf
{
enum
class
config_format
{
auto_detect
,
ini
};
using
config_value
=
variant
<
std
::
string
,
double
,
int64_t
,
bool
>
;
using
config_consumer
=
std
::
function
<
void
(
std
::
string
,
config_value
)
>
;
/// parse_config
/// @param file_name
/// @param cf
void
parse_config
(
const
std
::
string
&
file_name
,
config_format
cf
=
config_format
::
auto_detect
);
}
// namespace caf
#endif // CAF_PARSER_CONFIG_HPP
libcaf_core/src/parse_config.cpp
0 → 100644
View file @
decfb968
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/parse_config.hpp"
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include "caf/actor.hpp"
#include "caf/atom.hpp"
#include "caf/detail/optional_message_visitor.hpp"
#include "caf/detail/parse_ini.hpp"
#include "caf/experimental/whereis.hpp"
namespace
caf
{
void
parse_config
(
const
std
::
string
&
file_name
,
config_format
cf
)
{
if
(
cf
==
config_format
::
auto_detect
)
{
// try to detect file format according to file extension
if
(
file_name
.
size
()
<
5
)
{
std
::
cerr
<<
"filename is to short"
<<
std
::
endl
;
}
else
if
(
file_name
.
compare
(
file_name
.
size
()
-
4
,
4
,
".ini"
))
{
parse_config
(
file_name
,
config_format
::
ini
);
}
else
{
std
::
cerr
<<
"unknown config file format"
<<
std
::
endl
;
}
return
;
}
std
::
ifstream
raw_data
(
file_name
);
std
::
stringstream
error_stream
;
struct
consumer
{
actor
config_server_
;
consumer
()
{
config_server_
=
experimental
::
whereis
(
atom
(
"ConfigServ"
));
}
consumer
(
const
consumer
&
)
=
default
;
consumer
&
operator
=
(
const
consumer
&
)
=
default
;
void
operator
()(
std
::
string
key
,
config_value
value
)
const
{
// send message to config server
}
};
consumer
cons
;
switch
(
cf
)
{
case
config_format
:
:
ini
:
detail
::
parse_ini
(
raw_data
,
error_stream
,
cons
);
break
;
default:
std
::
cerr
<<
"no other format is supported"
<<
std
::
endl
;
break
;
}
raw_data
.
close
();
}
}
// namespace caf
libcaf_core/src/parse_ini.cpp
0 → 100644
View file @
decfb968
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/detail/parse_ini.hpp"
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include "caf/string_algorithms.hpp"
namespace
caf
{
void
detail
::
parse_ini
(
std
::
istream
&
raw_data
,
std
::
ostream
&
errors
,
config_consumer
consumer
)
{
std
::
string
group
;
std
::
string
line
;
size_t
ln
=
0
;
// line number
while
(
getline
(
raw_data
,
line
))
{
++
ln
;
// get begin-of-line (bol) and end-of-line (eol), ignoring whitespaces
auto
eol
=
find_if_not
(
line
.
rbegin
(),
line
.
rend
(),
::
isspace
).
base
();
auto
bol
=
find_if_not
(
line
.
begin
(),
eol
,
::
isspace
);
// ignore empty lines and lines starting with ';' (comment)
if
(
bol
==
eol
||
*
bol
==
';'
)
continue
;
// do we read a group name?
if
(
*
bol
==
'['
)
{
if
(
*
(
eol
-
1
)
!=
']'
)
{
errors
<<
"error in line "
<<
ln
<<
": missing ] at end of line"
<<
std
::
endl
;
}
else
{
group
.
assign
(
bol
+
1
,
eol
-
1
);
}
// skip further processing of this line
continue
;
}
// do we have a group name yet? (prohibit ungrouped values)
if
(
group
.
empty
())
{
errors
<<
"error in line "
<<
ln
<<
": value outside of a group"
<<
std
::
endl
;
continue
;
}
// position of the equal sign
auto
eqs
=
find
(
bol
,
eol
,
'='
);
if
(
eqs
==
eol
)
{
errors
<<
"error in line "
<<
ln
<<
": no '=' found"
<<
std
::
endl
;
continue
;
}
if
(
bol
==
eqs
)
{
errors
<<
"error in line "
<<
ln
<<
": line starting with '='"
<<
std
::
endl
;
continue
;
}
if
((
eqs
+
1
)
==
eol
)
{
errors
<<
"error in line "
<<
ln
<<
": line ends with '='"
<<
std
::
endl
;
continue
;
}
// our keys have the format "<group>.<config-name>"
auto
key
=
group
;
key
+=
'.'
;
// ignore any whitespace between config-name and equal sign
key
.
insert
(
key
.
end
(),
bol
,
find_if
(
bol
,
eqs
,
::
isspace
));
// begin-of-value, ignoreing whitespaces after '='
auto
bov
=
find_if_not
(
eqs
+
1
,
eol
,
::
isspace
);
// auto-detect what we are dealing with
const
char
*
true_str
=
"true"
;
const
char
*
false_str
=
"false"
;
if
(
std
::
equal
(
bov
,
eol
,
true_str
))
{
consumer
(
std
::
move
(
key
),
true
);
}
else
if
(
std
::
equal
(
bov
,
eol
,
false_str
))
{
consumer
(
std
::
move
(
key
),
false
);
}
else
if
(
*
bov
==
'"'
)
{
// found a string, remove first and last char from string, start escaping
// string sequence
auto
last_char_backslash
=
false
;
std
::
string
result
=
""
;
// skip leading " and iterate up to the trailing "
++
bov
;
for
(;
bov
+
1
!=
eol
;
++
bov
)
{
if
(
last_char_backslash
)
{
switch
(
*
bov
)
{
case
'n'
:
result
+=
'\n'
;
break
;
default:
result
+=
*
bov
;
}
last_char_backslash
=
false
;
}
else
if
(
*
bov
==
'\\'
)
{
last_char_backslash
=
true
;
}
else
{
result
+=
*
bov
;
}
}
if
(
last_char_backslash
)
{
errors
<<
"error in line "
<<
ln
<<
": trailing quotation mark was escaped"
<<
std
::
endl
;
}
consumer
(
std
::
move
(
key
),
std
::
move
(
result
));
}
else
{
bool
is_neg
=
*
bov
==
'-'
;
if
(
is_neg
&&
++
bov
==
eol
)
{
errors
<<
"error in line "
<<
ln
<<
": '-' is not a number"
<<
std
::
endl
;
continue
;
}
auto
set_ival
=
[
&
](
int
base
)
->
bool
{
char
*
e
;
int64_t
res
=
std
::
strtoll
(
&*
bov
,
&
e
,
base
);
if
(
e
==
&*
eol
)
{
consumer
(
std
::
move
(
key
),
is_neg
?
-
res
:
res
);
return
true
;
}
return
false
;
};
// are we dealing with a hex?
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
;
double
res
=
std
::
strtod
(
&*
bov
,
&
e
);
if
(
e
==
&*
eol
)
{
consumer
(
std
::
move
(
key
),
is_neg
?
-
res
:
res
);
}
else
{
errors
<<
"error in line "
<<
ln
<<
": can't parse value to double"
<<
std
::
endl
;
}
}
}
}
}
}
// namespace caf
libcaf_core/test/parse_ini.cpp
0 → 100644
View file @
decfb968
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/config.hpp"
#define CAF_SUITE ini_parser
#include "caf/test/unit_test.hpp"
#include <iostream>
#include <sstream>
#include "caf/all.hpp"
#include "caf/detail/parse_ini.hpp"
using
namespace
caf
;
namespace
{
template
<
class
T
>
bool
value_is
(
const
config_value
&
cv
,
const
T
&
what
)
{
const
T
*
ptr
=
get
<
T
>
(
&
cv
);
return
ptr
!=
nullptr
&&
*
ptr
==
what
;
}
constexpr
const
char
*
case1
=
R"__(
[scheduler]
policy="work-sharing"
max-threads=2
; the middleman
[middleman]
automatic-connections=true
[nexus]
host="127.0.0.1"
port=4242
[cash]
greeting="Hi there, this is \"CASH!\"\n ~\\~ use at your own risk ~\\~"
)__"
;
constexpr
const
char
*
case2
=
R"__(
[test]
foo=-0xff
bar=034
baz=-0.23
buzz=1E-34
)__"
;
}
// namespace <anonymous>
CAF_TEST
(
simple_ini
)
{
std
::
map
<
std
::
string
,
config_value
>
values
;
auto
f
=
[
&
](
std
::
string
key
,
config_value
value
)
{
values
.
emplace
(
std
::
move
(
key
),
std
::
move
(
value
));
};
std
::
stringstream
ss
;
std
::
stringstream
err
;
ss
<<
case1
;
detail
::
parse_ini
(
ss
,
err
,
f
);
CAF_CHECK
(
values
.
count
(
"nexus.port"
)
>
0
);
CAF_CHECK
(
value_is
(
values
[
"nexus.port"
],
int64_t
{
4242
}));
CAF_CHECK
(
value_is
(
values
[
"nexus.host"
],
std
::
string
{
"127.0.0.1"
}));
CAF_CHECK
(
value_is
(
values
[
"scheduler.policy"
],
std
::
string
{
"work-sharing"
}));
CAF_CHECK
(
value_is
(
values
[
"scheduler.max-threads"
],
int64_t
{
2
}));
CAF_CHECK
(
value_is
(
values
[
"middleman.automatic-connections"
],
bool
{
true
}));
CAF_CHECK
(
values
.
count
(
"cash.greeting"
)
>
0
);
CAF_CHECK
(
value_is
(
values
[
"cash.greeting"
],
std
::
string
{
"Hi there, this is
\"
CASH!
\"\n
~
\\
~ use at your own risk ~
\\
~"
}));
}
CAF_TEST
(
numbers
)
{
std
::
map
<
std
::
string
,
config_value
>
values
;
auto
f
=
[
&
](
std
::
string
key
,
config_value
value
)
{
values
.
emplace
(
std
::
move
(
key
),
std
::
move
(
value
));
};
std
::
stringstream
ss
;
std
::
stringstream
err
;
ss
<<
case2
;
detail
::
parse_ini
(
ss
,
err
,
f
);
CAF_CHECK
(
value_is
(
values
[
"test.foo"
],
int64_t
{
-
0xff
}));
CAF_CHECK
(
value_is
(
values
[
"test.bar"
],
int64_t
{
034
}));
CAF_CHECK
(
value_is
(
values
[
"test.baz"
],
double
{
-
0.23
}));
CAF_CHECK
(
value_is
(
values
[
"test.buzz"
],
double
{
1E-34
}));
}
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