12 #include <boost/program_options.hpp>
13 #include <boost/program_options/eof_iterator.hpp>
14 #include <boost/type_traits/is_same.hpp>
15 #include <boost/shared_ptr.hpp>
16 #include <boost/algorithm/string.hpp>
18 #include <boost/noncopyable.hpp>
26 namespace program_options {
28 typedef std::pair<std::string, std::string> option_result_pair;
29 std::string parse_suffix(
const std::string& arg_val);
30 option_result_pair parse_size_suffixes(std::string s);
31 option_result_pair parse_size_arg(std::string s);
33 std::string parse_suffix(
const std::string& arg_val)
37 size_t size_suffix_pos= arg_val.find_last_of(
"kmgKMG");
38 if (size_suffix_pos == arg_val.size()-1)
40 char suffix= arg_val[size_suffix_pos];
41 std::string size_val(arg_val.substr(0, size_suffix_pos));
43 uint64_t base_size= boost::lexical_cast<uint64_t>(size_val);
50 new_size= base_size * 1024;
54 new_size= base_size * 1024 * 1024;
58 new_size= base_size * 1024 * 1024 * 1024;
61 return boost::lexical_cast<std::string>(new_size);
64 catch (std::exception&)
70 option_result_pair parse_size_suffixes(std::string s)
72 size_t equal_pos= s.find(
"=");
73 if (equal_pos != std::string::npos)
75 std::string arg_key(s.substr(0, equal_pos));
76 std::string arg_val(parse_suffix(s.substr(equal_pos+1)));
78 if (arg_val != s.substr(equal_pos+1))
80 return std::make_pair(arg_key, arg_val);
84 return std::make_pair(std::string(
""), std::string(
""));
87 option_result_pair parse_size_arg(std::string s)
89 if (s.find(
"--") == 0)
91 return parse_size_suffixes(s.substr(2));
93 return make_pair(std::string(
""), std::string(
""));
97 public boost::program_options::error
102 long_not_allowed = 30,
103 long_adjacent_not_allowed,
104 short_adjacent_not_allowed,
105 empty_adjacent_parameter,
124 const std::string& tokens()
const
139 case long_not_allowed:
140 msg =
"long options are not allowed";
142 case long_adjacent_not_allowed:
143 msg =
"parameters adjacent to long options not allowed";
145 case short_adjacent_not_allowed:
146 msg =
"parameters adjust to short options are not allowed";
148 case empty_adjacent_parameter:
149 msg =
"adjacent parameter is empty";
151 case missing_parameter:
152 msg =
"required parameter is missing";
154 case extra_parameter:
155 msg =
"extra parameter";
157 case unrecognized_line:
158 msg =
"unrecognized line";
161 msg =
"unknown error";
168 std::string m_tokens;
173 invalid_syntax::invalid_syntax(
const std::string& in_tokens,
174 invalid_syntax::kind_t in_kind) :
175 boost::program_options::error(error_message(in_kind).append(
" in '").append(in_tokens).append(
"'")),
213 public boost::eof_iterator<common_config_file_iterator,
214 boost::program_options::option>
223 bool allow_unregistered) :
224 allowed_options(in_allowed_options),
225 m_allow_unregistered(allow_unregistered)
227 for(std::set<std::string>::const_iterator i = allowed_options.begin();
228 i != allowed_options.end();
242 std::string::size_type n;
245 while(this->getline(s)) {
248 if ((n = s.find(
'#')) != std::string::npos)
254 if (*s.begin() ==
'[' && *s.rbegin() ==
']')
256 m_prefix = s.substr(1, s.size()-2);
257 if (*m_prefix.rbegin() !=
'.')
264 std::string option_value(
"true");
266 if ((n = s.find(
'=')) != std::string::npos)
269 name = m_prefix + boost::trim_copy(s.substr(0, n));
270 option_value = boost::trim_copy(parse_suffix(s.substr(n+1)));
275 name = m_prefix + boost::trim_copy(s);
278 bool registered = allowed_option(name);
279 if (!registered && !m_allow_unregistered)
280 boost::throw_exception(boost::program_options::unknown_option(name));
283 this->value().string_key = name;
284 this->value().value.clear();
285 this->value().value.push_back(option_value);
286 this->value().unregistered = !registered;
287 this->value().original_tokens.clear();
288 this->value().original_tokens.push_back(name);
289 this->value().original_tokens.push_back(option_value);
306 virtual bool getline(std::string&) {
return false; }
317 if (*s.rbegin() ==
'*')
319 s.resize(s.size()-1);
320 bool bad_prefixes(
false);
325 std::set<std::string>::iterator i = allowed_prefixes.lower_bound(s);
326 if (i != allowed_prefixes.end())
331 if (i != allowed_prefixes.begin())
338 boost::throw_exception(boost::program_options::error(
"bad prefixes"));
339 allowed_prefixes.insert(s);
345 bool allowed_option(
const std::string& s)
const
347 std::set<std::string>::const_iterator i = allowed_options.find(s);
348 if (i != allowed_options.end())
353 i = allowed_prefixes.lower_bound(s);
354 if (i != allowed_prefixes.begin() && s.find(*--i) == 0)
362 std::set<std::string> allowed_options;
364 std::set<std::string> allowed_prefixes;
365 std::string m_prefix;
366 bool m_allow_unregistered;
369 template<
class charT>
382 const std::set<std::string>& allowed_options,
383 bool allow_unregistered =
false);
387 bool getline(std::string&);
390 boost::shared_ptr<std::basic_istream<charT> > is;
398 void operator()(
void const *)
const {}
402 template<
class charT>
405 const std::set<std::string>& in_allowed_options,
406 bool in_allow_unregistered) :
418 template<
class charT>
422 if (std::getline(*is, s))
438 template<
class charT>
439 boost::program_options::basic_parsed_options<charT>
440 parse_config_file(std::basic_istream<charT>& is,
441 const boost::program_options::options_description& desc,
442 bool allow_unregistered =
false)
444 std::set<std::string> allowed_options;
446 const std::vector<boost::shared_ptr<boost::program_options::option_description> >& options = desc.options();
447 for (
unsigned i = 0; i < options.size(); ++i)
449 const boost::program_options::option_description& d= *options[i];
451 if (d.long_name().empty())
452 boost::throw_exception(boost::program_options::error(
"long name required for config file"));
454 allowed_options.insert(d.long_name());
458 boost::program_options::parsed_options result(&desc);
459 std::copy(detail::basic_config_file_iterator<charT>(is,
462 detail::basic_config_file_iterator<charT>(),
463 std::back_inserter(result.options));
465 return boost::program_options::basic_parsed_options<charT>(result);
473 template<
class charT>
474 boost::program_options::basic_parsed_options<charT>
475 parse_config_file(
const char* filename,
476 const boost::program_options::options_description& desc,
477 bool allow_unregistered =
false)
480 std::basic_ifstream< charT > strm(filename);
483 boost::throw_exception(
"Couldn't open file");
485 return parse_config_file(strm, desc, allow_unregistered);
static std::string error_message(kind_t kind)
void add_option(const char *name)