# HG changeset patch # User alpar # Date 1173706016 0 # Node ID da8eb8f4ea417d089278fe9cd5b20eec6a3ecdc8 # Parent 7f20ec638bc22952ac35449c9cb9bc9c40ff0f82 An improved version of ArgParser: You don't need to give an explicit storage for each option. TODO: Documentation must be updated diff -r 7f20ec638bc2 -r da8eb8f4ea41 demo/arg_parser_demo.cc --- a/demo/arg_parser_demo.cc Wed Mar 07 13:32:12 2007 +0000 +++ b/demo/arg_parser_demo.cc Mon Mar 12 13:26:56 2007 +0000 @@ -27,15 +27,15 @@ double d; bool b,sil; bool g1,g2,g3; - ap.option("n", "an integer input", i, true) - .option("val", "a double input", d) + ap.refOption("n", "an integer input", i, true) + .refOption("val", "a double input", d) .synonym("vals","val") - .option("name", "a string input", s) - .option("f", "a switch", b) - .option("nohelp", "", sil) - .option("gra","Choise A",g1) - .option("grb","Choise B",g2) - .option("grc","Choise C",g3) + .refOption("name", "a string input", s) + .refOption("f", "a switch", b) + .refOption("nohelp", "", sil) + .refOption("gra","Choise A",g1) + .refOption("grb","Choise B",g2) + .refOption("grc","Choise C",g3) .optionGroup("gr","gra") .optionGroup("gr","grb") .optionGroup("gr","grc") diff -r 7f20ec638bc2 -r da8eb8f4ea41 lemon/arg_parser.cc --- a/lemon/arg_parser.cc Wed Mar 07 13:32:12 2007 +0000 +++ b/lemon/arg_parser.cc Mon Mar 12 13:26:56 2007 +0000 @@ -28,31 +28,59 @@ ArgParser::ArgParser(int argc, char **argv) :_argc(argc), _argv(argv), _command_name(argv[0]) { - option("-help","Print a short help message",_showHelp,this); + refOption("-help","Print a short help message",_showHelp,this); synonym("help","-help"); synonym("h","-help"); } - ArgParser &ArgParser::option(const std::string &name, + ArgParser::~ArgParser() + { + for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) + if(i->second.self_delete) + switch(i->second.type) { + case BOOL: + delete i->second.bool_p; + break; + case STRING: + delete i->second.string_p; + break; + case DOUBLE: + delete i->second.double_p; + break; + case INTEGER: + delete i->second.int_p; + break; + case UNKNOWN: + break; + case FUNC: + break; + } + } + + + ArgParser &ArgParser::intOption(const std::string &name, const std::string &help, - int &value, bool obl) + int value, bool obl) { ParData p; - p.int_p=&value; + p.int_p=new int(value); + p.self_delete=true; p.help=help; p.type=INTEGER; p.mandatory=obl; + p.self_delete=true; _opts[name]=p; return *this; } - ArgParser &ArgParser::option(const std::string &name, + ArgParser &ArgParser::doubleOption(const std::string &name, const std::string &help, - double &value, bool obl) + double value, bool obl) { ParData p; - p.double_p=&value; + p.double_p=new double(value); + p.self_delete=true; p.help=help; p.type=DOUBLE; p.mandatory=obl; @@ -60,12 +88,13 @@ return *this; } - ArgParser &ArgParser::option(const std::string &name, + ArgParser &ArgParser::boolOption(const std::string &name, const std::string &help, - bool &value, bool obl) + bool value, bool obl) { ParData p; - p.bool_p=&value; + p.bool_p=new bool(value); + p.self_delete=true; p.help=help; p.type=BOOL; p.mandatory=obl; @@ -76,12 +105,13 @@ return *this; } - ArgParser &ArgParser::option(const std::string &name, + ArgParser &ArgParser::stringOption(const std::string &name, const std::string &help, - std::string &value, bool obl) + std::string value, bool obl) { ParData p; - p.string_p=&value; + p.string_p=new std::string(value); + p.self_delete=true; p.help=help; p.type=STRING; p.mandatory=obl; @@ -89,19 +119,80 @@ return *this; } - ArgParser &ArgParser::option(const std::string &name, + ArgParser &ArgParser::refOption(const std::string &name, + const std::string &help, + int &value, bool obl) + { + ParData p; + p.int_p=&value; + p.self_delete=false; + p.help=help; + p.type=INTEGER; + p.mandatory=obl; + _opts[name]=p; + return *this; + } + + ArgParser &ArgParser::refOption(const std::string &name, + const std::string &help, + double &value, bool obl) + { + ParData p; + p.double_p=&value; + p.self_delete=false; + p.help=help; + p.type=DOUBLE; + p.mandatory=obl; + _opts[name]=p; + return *this; + } + + ArgParser &ArgParser::refOption(const std::string &name, + const std::string &help, + bool &value, bool obl) + { + ParData p; + p.bool_p=&value; + p.self_delete=false; + p.help=help; + p.type=BOOL; + p.mandatory=obl; + _opts[name]=p; + + value = false; + + return *this; + } + + ArgParser &ArgParser::refOption(const std::string &name, + const std::string &help, + std::string &value, bool obl) + { + ParData p; + p.string_p=&value; + p.self_delete=false; + p.help=help; + p.type=STRING; + p.mandatory=obl; + _opts[name]=p; + return *this; + } + + ArgParser &ArgParser::refOption(const std::string &name, const std::string &help, void (*func)(void *),void *data) { ParData p; p.func_p.p=func; p.func_p.data=data; + p.self_delete=false; p.help=help; p.type=FUNC; p.mandatory=false; _opts[name]=p; return *this; } + ArgParser &ArgParser::optionGroup(const std::string &group, const std::string &opt) { @@ -377,5 +468,5 @@ return *this; } - + } diff -r 7f20ec638bc2 -r da8eb8f4ea41 lemon/arg_parser.h --- a/lemon/arg_parser.h Wed Mar 07 13:32:12 2007 +0000 +++ b/lemon/arg_parser.h Mon Mar 12 13:26:56 2007 +0000 @@ -70,9 +70,9 @@ bool ingroup; bool has_syn; bool syn; - + bool self_delete; ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false), - has_syn(false), syn(false) {} + has_syn(false), syn(false), self_delete(false) {} }; typedef std::map Opts; @@ -108,13 +108,59 @@ ///\e ArgParser(int argc, char **argv); + ~ArgParser(); + ///Add a new integer type option ///\param name The name of the option. The leading '-' must be omitted. ///\param help A help string. ///\retval value The value of the argument will be written to this variable. ///\param obl Indicate if the option is mandatory. - ArgParser &option(const std::string &name, + ArgParser &intOption(const std::string &name, + const std::string &help, + int value=0, bool obl=false); + + ///Add a new floating type option + + ///\param name The name of the option. The leading '-' must be omitted. + ///\param help A help string. + ///\retval value The value of the argument will be written to this variable. + ///\param obl Indicate if the option is mandatory. + ArgParser &doubleOption(const std::string &name, + const std::string &help, + double value=0, bool obl=false); + + ///Add a new bool type option + + ///\param name The name of the option. The leading '-' must be omitted. + ///\param help A help string. + ///\retval value The value of the argument will be written to this variable. + ///\param obl Indicate if the option is mandatory. + ////\note A mandatory bool obtion is of very little use.) + ArgParser &boolOption(const std::string &name, + const std::string &help, + bool value=false, bool obl=false); + + ///Add a new string type option + + ///\param name The name of the option. The leading '-' must be omitted. + ///\param help A help string. + ///\retval value The value of the argument will be written to this variable. + ///\param obl Indicate if the option is mandatory. + ArgParser &stringOption(const std::string &name, + const std::string &help, + std::string value="", bool obl=false); + + + + + ///Add a new integer type option + + ///\param name The name of the option. The leading '-' must be omitted. + ///\param help A help string. + ///\retval value The value of the argument will be written to this variable. + ///\param obl Indicate if the option is mandatory. + ArgParser &refOption(const std::string &name, const std::string &help, int &value, bool obl=false); @@ -124,7 +170,7 @@ ///\param help A help string. ///\retval value The value of the argument will be written to this variable. ///\param obl Indicate if the option is mandatory. - ArgParser &option(const std::string &name, + ArgParser &refOption(const std::string &name, const std::string &help, double &value, bool obl=false); @@ -135,7 +181,7 @@ ///\retval value The value of the argument will be written to this variable. ///\param obl Indicate if the option is mandatory. ////\note A mandatory bool obtion is of very little use.) - ArgParser &option(const std::string &name, + ArgParser &refOption(const std::string &name, const std::string &help, bool &value, bool obl=false); @@ -145,7 +191,7 @@ ///\param help A help string. ///\retval value The value of the argument will be written to this variable. ///\param obl Indicate if the option is mandatory. - ArgParser &option(const std::string &name, + ArgParser &refOption(const std::string &name, const std::string &help, std::string &value, bool obl=false); @@ -156,7 +202,7 @@ ///\retval func The function to be called when the option is given. It /// must be of type "void f(void *)" ///\param data Data to be passed to \c func - ArgParser &option(const std::string &name, + ArgParser &refOption(const std::string &name, const std::string &help, void (*func)(void *),void *data); @@ -232,7 +278,51 @@ Opts::iterator i = _opts.find(op); return i!=_opts.end()?i->second.set:false; } + + + class RefType + { + ArgParser &_parser; + std::string _name; + public: + RefType(ArgParser &p,const std::string &n) :_parser(p),_name(n) {} + operator bool() + { + Opts::iterator i = _parser._opts.find(_name); + if(i==_parser._opts.end()) exit(3); ///\todo throw exception instead + else if(i->second.type!=ArgParser::BOOL) exit(3); + else return *(i->second.bool_p); + } + operator std::string() + { + Opts::iterator i = _parser._opts.find(_name); + if(i==_parser._opts.end()) exit(3); ///\todo throw exception instead + else if(i->second.type!=ArgParser::STRING) exit(3); + else return *(i->second.string_p); + } + operator double() + { + Opts::iterator i = _parser._opts.find(_name); + if(i==_parser._opts.end()) exit(3); ///\todo throw exception instead + else if(i->second.type!=ArgParser::DOUBLE) exit(3); + else return *(i->second.double_p); + } + operator int() + { + Opts::iterator i = _parser._opts.find(_name); + if(i==_parser._opts.end()) exit(3); ///\todo throw exception instead + else if(i->second.type!=ArgParser::INTEGER) exit(3); + else return *(i->second.int_p); + } + + }; + + RefType operator[](const std::string &n) + { + return RefType(*this, n); + } + }; } diff -r 7f20ec638bc2 -r da8eb8f4ea41 tools/lgf-gen.cc --- a/tools/lgf-gen.cc Wed Mar 07 13:32:12 2007 +0000 +++ b/tools/lgf-gen.cc Mon Mar 12 13:26:56 2007 +0000 @@ -29,6 +29,7 @@ #include #include #include +#include using namespace lemon; @@ -36,8 +37,10 @@ UGRAPH_TYPEDEFS(ListUGraph); +bool progress=true; + int N; -int girth; +// int girth; ListUGraph g; @@ -234,31 +237,44 @@ } void minTree() { + int en=0; + int pr=0; std::vector pedges; + Timer T; + std::cout << T.realTime() << "s: Setting up the edges...\n"; for(NodeIt n(g);n!=INVALID;++n) - for(NodeIt m=++(NodeIt(n));m!=INVALID;++m) - { - Pedge p; - p.a=n; - p.b=m; - p.len=(coords[m]-coords[n]).normSquare(); - pedges.push_back(p); - } + { + for(NodeIt m=++(NodeIt(n));m!=INVALID;++m) + { + Pedge p; + p.a=n; + p.b=m; + p.len=(coords[m]-coords[n]).normSquare(); + pedges.push_back(p); + } + en++; + if(progress && en>=pr*double(N)/100) + { + std::cout << pr << "% \r" << std::flush; + pr++; + } + } + std::cout << T.realTime() << "s: Sorting the edges...\n"; std::sort(pedges.begin(),pedges.end(),pedgeLess); + std::cout << T.realTime() << "s: Creating the tree...\n"; ListUGraph::NodeMap comp(g); UnionFind > uf(comp); for (NodeIt it(g); it != INVALID; ++it) - uf.insert(it); - - int en=0; + uf.insert(it); for(std::vector::iterator pi=pedges.begin();pi!=pedges.end();++pi) { if ( uf.join(pi->a,pi->b) ) { g.addEdge(pi->a,pi->b); - en++; - if(en>=N-1) return; + if(en>=N-1) + break; } } + std::cout << T.realTime() << "s: Done\n"; } @@ -267,34 +283,34 @@ { ArgParser ap(argc,argv); - bool eps; +// bool eps; bool disc_d, square_d, gauss_d; - bool tsp_a,two_a,tree_a; +// bool tsp_a,two_a,tree_a; int num_of_cities=1; double area=1; N=100; - girth=10; +// girth=10; std::string ndist("disc"); - ap.option("n", "Number of nodes (default is 100)", N) - .option("g", "Girth parameter (default is 10)", girth) - .option("cities", "Number of cities (default is 1)", num_of_cities) - .option("area", "Full relative area of the cities (default is 1)", area) - .option("disc", "Nodes are evenly distributed on a unit disc (default)",disc_d) + ap.refOption("n", "Number of nodes (default is 100)", N) + .intOption("g", "Girth parameter (default is 10)", 10) + .refOption("cities", "Number of cities (default is 1)", num_of_cities) + .refOption("area", "Full relative area of the cities (default is 1)", area) + .refOption("disc", "Nodes are evenly distributed on a unit disc (default)",disc_d) .optionGroup("dist", "disc") - .option("square", "Nodes are evenly distributed on a unit square", square_d) + .refOption("square", "Nodes are evenly distributed on a unit square", square_d) .optionGroup("dist", "square") - .option("gauss", + .refOption("gauss", "Nodes are located according to a two-dim gauss distribution", gauss_d) .optionGroup("dist", "gauss") // .mandatoryGroup("dist") .onlyOneGroup("dist") - .option("eps", "Also generate .eps output (prefix.eps)",eps) - .option("2con", "Create a two connected planar graph",two_a) + .boolOption("eps", "Also generate .eps output (prefix.eps)") + .boolOption("2con", "Create a two connected planar graph") .optionGroup("alg","2con") - .option("tree", "Create a min. cost spanning tree",tree_a) + .boolOption("tree", "Create a min. cost spanning tree") .optionGroup("alg","tree") - .option("tsp", "Create a TSP tour",tsp_a) + .boolOption("tsp", "Create a TSP tour") .optionGroup("alg","tsp") .onlyOneGroup("alg") .other("[prefix]","Prefix of the output files. Default is 'lgf-gen-out'") @@ -352,18 +368,18 @@ } } - if(tsp_a) { + if(ap["tsp"]) { tsp(); std::cout << "#2-opt improvements: " << tsp_impr_num << std::endl; } - else if(two_a) { + else if(ap["2con"]) { std::cout << "Make triangles\n"; // triangle(); - sparseTriangle(girth); + sparseTriangle(ap["g"]); std::cout << "Make it sparser\n"; - sparse2(girth); + sparse2(ap["g"]); } - else if(tree_a) { + else if(ap["tree"]) { minTree(); } @@ -374,7 +390,7 @@ for(UEdgeIt e(g);e!=INVALID;++e) tlen+=sqrt((coords[g.source(e)]-coords[g.target(e)]).normSquare()); std::cout << "Total edge length : " << tlen << std::endl; - if(eps) + if(ap["eps"]) graphToEps(g,prefix+".eps"). scale(600).nodeScale(.2).edgeWidthScale(.001).preScale(false). coords(coords).run();