1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/lemon/arg_parser.h Tue Jan 22 15:55:49 2008 +0000
1.3 @@ -0,0 +1,368 @@
1.4 +/* -*- C++ -*-
1.5 + *
1.6 + * This file is a part of LEMON, a generic C++ optimization library
1.7 + *
1.8 + * Copyright (C) 2003-2008
1.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
1.11 + *
1.12 + * Permission to use, modify and distribute this software is granted
1.13 + * provided that this copyright notice appears in all copies. For
1.14 + * precise terms see the accompanying LICENSE file.
1.15 + *
1.16 + * This software is provided "AS IS" with no warranty of any kind,
1.17 + * express or implied, and with no claim as to its suitability for any
1.18 + * purpose.
1.19 + *
1.20 + */
1.21 +
1.22 +#ifndef LEMON_ARG_PARSER
1.23 +#define LEMON_ARG_PARSER
1.24 +
1.25 +#include <vector>
1.26 +#include <map>
1.27 +#include <list>
1.28 +#include <string>
1.29 +#include <iostream>
1.30 +#include <sstream>
1.31 +#include <algorithm>
1.32 +#include <lemon/error.h>
1.33 +
1.34 +///\ingroup misc
1.35 +///\file
1.36 +///\brief A tools to parse command line arguments.
1.37 +///
1.38 +///\author Alpar Juttner
1.39 +
1.40 +namespace lemon {
1.41 +
1.42 + ///Command line arguments parser
1.43 +
1.44 + ///\ingroup misc
1.45 + ///Command line arguments parser
1.46 + ///
1.47 + class ArgParser {
1.48 +
1.49 + static void _showHelp(void *p);
1.50 + protected:
1.51 +
1.52 + int _argc;
1.53 + const char **_argv;
1.54 +
1.55 + enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
1.56 +
1.57 + class ParData {
1.58 + public:
1.59 + union {
1.60 + bool *bool_p;
1.61 + int *int_p;
1.62 + double *double_p;
1.63 + std::string *string_p;
1.64 + struct {
1.65 + void (*p)(void *);
1.66 + void *data;
1.67 + } func_p;
1.68 +
1.69 + };
1.70 + std::string help;
1.71 + bool mandatory;
1.72 + OptType type;
1.73 + bool set;
1.74 + bool ingroup;
1.75 + bool has_syn;
1.76 + bool syn;
1.77 + bool self_delete;
1.78 + ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false),
1.79 + has_syn(false), syn(false), self_delete(false) {}
1.80 + };
1.81 +
1.82 + typedef std::map<std::string,ParData> Opts;
1.83 + Opts _opts;
1.84 +
1.85 + class GroupData
1.86 + {
1.87 + public:
1.88 + typedef std::list<std::string> Opts;
1.89 + Opts opts;
1.90 + bool only_one;
1.91 + bool mandatory;
1.92 + GroupData() :only_one(false), mandatory(false) {}
1.93 + };
1.94 +
1.95 + typedef std::map<std::string,GroupData> Groups;
1.96 + Groups _groups;
1.97 +
1.98 + struct OtherArg
1.99 + {
1.100 + std::string name;
1.101 + std::string help;
1.102 + OtherArg(std::string n, std::string h) :name(n), help(h) {}
1.103 +
1.104 + };
1.105 +
1.106 + std::vector<OtherArg> _others_help;
1.107 + std::vector<std::string> _file_args;
1.108 + std::string _command_name;
1.109 +
1.110 + public:
1.111 +
1.112 + ///\e
1.113 + ArgParser(int argc, const char **argv);
1.114 +
1.115 + ~ArgParser();
1.116 +
1.117 + ///Add a new integer type option
1.118 +
1.119 + ///\param name The name of the option. The leading '-' must be omitted.
1.120 + ///\param help A help string.
1.121 + ///\retval value The value of the argument will be written to this variable.
1.122 + ///\param obl Indicate if the option is mandatory.
1.123 + ArgParser &intOption(const std::string &name,
1.124 + const std::string &help,
1.125 + int value=0, bool obl=false);
1.126 +
1.127 + ///Add a new floating type option
1.128 +
1.129 + ///\param name The name of the option. The leading '-' must be omitted.
1.130 + ///\param help A help string.
1.131 + ///\retval value The value of the argument will be written to this variable.
1.132 + ///\param obl Indicate if the option is mandatory.
1.133 + ArgParser &doubleOption(const std::string &name,
1.134 + const std::string &help,
1.135 + double value=0, bool obl=false);
1.136 +
1.137 + ///Add a new bool type option
1.138 +
1.139 + ///\param name The name of the option. The leading '-' must be omitted.
1.140 + ///\param help A help string.
1.141 + ///\retval value The value of the argument will be written to this variable.
1.142 + ///\param obl Indicate if the option is mandatory.
1.143 + ////\note A mandatory bool obtion is of very little use.)
1.144 + ArgParser &boolOption(const std::string &name,
1.145 + const std::string &help,
1.146 + bool value=false, bool obl=false);
1.147 +
1.148 + ///Add a new string type option
1.149 +
1.150 + ///\param name The name of the option. The leading '-' must be omitted.
1.151 + ///\param help A help string.
1.152 + ///\retval value The value of the argument will be written to this variable.
1.153 + ///\param obl Indicate if the option is mandatory.
1.154 + ArgParser &stringOption(const std::string &name,
1.155 + const std::string &help,
1.156 + std::string value="", bool obl=false);
1.157 +
1.158 + ///Bind a function to an option.
1.159 +
1.160 + ///\param name The name of the option. The leading '-' must be omitted.
1.161 + ///\param help A help string.
1.162 + ///\retval func The function to be called when the option is given. It
1.163 + /// must be of type "void f(void *)"
1.164 + ///\param data Data to be passed to \c func
1.165 + ArgParser &funcOption(const std::string &name,
1.166 + const std::string &help,
1.167 + void (*func)(void *),void *data);
1.168 +
1.169 + ///\name Options with an external strorage.
1.170 + ///Using this functions, the value of the option will be directly written
1.171 + ///into a variable once the option appears in the command line.
1.172 +
1.173 + ///@{
1.174 +
1.175 + ///Add a new integer type option with a storage reference
1.176 +
1.177 + ///\param name The name of the option. The leading '-' must be omitted.
1.178 + ///\param help A help string.
1.179 + ///\retval ref The value of the argument will be written to this variable.
1.180 + ///\param obl Indicate if the option is mandatory.
1.181 + ArgParser &refOption(const std::string &name,
1.182 + const std::string &help,
1.183 + int &ref, bool obl=false);
1.184 +
1.185 + ///Add a new floating type option with a storage reference
1.186 +
1.187 + ///\param name The name of the option. The leading '-' must be omitted.
1.188 + ///\param help A help string.
1.189 + ///\retval ref The value of the argument will be written to this variable.
1.190 + ///\param obl Indicate if the option is mandatory.
1.191 + ArgParser &refOption(const std::string &name,
1.192 + const std::string &help,
1.193 + double &ref, bool obl=false);
1.194 +
1.195 + ///Add a new bool type option with a storage reference
1.196 +
1.197 + ///\param name The name of the option. The leading '-' must be omitted.
1.198 + ///\param help A help string.
1.199 + ///\retval ref The value of the argument will be written to this variable.
1.200 + ///\param obl Indicate if the option is mandatory.
1.201 + ////\note A mandatory bool obtion is of very little use.)
1.202 + ArgParser &refOption(const std::string &name,
1.203 + const std::string &help,
1.204 + bool &ref, bool obl=false);
1.205 +
1.206 + ///Add a new string type option with a storage reference
1.207 +
1.208 + ///\param name The name of the option. The leading '-' must be omitted.
1.209 + ///\param help A help string.
1.210 + ///\retval ref The value of the argument will be written to this variable.
1.211 + ///\param obl Indicate if the option is mandatory.
1.212 + ArgParser &refOption(const std::string &name,
1.213 + const std::string &help,
1.214 + std::string &ref, bool obl=false);
1.215 +
1.216 + ///@}
1.217 +
1.218 + ///\name Option Groups and Synonyms
1.219 + ///
1.220 +
1.221 + ///@{
1.222 +
1.223 + ///Boundle some options into a group
1.224 +
1.225 + /// You can group some option by calling this function repeatedly for each
1.226 + /// option to be grupped with the same groupname.
1.227 + ///\param group The group name
1.228 + ///\param opt The option name
1.229 + ArgParser &optionGroup(const std::string &group,
1.230 + const std::string &opt);
1.231 +
1.232 + ///Make the members of a group exclusive
1.233 +
1.234 + ///If you call this function for a group, than at most one of them can be
1.235 + ///given at the same time
1.236 + ArgParser &onlyOneGroup(const std::string &group);
1.237 +
1.238 + ///Make a group mandatory
1.239 +
1.240 + ///Using this function, at least one of the members of \c group
1.241 + ///must be given.
1.242 + ArgParser &mandatoryGroup(const std::string &group);
1.243 +
1.244 + ///Create synonym to an option
1.245 +
1.246 + ///With this function you can create a sysnonym called \c sys of the
1.247 + ///option \c opt.
1.248 + ArgParser &synonym(const std::string &syn,
1.249 + const std::string &opt);
1.250 +
1.251 + ///@}
1.252 +
1.253 + ///Give help string for non-parsed arguments.
1.254 +
1.255 + ///With this function you can give help string for non-parsed arguments.
1.256 + ///the parameter \c name will be printed in the short usage line, while
1.257 + ///\c help gives a more detailed description.
1.258 + ArgParser &other(const std::string &name,
1.259 + const std::string &help="");
1.260 +
1.261 + ///Non option type arguments.
1.262 +
1.263 + ///Gives back a reference to a vector consisting of the program arguments
1.264 + ///not starting with a '-' character.
1.265 + std::vector<std::string> &files() { return _file_args; }
1.266 +
1.267 + ///Give back the command name (the 0th argument)
1.268 + const std::string &commandName() { return _command_name; }
1.269 +
1.270 + void show(std::ostream &os,Opts::iterator i);
1.271 + void show(std::ostream &os,Groups::iterator i);
1.272 + void showHelp(Opts::iterator i);
1.273 + void showHelp(std::vector<OtherArg>::iterator i);
1.274 + void shortHelp();
1.275 + void showHelp();
1.276 +
1.277 + void unknownOpt(std::string arg);
1.278 +
1.279 + void requiresValue(std::string arg, OptType t);
1.280 + void checkMandatories();
1.281 +
1.282 + ///Start the parsing process
1.283 + ArgParser &parse();
1.284 +
1.285 + /// Synonym for parse()
1.286 + ArgParser &run()
1.287 + {
1.288 + return parse();
1.289 + }
1.290 +
1.291 + ///Check if an opion has been given to the command.
1.292 + bool given(std::string op)
1.293 + {
1.294 + Opts::iterator i = _opts.find(op);
1.295 + return i!=_opts.end()?i->second.set:false;
1.296 + }
1.297 +
1.298 +
1.299 + ///Magic type for operator[]
1.300 +
1.301 + ///This is the type of the return value of ArgParser::operator[]().
1.302 + ///It automatically converts to int, double, bool or std::string, if it
1.303 + ///match the type of the option, otherwise it throws an exception.
1.304 + ///(i.e. it performs runtime type checking).
1.305 + class RefType
1.306 + {
1.307 + ArgParser &_parser;
1.308 + std::string _name;
1.309 + public:
1.310 + ///\e
1.311 + RefType(ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
1.312 + ///\e
1.313 + operator bool()
1.314 + {
1.315 + Opts::iterator i = _parser._opts.find(_name);
1.316 + LEMON_ASSERT(i==_parser._opts.end(),
1.317 + std::string()+"Unkown option: '"+_name+"'");
1.318 + LEMON_ASSERT(i->second.type!=ArgParser::BOOL,
1.319 + std::string()+"'"+_name+"' is a bool option");
1.320 + return *(i->second.bool_p);
1.321 + }
1.322 + ///\e
1.323 + operator std::string()
1.324 + {
1.325 + Opts::iterator i = _parser._opts.find(_name);
1.326 + LEMON_ASSERT(i==_parser._opts.end(),
1.327 + std::string()+"Unkown option: '"+_name+"'");
1.328 + LEMON_ASSERT(i->second.type!=ArgParser::STRING,
1.329 + std::string()+"'"+_name+"' is a string option");
1.330 + return *(i->second.string_p);
1.331 + }
1.332 + ///\e
1.333 + operator double()
1.334 + {
1.335 + Opts::iterator i = _parser._opts.find(_name);
1.336 + LEMON_ASSERT(i==_parser._opts.end(),
1.337 + std::string()+"Unkown option: '"+_name+"'");
1.338 + LEMON_ASSERT(i->second.type!=ArgParser::DOUBLE &&
1.339 + i->second.type!=ArgParser::INTEGER,
1.340 + std::string()+"'"+_name+"' is a floating point option");
1.341 + return i->second.type==ArgParser::DOUBLE ?
1.342 + *(i->second.double_p) : *(i->second.int_p);
1.343 + }
1.344 + ///\e
1.345 + operator int()
1.346 + {
1.347 + Opts::iterator i = _parser._opts.find(_name);
1.348 + LEMON_ASSERT(i==_parser._opts.end(),
1.349 + std::string()+"Unkown option: '"+_name+"'");
1.350 + LEMON_ASSERT(i->second.type!=ArgParser::INTEGER,
1.351 + std::string()+"'"+_name+"' is an integer option");
1.352 + return *(i->second.int_p);
1.353 + }
1.354 +
1.355 + };
1.356 +
1.357 + ///Give back the value of an option
1.358 +
1.359 + ///Give back the value of an option
1.360 + ///\sa RefType
1.361 + RefType operator[](const std::string &n)
1.362 + {
1.363 + return RefType(*this, n);
1.364 + }
1.365 +
1.366 + };
1.367 +}
1.368 +
1.369 +
1.370 +
1.371 +#endif // LEMON_MAIN_PARAMS