50 namespace program_options_lite
54 ostream& ErrorReporter::error(
const string& where)
57 cerr << where <<
" error: ";
61 ostream& ErrorReporter::warn(
const string& where)
63 cerr << where <<
" warning: ";
69 for(Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); it++)
82 for (
size_t opt_end = 0; opt_end != string::npos;)
84 opt_end = opt_string.find_first_of(
',', opt_start);
86 if (opt_string[opt_start] ==
'-')
91 string opt_name = opt_string.substr(opt_start, opt_end - opt_start);
92 if (force_short || opt_name.size() == 1)
95 opt_short_map[opt_name].push_back(names);
100 opt_long_map[opt_name].push_back(names);
102 opt_start += opt_end + 1;
104 opt_list.push_back(names);
117 for (Options::NamesPtrList::iterator it = opt_list.begin(); it != opt_list.end(); ++it)
119 (*it)->opt->parse(value, error_reporter);
131 pad_short = min(pad_short, 8u);
135 unsigned pad = max((
int)pad_short - (
int)entry.
opt_short.front().size(), 0);
141 out << &(
spaces[40 - pad]);
146 out << &(
spaces[40 - pad_short]);
151 out <<
"--" << entry.
opt_long.front();
158 const unsigned pad_short = 3;
160 unsigned max_width = 0;
161 for(Options::NamesPtrList::iterator it = opts.
opt_list.begin(); it != opts.
opt_list.end(); it++)
163 ostringstream line(ios_base::out);
165 max_width = max(max_width, (
unsigned) line.tellp());
168 unsigned opt_width = min(max_width+2, 28u + pad_short) + 2;
169 unsigned desc_width = columns - opt_width;
176 for(Options::NamesPtrList::iterator it = opts.
opt_list.begin(); it != opts.
opt_list.end(); it++)
178 ostringstream line(ios_base::out);
182 const string& opt_desc = (*it)->opt->opt_desc;
183 if (opt_desc.empty())
186 cout << line.str() << endl;
189 size_t currlength = size_t(line.tellp());
190 if (currlength > opt_width)
199 for (
size_t newline_pos = 0, cur_pos = 0; cur_pos != string::npos; currlength = 0)
202 line << &(
spaces[40 - opt_width + currlength]);
203 newline_pos = opt_desc.find_first_of(
'\n', newline_pos);
204 if (newline_pos != string::npos)
208 line << opt_desc.substr(cur_pos, newline_pos - cur_pos);
209 cur_pos = newline_pos;
212 if (cur_pos + desc_width > opt_desc.size())
215 line << opt_desc.substr(cur_pos);
219 size_t split_pos = opt_desc.find_last_of(
' ', cur_pos + desc_width);
220 if (split_pos != string::npos)
223 split_pos = opt_desc.find_last_not_of(
' ', split_pos) + 1;
227 bool bad_split = split_pos == string::npos || split_pos <= cur_pos;
230 split_pos = cur_pos + desc_width;
232 line << opt_desc.substr(cur_pos, split_pos - cur_pos);
237 split_pos = opt_desc.find_first_not_of(
' ', split_pos);
239 cur_pos = newline_pos = split_pos;
241 if (cur_pos >= opt_desc.size())
248 cout << line.str() << endl;
255 : opts(rOpts), error_reporter(err)
259 virtual const string where() = 0;
261 bool storePair(
bool allow_long,
bool allow_short,
const string& name,
const string& value);
264 return storePair(
true,
true, name, value);
271 bool OptionWriter::storePair(
bool allow_long,
bool allow_short,
const string& name,
const string& value)
274 Options::NamesMap::iterator opt_it;
277 opt_it = opts.opt_long_map.find(name);
278 if (opt_it != opts.opt_long_map.end())
285 if (allow_short && !(found && allow_long))
287 opt_it = opts.opt_short_map.find(name);
288 if (opt_it != opts.opt_short_map.end())
296 error_reporter.
error(where())
297 <<
"Unknown option `" << name <<
"' (value:`" << value <<
"')\n";
301 setOptions((*opt_it).second, value, error_reporter);
311 const string where() {
return "command line"; }
313 unsigned parseGNU(
unsigned argc,
const char* argv[]);
314 unsigned parseSHORT(
unsigned argc,
const char* argv[]);
320 unsigned ArgvParser::parseGNU(
unsigned argc,
const char* argv[])
327 size_t arg_opt_start = arg.find_first_not_of(
'-');
328 size_t arg_opt_sep = arg.find_first_of(
'=');
329 string option = arg.substr(arg_opt_start, arg_opt_sep - arg_opt_start);
331 unsigned extra_argc_consumed = 0;
332 if (arg_opt_sep == string::npos)
344 extra_argc_consumed = 1;
346 if(!storePair(
true,
false, option,
"1"))
354 string val = arg.substr(arg_opt_sep + 1);
355 storePair(
true,
false, option, val);
358 return extra_argc_consumed;
361 unsigned ArgvParser::parseSHORT(
unsigned argc,
const char* argv[])
368 size_t arg_opt_start = arg.find_first_not_of(
'-');
369 string option = arg.substr(arg_opt_start);
376 error_reporter.error(where())
377 <<
"Not processing option `" << option <<
"' without argument\n";
380 storePair(
false,
true, option,
string(argv[1]));
391 list<const char*> non_option_arguments;
393 for(
unsigned i = 1; i < argc; i++)
395 if (argv[i][0] !=
'-')
397 non_option_arguments.push_back(argv[i]);
404 non_option_arguments.push_back(argv[i]);
408 if (argv[i][1] !=
'-')
420 non_option_arguments.push_back(argv[i]);
426 i += avp.
parseGNU(argc - i, &argv[i]);
429 return non_option_arguments;
445 os << name <<
":" << linenum;
449 void scanLine(
string& line);
450 void scanStream(istream& in);
453 void CfgStreamParser::scanLine(
string& line)
456 size_t start = line.find_first_not_of(
" \t\n\r");
457 if (start == string::npos)
462 if (line[start] ==
'#')
468 size_t option_end = line.find_first_of(
": \t\n\r",start);
469 string option = line.substr(start, option_end - start);
472 start = line.find_first_not_of(
" \t\n\r", option_end);
473 if (start == string::npos)
476 error_reporter.warn(where()) <<
"line formatting error\n";
479 if (line[start] !=
':')
482 error_reporter.warn(where()) <<
"line formatting error\n";
487 start = line.find_first_not_of(
" \t\n\r", ++start);
488 if (start == string::npos)
491 error_reporter.warn(where()) <<
"line formatting error\n";
497 size_t value_end = start;
500 if (line[value_end] ==
'#')
506 value_end = line.find_first_of(
" \t\n\r", value_end);
509 value_end = line.find_first_not_of(
" \t\n\r", value_end);
510 }
while (value_end != string::npos);
512 value_end = line.find_last_not_of(
" \t\n\r", value_end);
515 if (value_end >= start)
517 value = line.substr(start, value_end +1 - start);
522 error_reporter.warn(where()) <<
"no value found\n";
527 storePair(
true,
false, option, value);
530 void CfgStreamParser::scanStream(istream& in)
545 for(Options::NamesPtrList::iterator it = opts.
opt_list.begin(); it != opts.
opt_list.end(); it++)
547 (*it)->opt->setDefault();
553 ifstream cfgstream(filename.c_str(), ifstream::in);
556 error_reporter.
error(filename) <<
"Failed to open config file\n";
std::list< std::string > opt_long
std::list< std::string > opt_short
void doHelp(ostream &out, Options &opts, unsigned columns)
unsigned parseGNU(unsigned argc, const char *argv[])
ErrorReporter & error_reporter
static const char spaces[41]
static void setOptions(Options::NamesPtrList &opt_list, const string &value, ErrorReporter &error_reporter)
ErrorReporter default_error_reporter
void setDefaults(Options &opts)
list< const char * > scanArgv(Options &opts, unsigned argc, const char *argv[], ErrorReporter &error_reporter)
unsigned parseSHORT(unsigned argc, const char *argv[])
CfgStreamParser(const string &rName, Options &rOpts, ErrorReporter &rError_reporter)
bool storePair(const string &name, const string &value)
OptionWriter(Options &rOpts, ErrorReporter &err)
std::list< Names * > NamesPtrList
void parseConfigFile(Options &opts, const string &filename, ErrorReporter &error_reporter)
static void doHelpOpt(ostream &out, const Options::Names &entry, unsigned pad_short=0)
ArgvParser(Options &rOpts, ErrorReporter &rError_reporter)
void scanStream(istream &in)
virtual std::ostream & error(const std::string &where)