[complement-svn] SF.net SVN: complement: [1877] trunk/complement/explore
Status: Pre-Alpha
Brought to you by:
complement
From: <Dmi...@us...> - 2008-05-16 15:19:14
|
Revision: 1877 http://complement.svn.sourceforge.net/complement/?rev=1877&view=rev Author: DmitryOsmakov Date: 2008-05-16 08:18:52 -0700 (Fri, 16 May 2008) Log Message: ----------- fixed lib Opts : bad argument recognition is improved , get_default is added , unit test added and updated Modified Paths: -------------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cpp trunk/complement/explore/lib/misc/ut/misc_test_suite.cc trunk/complement/explore/lib/misc/ut/opts_test.cc trunk/complement/explore/lib/misc/ut/opts_test.h Modified: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h 2008-05-15 15:22:47 UTC (rev 1876) +++ trunk/complement/explore/include/misc/opts.h 2008-05-16 15:18:52 UTC (rev 1877) @@ -20,7 +20,7 @@ std::string longname; std::string desc; std::vector< std::string > args; - std::string v; + std::string default_v; bool has_arg; bool is_set; @@ -38,7 +38,7 @@ // adding option / flag template <class T> - void add( char _shortname,T default_value,const std::string& _longname = "", const std::string& _desc = "" ); + void add( char _shortname,T _default_value,const std::string& _longname = "", const std::string& _desc = "" ); void addflag( char _shortname,const std::string& _longname = "",const std::string& _desc = "" ); // getting option @@ -47,10 +47,19 @@ template <class T> T get( const std::string& _longname ); - + + template <class T> + T get_default( char _shorname ); + + template <class T> + T get_default( const std::string& _longname ); + template <class BackInsertIterator> void getemall(char _shortname,BackInsertIterator bi); + template <class BackInsertIterator> + void getemall(const std::string& _longname,BackInsertIterator bi); + bool is_set( char _shortname ); bool is_set( const std::string& _longname ); @@ -67,36 +76,42 @@ std::string get_author() const; std::string get_copyright() const; + struct error : public std::logic_error + { + error(const std::string& what) : + std::logic_error(what) + { } + }; + // error handling - struct invalid_opt : public std::logic_error + struct invalid_opt : public error { invalid_opt(const std::string& _optname) : - std::logic_error(std::string("invalid opt: ").append(_optname)) + error(std::string("invalid opt: ").append(_optname)) { } }; - struct missing_arg : public std::logic_error + struct missing_arg : public error { missing_arg( const std::string& _optname) : - std::logic_error(std::string("missing argument for option ").append(_optname)) + error(std::string("missing argument for option ").append(_optname)) { } }; - struct invalid_arg : public std::logic_error + struct invalid_arg : public error { invalid_arg( const std::string& _optname, const std::string& _argname) : - std::logic_error(std::string("invalid argument [").append(_argname).append("] for option ").append(_optname)) + error(std::string("invalid argument [").append(_argname).append("] for option ").append(_optname)) { } }; - struct bad_usage : public std::runtime_error + struct bad_usage : public error { bad_usage( const std::string& what) : - std::runtime_error(what) + error(what) { } }; - //std::vector< std::string > args; private: // data @@ -120,7 +135,7 @@ addflag(_shortname,_longname,_desc); std::stringstream ss; ss << _default_value; - storage[storage.size() - 1].v = ss.str(); + storage[storage.size() - 1].default_v = ss.str(); storage[storage.size() - 1].has_arg = true; } @@ -135,18 +150,16 @@ if (!storage[i].has_arg) throw bad_usage("using Opts::get for option without arguments"); + std::stringstream ss; if (!storage[i].args.empty()) - storage[i].v = storage[i].args[0]; + ss << storage[i].args[0]; + else + ss << storage[i].default_v; - try - { - std::stringstream ss(storage[i].v); - ss >> res; - } - catch(...) - { - throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].v); - } + ss >> res; + + if (ss.fail()) + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[0]); break; } @@ -156,8 +169,33 @@ return res; } +template <class T> +T Opts::get_default( char _shortname ) +{ + int i; + T res; + for (i = 0;i < storage.size();i++) + if (storage[i].shortname == _shortname) + { + if (!storage[i].has_arg) + throw bad_usage("using Opts::get for option without arguments"); + + std::stringstream ss; + ss << storage[i].default_v; + ss >> res; + if (ss.fail()) + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].default_v); + + break; + } + + if (i == storage.size()) + throw invalid_opt(std::string("-") + std::string(1,_shortname)); + return res; +} + template <class T> T Opts::get( const std::string& _longname ) { @@ -169,19 +207,17 @@ if (!storage[i].has_arg) throw bad_usage("using Opts::get for option without arguments"); + std::stringstream ss; if (!storage[i].args.empty()) - storage[i].v = storage[i].args[0]; + ss << storage[i].args[0]; + else + ss << storage[i].default_v; - try - { - std::stringstream ss(storage[i].v); - ss >> res; - } - catch(...) - { - throw invalid_arg(std::string("--") + _longname,storage[i].v); - } + ss >> res; + if (ss.fail()) // need to recover stream? + throw invalid_arg(std::string("--") + _longname,storage[i].args[0]); + break; } @@ -190,6 +226,32 @@ return res; } +template <class T> +T Opts::get_default( const std::string& _longname ) +{ + int i; + T res; + for (i = 0;i < storage.size();i++) + if (storage[i].longname == _longname) + { + if (!storage[i].has_arg) + throw bad_usage("using Opts::get for option without arguments"); + + std::stringstream ss(storage[i].default_v); + + ss >> res; + + if (ss.fail()) // need to recover stream? + throw invalid_arg(std::string("--") + _longname,storage[i].default_v); + + break; + } + + if (i == storage.size()) + throw invalid_opt(std::string("--") + _longname); + return res; +} + template <class BackInsertIterator> void Opts::getemall( char _shortname , BackInsertIterator bi) { @@ -200,24 +262,28 @@ if (!storage[i].has_arg) throw bad_usage("using Opts::getemall for option without arguments"); - if (!storage[i].v.empty()) + if (!storage[i].default_v.empty()) { - std::stringstream ss(storage[i].v); + std::stringstream ss(storage[i].default_v); ss >> *bi++; } if (!storage[i].args.empty()) for (int j = 0;j < storage[i].args.size();j++) { + + std::stringstream ss(storage[i].args[j]); try { - std::stringstream ss(storage[i].args[j]); ss >> *bi++; } catch(...) { - throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].v); + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[j]); } + + if (ss.fail()) + throw invalid_arg(std::string("-") + std::string(1,_shortname),storage[i].args[j]); } break; @@ -227,5 +293,45 @@ throw invalid_opt(std::string("-") + std::string(1,_shortname)); } +template <class BackInsertIterator> +void Opts::getemall( const std::string& _longname , BackInsertIterator bi) +{ + int i; + for (i = 0;i < storage.size();i++) + if (storage[i].longname == _longname) + { + if (!storage[i].has_arg) + throw bad_usage("using Opts::getemall for option without arguments"); + + if (!storage[i].default_v.empty()) + { + std::stringstream ss(storage[i].default_v); + ss >> *bi++; + } + if (!storage[i].args.empty()) + for (int j = 0;j < storage[i].args.size();j++) + { + + std::stringstream ss(storage[i].args[j]); + try + { + ss >> *bi++; + } + catch(...) + { + throw invalid_arg(std::string("--") + _longname,storage[i].args[j]); + } + + if (ss.fail()) + throw invalid_arg(std::string("-") + _longname,storage[i].args[j]); + } + + break; + } + + if (i == storage.size()) + throw invalid_opt(std::string("-") + _longname); +} + #endif Modified: trunk/complement/explore/lib/misc/opts.cpp =================================================================== --- trunk/complement/explore/lib/misc/opts.cpp 2008-05-15 15:22:47 UTC (rev 1876) +++ trunk/complement/explore/lib/misc/opts.cpp 2008-05-16 15:18:52 UTC (rev 1877) @@ -19,7 +19,7 @@ bool Opts::is_opt_name(const string& s) { - return (s.size() > 0) && (s[0] == '-') && !is_flag_group(s); + return (s.size() > 1) && (s[0] == '-') && !is_flag_group(s); } bool Opts::is_substr(const string& small,const string& big) @@ -95,7 +95,7 @@ out << pname << " [option ...] [optiongoup ...] [end operands ...]" << endl; out << "available options:" << endl; for (int i = 0;i < storage.size();i++) - out << "-" << storage[i].shortname << "\t[--" << storage[i].longname << "] [" << storage[i].v << "]\t-\t" << storage[i].desc << endl; + out << "-" << storage[i].shortname << "\t[--" << storage[i].longname << "] [" << storage[i].default_v << "]\t-\t" << storage[i].desc << endl; } void Opts::addflag(char _shortname,const string& _longname,const string& _desc) Modified: trunk/complement/explore/lib/misc/ut/misc_test_suite.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-15 15:22:47 UTC (rev 1876) +++ trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-05-16 15:18:52 UTC (rev 1877) @@ -71,12 +71,17 @@ t.add( &opts_test::bad_option, opts, "bad option" ); t.add( &opts_test::bad_argument, opts, "bad argument" ); + t.add( &opts_test::unexpected_argument, opts, "unexpected_argument" ); + t.add( &opts_test::missing_argument, opts, "missing argument" ); + t.add( &opts_test::user_defined, opts, "user-defined type" ); t.add( &opts_test::compound, opts, "compound" ); t.add( &opts_test::multiple, opts,"multiple"); + + t.add( &opts_test::multiple_compound, opts,"multiple_compound"); t.add( &opts_test::args, opts,"args"); @@ -84,6 +89,7 @@ // check whether autocomplement works t.add( &opts_test::autocomplement, opts,"autocomplement"); + t.add( &opts_test::autocomplement_failure, opts,"autocomplement_failure"); t.add( &opts_test::multiple_args, opts,"multiple_args"); Modified: trunk/complement/explore/lib/misc/ut/opts_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-15 15:22:47 UTC (rev 1876) +++ trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-05-16 15:18:52 UTC (rev 1877) @@ -168,12 +168,12 @@ Opts opts; - opts.add( 'p', "port", "listen tcp port" ); + opts.add( 'p', 10, "port", "listen tcp port" ); bool exception_happens = false; + + opts.parse( argc, argv ); - opts.parse( argc, argv ); - try { int t = opts.get<int>('p'); @@ -184,10 +184,61 @@ } EXAM_CHECK( exception_happens ); + EXAM_CHECK ( opts.get_default<int>('p') == 10 ); return EXAM_RESULT; } +int EXAM_IMPL(opts_test::unexpected_argument) +{ + const char* argv[] = { "name", "--help=10" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.addflag('h',"help"); + + bool exception_happens = false; + + try + { + opts.parse( argc, argv ); + } + catch(const Opts::invalid_arg& e) + { + exception_happens = true; + } + + EXAM_CHECK( exception_happens ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(opts_test::missing_argument) +{ + const char* argv[] = { "name", "-n" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add('n',10,"num"); + + bool exception_happens = false; + + try + { + opts.parse( argc, argv ); + } + catch(const Opts::missing_arg& e) + { + exception_happens = true; + } + + EXAM_CHECK( exception_happens ); + + return EXAM_RESULT; +} + int EXAM_IMPL(opts_test::multiple) { { @@ -232,6 +283,7 @@ return EXAM_RESULT; } + int EXAM_IMPL(opts_test::compound) { { @@ -253,6 +305,39 @@ return EXAM_RESULT; } +int EXAM_IMPL(opts_test::multiple_compound) +{ + { + const char* argv[] = { "name", "-xf","--flag", "-f", "-p=second" ,"--pa","third" }; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.addflag( 'x', "x-option", "option x" ); + opts.addflag( 'f', "flag", "option f" ); + + opts.add('p',"first","path","some path"); + + opts.parse( argc, argv ); + + EXAM_CHECK(opts.is_set('x')); + EXAM_CHECK(opts.is_set("flag")); + EXAM_CHECK(opts.is_set('p')); + EXAM_CHECK(opts.get_cnt("flag") == 3 && opts.get_cnt('f') == 3); + vector<string> vs(3); + + opts.getemall("path",vs.begin()); + EXAM_CHECK( vs[0] == "first" ); + EXAM_CHECK( vs[1] == "second" ); + EXAM_CHECK( vs[2] == "third" ); + } + + + return EXAM_RESULT; +} + + + int EXAM_IMPL(opts_test::args) { { @@ -389,6 +474,34 @@ return EXAM_RESULT; } +int EXAM_IMPL(opts_test::autocomplement_failure) +{ + { + const char* argv[] = { "name" , "--proc" , "4"}; + int argc = sizeof( argv ) / sizeof(argv[0]); + + Opts opts; + + opts.add('p',1,"proc_num","process number" ); + opts.add('t',string("standart"),"proc_type","process type"); + + bool exception_happens = false; + + try + { + opts.parse( argc, argv ); + } + catch(const Opts::invalid_opt& e) + { + exception_happens = true; + } + + EXAM_CHECK( exception_happens ); + } + + return EXAM_RESULT; +} + int EXAM_IMPL(opts_test::multiple_args) { { Modified: trunk/complement/explore/lib/misc/ut/opts_test.h =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-15 15:22:47 UTC (rev 1876) +++ trunk/complement/explore/lib/misc/ut/opts_test.h 2008-05-16 15:18:52 UTC (rev 1877) @@ -26,12 +26,16 @@ int EXAM_DECL(defaults); int EXAM_DECL(bad_option); int EXAM_DECL(bad_argument); + int EXAM_DECL(unexpected_argument); + int EXAM_DECL(missing_argument); int EXAM_DECL(multiple); int EXAM_DECL(compound); + int EXAM_DECL(multiple_compound); int EXAM_DECL(args); int EXAM_DECL(stop); int EXAM_DECL(user_defined); int EXAM_DECL(autocomplement); + int EXAM_DECL(autocomplement_failure); int EXAM_DECL(multiple_args); }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |