Skip to content

Possible implementation of limited comments #101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion doc/overview.xml
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,9 @@ notify(vm);
<para>introduces a new section in the configuration file.</para>
</listitem>
<listitem><para>The <literal>#</literal> character introduces a
comment that spans until the end of the line.</para>
comment that spans until the end of the line. A flag may be
passed to limit comments to only <literal>#</literal> characters
which start the line.</para>
</listitem>
</itemizedlist>

Expand Down
14 changes: 10 additions & 4 deletions include/boost/program_options/detail/config_file.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ namespace boost { namespace program_options { namespace detail {
common_config_file_iterator() { found_eof(); }
common_config_file_iterator(
const std::set<std::string>& allowed_options,
bool allow_unregistered = false);
bool allow_unregistered = false,
bool limited_comments = false);

virtual ~common_config_file_iterator() {}

Expand Down Expand Up @@ -113,6 +114,7 @@ namespace boost { namespace program_options { namespace detail {
std::set<std::string> allowed_prefixes;
std::string m_prefix;
bool m_allow_unregistered;
bool m_limited_comments;
};

template<class charT>
Expand All @@ -127,7 +129,8 @@ namespace boost { namespace program_options { namespace detail {
*/
basic_config_file_iterator(std::basic_istream<charT>& is,
const std::set<std::string>& allowed_options,
bool allow_unregistered = false);
bool allow_unregistered = false,
bool limited_comments = false);

private: // base overrides

Expand All @@ -151,8 +154,11 @@ namespace boost { namespace program_options { namespace detail {
basic_config_file_iterator<charT>::
basic_config_file_iterator(std::basic_istream<charT>& is,
const std::set<std::string>& allowed_options,
bool allow_unregistered)
: common_config_file_iterator(allowed_options, allow_unregistered)
bool allow_unregistered,
bool limited_comments)
: common_config_file_iterator(allowed_options,
allow_unregistered,
limited_comments)
{
this->is.reset(&is, null_deleter());
get();
Expand Down
12 changes: 8 additions & 4 deletions include/boost/program_options/parsers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,10 @@ namespace boost { namespace program_options {
BOOST_PROGRAM_OPTIONS_DECL
#endif
basic_parsed_options<charT>
parse_config_file(std::basic_istream<charT>&, const options_description&,
bool allow_unregistered = false);
parse_config_file(std::basic_istream<charT>&,
const options_description&,
bool allow_unregistered = false,
bool limited_comments = false);

/** Parse a config file.

Expand All @@ -199,8 +201,10 @@ namespace boost { namespace program_options {
BOOST_PROGRAM_OPTIONS_DECL
#endif
basic_parsed_options<charT>
parse_config_file(const char* filename, const options_description&,
bool allow_unregistered = false);
parse_config_file(const char* filename,
const options_description&,
bool allow_unregistered = false,
bool limited_comments = false);

/** Controls if the 'collect_unregistered' function should
include positional options, or not. */
Expand Down
14 changes: 10 additions & 4 deletions src/config_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ namespace boost { namespace program_options { namespace detail {

common_config_file_iterator::common_config_file_iterator(
const std::set<std::string>& allowed_options,
bool allow_unregistered)
bool allow_unregistered,
bool limited_comments)
: allowed_options(allowed_options),
m_allow_unregistered(allow_unregistered)
m_allow_unregistered(allow_unregistered),
m_limited_comments(limited_comments)
{
for(std::set<std::string>::const_iterator i = allowed_options.begin();
i != allowed_options.end();
Expand Down Expand Up @@ -88,9 +90,13 @@ namespace boost { namespace program_options { namespace detail {
while(this->getline(s)) {

// strip '#' comments and whitespace
if ((n = s.find('#')) != string::npos)
s = s.substr(0, n);
s = trim_ws(s);
if ((n = s.find('#')) != string::npos) {
if (!m_limited_comments || n == 0) {
s = s.substr(0, n);
s = trim_ws(s);
}
}

if (!s.empty()) {
// Handle section name
Expand Down
25 changes: 17 additions & 8 deletions src/parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ namespace boost { namespace program_options {
basic_parsed_options<charT>
parse_config_file(std::basic_istream<charT>& is,
const options_description& desc,
bool allow_unregistered)
bool allow_unregistered,
bool limited_comments)
{
set<string> allowed_options;

Expand All @@ -120,7 +121,7 @@ namespace boost { namespace program_options {
// Parser return char strings
parsed_options result(&desc);
copy(detail::basic_config_file_iterator<charT>(
is, allowed_options, allow_unregistered),
is, allowed_options, allow_unregistered, limited_comments),
detail::basic_config_file_iterator<charT>(),
back_inserter(result.options));
// Convert char strings into desired type.
Expand All @@ -131,43 +132,51 @@ namespace boost { namespace program_options {
BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char>
parse_config_file(std::basic_istream<char>& is,
const options_description& desc,
bool allow_unregistered);
bool allow_unregistered,
bool limited_comments);

#ifndef BOOST_NO_STD_WSTRING
template
BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t>
parse_config_file(std::basic_istream<wchar_t>& is,
const options_description& desc,
bool allow_unregistered);
bool allow_unregistered,
bool limited_comments);
#endif

template<class charT>
basic_parsed_options<charT>
parse_config_file(const char* filename,
const options_description& desc,
bool allow_unregistered)
bool allow_unregistered,
bool limited_comments)
{
// Parser return char strings
std::basic_ifstream< charT > strm(filename);
if (!strm)
{
boost::throw_exception(reading_file(filename));
}
return parse_config_file(strm, desc, allow_unregistered);
return parse_config_file(strm,
desc,
allow_unregistered,
limited_comments);
}

template
BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char>
parse_config_file(const char* filename,
const options_description& desc,
bool allow_unregistered);
bool allow_unregistered,
bool limited_comments);

#ifndef BOOST_NO_STD_WSTRING
template
BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t>
parse_config_file(const char* filename,
const options_description& desc,
bool allow_unregistered);
bool allow_unregistered,
bool limited_comments);
#endif


Expand Down
3 changes: 2 additions & 1 deletion test/config_test.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
gv1 = 0#asd
gv1 = 0 #asd
empty_value =
plug3 = 7
# line comment
b = true

[m1]
Expand Down
16 changes: 15 additions & 1 deletion test/parsers_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,10 @@ void test_config_file(const char* config_file)
;

const char content1[] =
" gv1 = 0#asd\n"
" gv1 = 0 #asd\n"
"empty_value = \n"
"plug3 = 7\n"
" # line comment\n"
"b = true\n"
"[m1]\n"
"v1 = 1\n"
Expand Down Expand Up @@ -298,6 +299,19 @@ void test_config_file(const char* config_file)
check_value(a2[4], "m1.v1", "1");
check_value(a2[5], "m1.v2", "2");
check_value(a2[6], "m1.v3", "3");

// same test, with # signs in values
ss.clear();
ss.seekg(0, ios::beg);
vector<option> a3 = parse_config_file(ss, desc, false, true).options;
BOOST_REQUIRE(a3.size() == 7);
check_value(a3[0], "gv1", "0 #asd");
check_value(a3[1], "empty_value", "");
check_value(a3[2], "plug3", "7");
check_value(a3[3], "b", "true");
check_value(a3[4], "m1.v1", "1");
check_value(a3[5], "m1.v2", "2");
check_value(a2[6], "m1.v3", "3");
}

void test_environment()
Expand Down