diff --git a/doc/overview.xml b/doc/overview.xml index 52fe9b9865..e67ad8eb02 100644 --- a/doc/overview.xml +++ b/doc/overview.xml @@ -498,7 +498,9 @@ notify(vm); introduces a new section in the configuration file. The # character introduces a - comment that spans until the end of the line. + comment that spans until the end of the line. A flag may be + passed to limit comments to only # characters + which start the line. diff --git a/include/boost/program_options/detail/config_file.hpp b/include/boost/program_options/detail/config_file.hpp index be6bba1447..5285d914b9 100644 --- a/include/boost/program_options/detail/config_file.hpp +++ b/include/boost/program_options/detail/config_file.hpp @@ -74,7 +74,8 @@ namespace boost { namespace program_options { namespace detail { common_config_file_iterator() { found_eof(); } common_config_file_iterator( const std::set& allowed_options, - bool allow_unregistered = false); + bool allow_unregistered = false, + bool limited_comments = false); virtual ~common_config_file_iterator() {} @@ -113,6 +114,7 @@ namespace boost { namespace program_options { namespace detail { std::set allowed_prefixes; std::string m_prefix; bool m_allow_unregistered; + bool m_limited_comments; }; template @@ -127,7 +129,8 @@ namespace boost { namespace program_options { namespace detail { */ basic_config_file_iterator(std::basic_istream& is, const std::set& allowed_options, - bool allow_unregistered = false); + bool allow_unregistered = false, + bool limited_comments = false); private: // base overrides @@ -151,8 +154,11 @@ namespace boost { namespace program_options { namespace detail { basic_config_file_iterator:: basic_config_file_iterator(std::basic_istream& is, const std::set& 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(); diff --git a/include/boost/program_options/parsers.hpp b/include/boost/program_options/parsers.hpp index 0576469278..a60d7d87ad 100644 --- a/include/boost/program_options/parsers.hpp +++ b/include/boost/program_options/parsers.hpp @@ -182,8 +182,10 @@ namespace boost { namespace program_options { BOOST_PROGRAM_OPTIONS_DECL #endif basic_parsed_options - parse_config_file(std::basic_istream&, const options_description&, - bool allow_unregistered = false); + parse_config_file(std::basic_istream&, + const options_description&, + bool allow_unregistered = false, + bool limited_comments = false); /** Parse a config file. @@ -199,8 +201,10 @@ namespace boost { namespace program_options { BOOST_PROGRAM_OPTIONS_DECL #endif basic_parsed_options - 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. */ diff --git a/src/config_file.cpp b/src/config_file.cpp index f2a57b4b82..86e6d11cd1 100644 --- a/src/config_file.cpp +++ b/src/config_file.cpp @@ -22,9 +22,11 @@ namespace boost { namespace program_options { namespace detail { common_config_file_iterator::common_config_file_iterator( const std::set& 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::const_iterator i = allowed_options.begin(); i != allowed_options.end(); @@ -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 diff --git a/src/parsers.cpp b/src/parsers.cpp index 364fc81a4c..3ae600c24b 100644 --- a/src/parsers.cpp +++ b/src/parsers.cpp @@ -101,7 +101,8 @@ namespace boost { namespace program_options { basic_parsed_options parse_config_file(std::basic_istream& is, const options_description& desc, - bool allow_unregistered) + bool allow_unregistered, + bool limited_comments) { set allowed_options; @@ -120,7 +121,7 @@ namespace boost { namespace program_options { // Parser return char strings parsed_options result(&desc); copy(detail::basic_config_file_iterator( - is, allowed_options, allow_unregistered), + is, allowed_options, allow_unregistered, limited_comments), detail::basic_config_file_iterator(), back_inserter(result.options)); // Convert char strings into desired type. @@ -131,21 +132,24 @@ namespace boost { namespace program_options { BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options parse_config_file(std::basic_istream& 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 parse_config_file(std::basic_istream& is, const options_description& desc, - bool allow_unregistered); + bool allow_unregistered, + bool limited_comments); #endif template basic_parsed_options 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); @@ -153,21 +157,26 @@ namespace boost { namespace program_options { { 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 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 parse_config_file(const char* filename, const options_description& desc, - bool allow_unregistered); + bool allow_unregistered, + bool limited_comments); #endif diff --git a/test/config_test.cfg b/test/config_test.cfg index 1530f7c8ab..9a4cdd540e 100644 --- a/test/config_test.cfg +++ b/test/config_test.cfg @@ -1,6 +1,7 @@ -gv1 = 0#asd +gv1 = 0 #asd empty_value = plug3 = 7 + # line comment b = true [m1] diff --git a/test/parsers_test.cpp b/test/parsers_test.cpp index 8f01731dcd..70502594e5 100644 --- a/test/parsers_test.cpp +++ b/test/parsers_test.cpp @@ -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" @@ -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