19 #ifndef INCLUDE_UTIL_COMMANDLINE_HPP
20 #define INCLUDE_UTIL_COMMANDLINE_HPP
31 #define ASSERT(x) UTIL_ASSERT(x, std::runtime_error("Assertion failure (command line parser)"))
32 #define REMEMBER_TO_UNDEFINE_ASSERT
40 class I_CommandLineOption {
42 virtual ~I_CommandLineOption() {}
43 virtual void notify_begin() = 0;
44 virtual void notify( std::string) = 0;
45 virtual void notify_end() = 0;
46 virtual std::string getName() = 0;
47 virtual std::string getDefaultValue() = 0;
48 virtual std::string getHelpString() = 0;
58 static CommandLine &getSingleton()
60 static CommandLine commandLine;
64 void parse(
int argc,
char **argv,
bool exitOnHelp =
true)
66 parse(argc, const_cast<const char **>(argv), exitOnHelp);
69 void parse(
int argc,
const char **argv,
bool exitOnHelp =
true)
71 mOptionValues.clear();
77 if (argc == 2 && isKey(argv[1]) && toKey(argv[1]) ==
"help")
79 if (mOptions.find(
"help" ) == mOptions.end())
81 std::cout <<
"Available command line switches:\n";
82 for (OptionIterator it = mOptions.begin(); it != mOptions.end(); it++)
86 I_CommandLineOption *option = (*it).second;
87 std::cout <<
"-" << option->getName() <<
"\n";
88 std::cout <<
"\tDescription: " << option->getHelpString() <<
"\n";
89 std::cout <<
"\tDefault: " << option->getDefaultValue() <<
"\n";
102 std::string arg1 = argv[i];
104 std::string arg2 = (i<argc) ? argv[i] :
"";
110 mOptionValues[ toKey(arg1) ].push_back( arg2 );
114 mOptionValues[ toKey(arg1) ].push_back(
"" );
117 if (mOptions.find( toKey(arg1) ) == mOptions.end())
125 mArgs.push_back( arg1 );
131 for (OptionIterator iter = mOptions.begin(); iter != mOptions.end(); iter++)
135 (*iter).second->notify_begin();
139 for (OptionValueIterator iter = mOptionValues.begin(); iter != mOptionValues.end(); iter++)
141 OptionIterator jter = mOptions.find((*iter).first);
142 if (jter != mOptions.end())
144 for (ValueIterator kter = (*iter).second.begin(); kter != (*iter).second.end(); kter++)
146 jter->second->notify( *kter );
151 for (OptionIterator iter = mOptions.begin(); iter != mOptions.end(); iter++)
155 (*iter).second->notify_end();
160 void registerOption(I_CommandLineOption *option)
162 mOptions[ option->getName() ] = option;
165 void unregisterOption(I_CommandLineOption *option)
167 OptionIterator it = mOptions.find( option->getName() );
168 if (it != mOptions.end() && (*it).second == option)
170 mOptions.erase( it );
177 mOptionValues.clear();
182 T
get(std::string name)
185 lexical_cast( mOptionValues[name][0], t );
189 const std::vector<std::string> &getArguments()
194 const std::vector<std::string> &getValues(std::string name)
196 return mOptionValues[name];
200 T lexical_cast(std::string strValue, T* = NULL)
204 lexical_cast(strValue, t);
210 std::map< std::string, I_CommandLineOption *> mOptions;
211 std::map<std::string, std::vector<std::string> > mOptionValues;
212 std::vector<std::string> mArgs;
214 typedef std::map< std::string, I_CommandLineOption *>::iterator OptionIterator;
215 typedef std::map<std::string, std::vector<std::string> >::iterator OptionValueIterator;
216 typedef std::vector<std::string>::iterator ValueIterator;
218 bool isKey(
const std::string &arg)
220 bool startsWithDash = (arg.size() > 1 && arg[0] ==
'-' );
221 bool startsWithDoubleDash = (arg.size() > 2 && arg[0] ==
'-' && arg[1] ==
'-');
222 return startsWithDash || startsWithDoubleDash;
225 std::string toKey(
const std::string &arg)
227 assert( isKey(arg) );
229 bool startsWithDash = (arg.size() > 1 && arg[0] ==
'-' );
230 bool startsWithDoubleDash = (arg.size() > 2 && arg[0] ==
'-' && arg[1] ==
'-');
232 if (startsWithDoubleDash)
234 return arg.substr(2);
236 else if (startsWithDash)
238 return arg.substr(1);
242 assert(0 &&
"invalid command line option syntax");
247 void lexical_cast(
const std::string &strValue,
bool &value )
249 if (strValue ==
"1" || strValue ==
"true" || strValue ==
"")
255 void lexical_cast(
const std::string &strValue,
int &value )
257 value = atoi(strValue.c_str());
260 void lexical_cast(
const std::string &strValue,
unsigned int &value )
262 value =
static_cast<unsigned int>(atoi(strValue.c_str()));
265 void lexical_cast(
const std::string &strValue, std::string &value )
273 class CommandLineOption :
public I_CommandLineOption {
276 CommandLineOption(std::string name, T default_value, std::string helpString) :
277 name(name), default_value(default_value), helpString(helpString)
279 CommandLine::getSingleton().registerOption(
this);
284 CommandLine::getSingleton().unregisterOption(
this);
293 const std::vector<T> &getValues()
const
300 return (values.empty()) ? default_value : values[0];
306 values.push_back( t );
309 virtual void on_notify_end()
324 void notify( std::string value )
327 values.push_back( CommandLine::getSingleton().lexical_cast(value, (T *) 0));
330 std::string getName()
335 std::string getHelpString()
340 std::string getDefaultValue()
342 std::ostringstream ostr;
343 ostr << default_value ;
350 std::vector<T> values;
351 std::string helpString;
355 inline std::istream &operator>>(std::istream &is, CommandLineOption<T> &option)
364 inline std::ostream &operator<<(std::ostream &os, CommandLineOption<T> &option)
372 #ifdef REMEMBER_TO_UNDEFINE_ASSERT
373 #undef REMEMBER_TO_UNDEFINE_ASSERT
377 #endif // ! INCLUDE_UTIL_COMMANDLINE_HPP