[complement-svn] SF.net SVN: complement: [1927] trunk/complement/explore
Status: Pre-Alpha
Brought to you by:
complement
From: <com...@us...> - 2008-06-29 21:48:13
|
Revision: 1927 http://complement.svn.sourceforge.net/complement/?rev=1927&view=rev Author: complement Date: 2008-06-29 14:48:10 -0700 (Sun, 29 Jun 2008) Log Message: ----------- Clean code; enhance help message; pass default value via operator [] Also rename option to option_base (keep in mind future changes). Test for print help really check printed message. Modified Paths: -------------- trunk/complement/explore/include/misc/opts.h trunk/complement/explore/lib/misc/opts.cc trunk/complement/explore/lib/misc/ut/opts_test.cc Modified: trunk/complement/explore/include/misc/opts.h =================================================================== --- trunk/complement/explore/include/misc/opts.h 2008-06-29 21:47:47 UTC (rev 1926) +++ trunk/complement/explore/include/misc/opts.h 2008-06-29 21:48:10 UTC (rev 1927) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/06/28 10:26:23 ptr> +// -*- C++ -*- Time-stamp: <08/06/29 13:52:41 ptr> /* * Copyright (c) 2008 @@ -23,30 +23,34 @@ #include <exception> #include <stdexcept> -#define all(c) (c).begin() , (c).end() - -class option +class option_base { public: - option( const char* _description, char _short_var, const char* _long_var ) : + option_base( const char* _description, char _short_var, const char* _long_var ) : shortname( _short_var ), longname( _long_var ), - desc( _description ) + desc( _description ), + has_arg( false ) { } - option( const char* _description, char _short_var ) : + option_base( const char* _description, char _short_var ) : shortname( _short_var ), longname(), - desc( _description ) + desc( _description ), + has_arg( false ) { } - option( const char* _description, const char* _long_var ) : + option_base( const char* _description, const char* _long_var ) : shortname( 0 ), longname( _long_var ), - desc( _description ) + desc( _description ), + has_arg( false ) { } + option_base& operator []( const std::string& d ) + { default_v = d; has_arg = true; } + bool operator ==( const std::string& _longname ) const { return longname == _longname; } bool operator ==( char _shortname ) const @@ -66,14 +70,14 @@ bool has_arg; - friend std::ostream& operator <<( std::ostream& t, const option& opt ); + friend std::ostream& operator <<( std::ostream& t, const option_base& opt ); friend class Opts; }; class Opts { private: - typedef std::vector< option > options_container_type; + typedef std::vector< option_base > options_container_type; options_container_type storage; public: @@ -84,6 +88,9 @@ void description( const char* text ) { _brief = text; } + void usage( const char* text ) + { _usage = text; } + void author( const char* text ) { _author = text; } @@ -167,6 +174,7 @@ std::string pname; std::string _brief; + std::string _usage; std::string _author; std::string _copyright; @@ -183,8 +191,7 @@ addflag(_shortname,_longname,_desc); std::stringstream ss; ss << _default_value; - storage[storage.size() - 1].default_v = ss.str(); - storage[storage.size() - 1].has_arg = true; + storage[storage.size() - 1][ss.str()]; return storage[storage.size() - 1].token; } @@ -194,186 +201,157 @@ addflag(_longname,_desc); std::stringstream ss; ss << _default_value; - storage[storage.size() - 1].default_v = ss.str(); - storage[storage.size() - 1].has_arg = true; + storage[storage.size() - 1][ss.str()]; return storage[storage.size() - 1].token; } template <class T> bool Opts::is_set(T field) const { - options_container_type::const_iterator i = find(all(storage),field); + options_container_type::const_iterator i = std::find( storage.begin(), storage.end(), field ); return ( (i == storage.end()) ? false : !i->pos.empty()); } template <class T> int Opts::get_cnt(T field) const { - options_container_type::const_iterator i = find(all(storage),field); + options_container_type::const_iterator i = std::find( storage.begin(), storage.end(), field ); return ( (i == storage.end()) ? 0 : i->pos.size()); } template <class V> std::string Opts::get( V field ) { - options_container_type::const_iterator i = find(all(storage),field); - std::string res; + options_container_type::const_iterator i = std::find( storage.begin(), storage.end(), field ); - if (i != storage.end()) - { - if ( !i->has_arg ) - { - throw std::logic_error("using Opts::get for option without arguments"); - } - - res = i->args.empty() ? i->default_v : i->args[0]; - } - else - { + if ( i == storage.end() ) { std::stringstream ss1; ss1 << field; - throw unknown_option( ss1.str() ); + throw unknown_option( ss1.str() ); } - return res; + if ( !i->has_arg ) { + throw std::logic_error("using Opts::get for option without arguments"); + } + + return i->args.empty() ? i->default_v : i->args[0]; } template < class T , class V > T Opts::get( V field ) { - options_container_type::const_iterator i = find(all(storage),field); - T res; + options_container_type::const_iterator i = std::find(storage.begin(), storage.end() ,field); - if (i != storage.end()) - { - if ( !i->has_arg ) - { - throw std::logic_error("using Opts::get for option without arguments"); - } + if ( i == storage.end() ) { + std::stringstream ss1; + ss1 << field; + throw unknown_option( ss1.str() ); + } - std::stringstream ss(i->args.empty() ? i->default_v : i->args[0]); - ss >> res; - - if (ss.fail()) - { - std::stringstream ss1; - ss1 << field; - throw arg_typemismatch(ss1.str(),i->args.empty() ? i->default_v : i->args[0]); - } + if ( !i->has_arg ) { + throw std::logic_error("using Opts::get for option without arguments"); } - else - { + + T res; + std::stringstream ss(i->args.empty() ? i->default_v : i->args[0]); + ss >> res; + + if ( ss.fail() ) { std::stringstream ss1; ss1 << field; - throw unknown_option( ss1.str() ); + throw arg_typemismatch(ss1.str(),i->args.empty() ? i->default_v : i->args[0]); } return res; } - template < class V> std::string Opts::get_default( V field ) { - options_container_type::const_iterator i = find(all(storage),field); - std::string res; + options_container_type::const_iterator i = std::find( storage.begin(), storage.end(), field ); - if (i != storage.end()) - { - if (!i->has_arg) - throw std::logic_error("using Opts::get for option without arguments"); - - res = i->default_v; - } - else - { + if ( i == storage.end() ) { std::stringstream ss1; ss1 << field; throw unknown_option( ss1.str() ); } - return res; + if ( !i->has_arg ) { + throw std::logic_error("using Opts::get for option without arguments"); + } + + return i->default_v; } template <class T , class V> T Opts::get_default( V field ) { - options_container_type::const_iterator i = find(all(storage),field); - T res; + options_container_type::const_iterator i = std::find( storage.begin(), storage.end(), field ); - if (i != storage.end()) - { - if (!i->has_arg) - throw std::logic_error("using Opts::get for option without arguments"); - - std::stringstream ss(i->default_v); - ss >> res; - - if (ss.fail()) - { - std::stringstream ss1; - ss1 << field; - throw arg_typemismatch(ss1.str(),i->default_v); - } - } - else - { + if ( i == storage.end() ) { std::stringstream ss1; ss1 << field; throw unknown_option( ss1.str() ); } + if ( !i->has_arg ) { + throw std::logic_error("using Opts::get for option without arguments"); + } + + T res; + std::stringstream ss(i->default_v); + ss >> res; + + if ( ss.fail() ) { + std::stringstream ss1; + ss1 << field; + throw arg_typemismatch(ss1.str(),i->default_v); + } + return res; } template <class V , class BackInsertIterator> void Opts::getemall( V field , BackInsertIterator bi) { - options_container_type::const_iterator i = find(all(storage),field); - if (i != storage.end()) - { - if (!i->has_arg) - throw std::logic_error("using Opts::getemall for option without arguments"); - - if (!i->args.empty()) - { - for (int j = 0;j < i->args.size();++j) - { - std::stringstream ss(i->args[j]); - ss >> *bi++; + options_container_type::const_iterator i = std::find( storage.begin(), storage.end(), field ); - if (ss.fail()) - { - std::stringstream ss1; - ss1 << field; - throw arg_typemismatch(ss1.str(),i->args[j]); - } - } - } - } - else - { + if ( i == storage.end() ) { std::stringstream ss1; ss1 << field; throw unknown_option(ss1.str()); } + + if ( !i->has_arg ) { + throw std::logic_error("using Opts::getemall for option without arguments"); + } + + if ( !i->args.empty() ) { + for ( int j = 0; j < i->args.size(); ++j) { + std::stringstream ss(i->args[j]); + ss >> *bi++; + + if ( ss.fail() ) { + std::stringstream ss1; + ss1 << field; + throw arg_typemismatch(ss1.str(),i->args[j]); + } + } + } } template <class V , class BackInsertIterator> void Opts::get_pos( V field , BackInsertIterator bi) { - options_container_type::const_iterator i = find(all(storage),field); + options_container_type::const_iterator i = std::find( storage.begin(), storage.end(), field ); - if (i != storage.end()) - { - copy(all(i->pos),bi); - } - else - { + if ( i == storage.end() ) { std::stringstream ss1; ss1 << field; throw unknown_option(ss1.str()); } + + std::copy( i->pos.begin(), i->pos.end(), bi ); } #endif // __OPTS_H__ Modified: trunk/complement/explore/lib/misc/opts.cc =================================================================== --- trunk/complement/explore/lib/misc/opts.cc 2008-06-29 21:47:47 UTC (rev 1926) +++ trunk/complement/explore/lib/misc/opts.cc 2008-06-29 21:48:10 UTC (rev 1927) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/06/28 10:25:43 ptr> +// -*- C++ -*- Time-stamp: <08/06/29 13:05:13 ptr> /* * Copyright (c) 2008 @@ -21,6 +21,22 @@ using namespace std; +ostream& operator <<( ostream& out, const option_base& opt ) +{ + if ( opt.shortname != 0 ) { + out << '-' << opt.shortname << (opt.has_arg ? " <val>" : "" ); + if ( !opt.longname.empty() ) { + out << ", "; + } + } + + if ( !opt.longname.empty() ) { + out << "--" << opt.longname << (opt.has_arg ? "=<val>" : "" ); + } + + return out << (opt.has_arg ? (string(" [") + opt.default_v + "]\t") : "\t" ) << opt.desc; +} + string Opts::get_pname() const { return pname; } bool Opts::is_opt_name(const string& s) @@ -39,17 +55,19 @@ return true; } -bool Opts::is_flag_group(const string& s) +bool Opts::is_flag_group( const string& s ) { - if (s.size() > 2 && s[0] == '-') - { - for (int i = 1;i < s.size();i++) - if (!isalnum(s[i])) + string::const_iterator i = s.begin(); + + if ( s.size() > 2 && *i == '-' ) { + while ( ++i != s.end() ) { + if ( !isalnum( *i ) ) { return false; + } + } return true; } - else - return false; + return false; } // this function assumes that is_opt_name(s) = true; @@ -89,37 +107,37 @@ return storage.end(); } -ostream& operator <<( ostream& out, const option& opt ) +void Opts::help( ostream& out ) { - if ( opt.shortname == 0 ) { - out << "--" << opt.longname << '\t' << (opt.has_arg ? (string("[") + opt.default_v + "]\t") : "" ) << opt.desc; - } else { - out << '-' << opt.shortname << '\t' << (!opt.longname.empty() ? (string("[--") + opt.longname +"]\t") : "") << (opt.has_arg ? string("[") + opt.default_v + ("]\t") : "") << opt.desc; + out << "This is " << pname; + if ( !_brief.empty() ) { + out << ", " << _brief; } - - return out; -} + out << "\n\n"; -void Opts::help(ostream& out) -{ - if (!_brief.empty()) - out << _brief << endl; - if (!_author.empty()) - out << _author << endl; - if (!_copyright.empty()) - out << _copyright << endl; - - out << "Valid options:" << endl; - options_container_type::const_iterator i; - for (i = storage.begin();i != storage.end();++i) - { - out << *i << endl; + if ( !_author.empty() ) { + out << _author << "\n\n"; } + + if ( !_copyright.empty() ) { + out << _copyright << "\n\n"; + } + + out << "Usage:\n\n" << pname << " " << _usage << "\n"; // " [options] etc. etc." + + if ( !storage.empty() ) { + out << "\nOptions:\n\n"; + + for ( options_container_type::const_iterator i = storage.begin(); i != storage.end(); ++i) { + out << *i << "\n"; + } + } + out << endl; } int Opts::addflag( char _shortname, const string& _longname, const string& _desc ) { - option opt( _desc.c_str(), _shortname, _longname.c_str() ); + option_base opt( _desc.c_str(), _shortname, _longname.c_str() ); opt.has_arg = false; opt.token = ++free_token; @@ -129,7 +147,7 @@ int Opts::addflag( const string& _longname, const string& _desc ) { - option opt( _desc.c_str(), _longname.c_str() ); + option_base opt( _desc.c_str(), _longname.c_str() ); opt.has_arg = false; opt.token = ++free_token; @@ -137,77 +155,67 @@ return opt.token; } -void Opts::parse(int& ac,const char** av) +void Opts::parse( int& ac, const char** av ) { pname = av[0]; int i = 1; int j = 1; int q = 0; - while ( (i < ac) && (string(av[i]) != "--") ) - { - if (is_opt_name(av[i])) - { + + while ( (i < ac) && (string(av[i]) != "--") ) { + if ( is_opt_name(av[i]) ) { string opt = av[i]; string arg; - int k = opt.find("="); + int k = opt.find( "=" ); - if (k != string::npos) - { - arg = opt.substr(k + 1); - opt = opt.substr(0,k); + if ( k != string::npos ) { + arg = opt.substr( k + 1 ); + opt = opt.substr( 0, k ); } - options_container_type::iterator p = get_opt_index(opt); + options_container_type::iterator p = get_opt_index(opt); - if (p == storage.end()) + if ( p == storage.end() ) { throw unknown_option(opt); - else - { - p->pos.push_back(++q); - if (p->has_arg) - { - if (!arg.empty()) - p->args.push_back(arg); - else - if (i + 1 < ac) - p->args.push_back(av[++i]); - else - throw missing_arg(opt); + } + + p->pos.push_back(++q); + if ( p->has_arg ) { + if ( !arg.empty() ) { + p->args.push_back(arg); + } else { + if ( (i + 1) >= ac ) { + throw missing_arg(opt); + } + p->args.push_back(av[++i]); } - else - if (!arg.empty()) //unexpected arg (not exactly mismatch) - throw arg_typemismatch(opt,arg); - } - } - else - if (is_flag_group(av[i])) - { + } else if ( !arg.empty() ) { //unexpected arg (not exactly mismatch) + throw arg_typemismatch(opt,arg); + } + } else if ( is_flag_group(av[i]) ) { string optgroup = av[i]; - for (int j = 1;j < optgroup.size();j++) - { + for ( int j = 1; j < optgroup.size(); j++ ) { options_container_type::iterator p = get_opt_index(string("-") + optgroup[j]); - if (p == storage.end()) - { + if ( p == storage.end() ) { throw unknown_option( "-" + string(1,optgroup[j]) ); } - else - { - p->pos.push_back(++q); - if (p->has_arg) - throw missing_arg( "-" + string(1,optgroup[j]) ); + p->pos.push_back(++q); + if ( p->has_arg ) { + throw missing_arg( "-" + string(1,optgroup[j]) ); } } + } else { + av[j++] = av[i]; } - else - av[j++] = av[i]; i++; } i += ( i < ac ); - while (i < ac) - av[j++] = av[i++]; + while (i < ac) { + av[j++] = av[i++]; + } ac = j; } Modified: trunk/complement/explore/lib/misc/ut/opts_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-06-29 21:47:47 UTC (rev 1926) +++ trunk/complement/explore/lib/misc/ut/opts_test.cc 2008-06-29 21:48:10 UTC (rev 1927) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <08/06/28 10:25:10 ptr> +// -*- C++ -*- Time-stamp: <08/06/29 13:18:16 ptr> /* * Copyright (c) 2008 @@ -704,34 +704,55 @@ int EXAM_IMPL(opts_test::help) { - { - const char* argv[] = { "name" , "--help" }; - int argc = sizeof( argv ) / sizeof(argv[0]); + const char* argv[] = { "programname" , "--help" }; + int argc = sizeof( argv ) / sizeof(argv[0]); - Opts opts; + Opts opts; - opts.description( "what utility do" ); - opts.author( "author" ); - opts.copyright( "copyright" ); + opts.description( "test for printing help message" ); + opts.usage( "[options] file-from file-to" ); + opts.author( "B. L. User" ); + opts.copyright( "Copyright (C) Youyoudine, 2008" ); - opts.addflag('h',"help","print this help message"); - opts.addflag("flag","some program flag"); - opts.addflag('v',"version","view program version"); - opts.add('I',"/usr/include","include","include paths" ); - opts.add('p',80,"port","listen to tcp port"); - opts.add("mode","standart","program mode"); + opts.addflag( 'h', "help", "print this help message" ); + opts.addflag( "flag", "some program flag" ); + opts.addflag( 'v', "version", "print version"); + opts.add( 'I', "/usr/include", "include", "include paths" ); + opts.add( 'p', 80, "port", "listen to tcp port" ); + opts.add( "mode", "standard", "program mode"); - opts.parse(argc,argv); + opts.parse( argc,argv ); - EXAM_CHECK(opts.is_set('h')); - EXAM_CHECK( opts.get_pname() == "name" ); + EXAM_CHECK( opts.is_set('h') ); + EXAM_CHECK( opts.get_pname() == "programname" ); - ofstream out("help.out"); - opts.help(out); - cout << "check file help.out" << endl; - out.close(); - } + stringstream s; + opts.help( s ); + + const char sample[] = +"This is programname, test for printing help message\n\ +\n\ +B. L. User\n\ +\n\ +Copyright (C) Youyoudine, 2008\n\ +\n\ +Usage:\n\ +\n\ +programname [options] file-from file-to\n\ +\n\ +Options:\n\ +\n\ +-h, --help\tprint this help message\n\ +--flag\tsome program flag\n\ +-v, --version\tprint version\n\ +-I <val>, --include=<val> [/usr/include]\tinclude paths\n\ +-p <val>, --port=<val> [80]\tlisten to tcp port\n\ +--mode=<val> [standard]\tprogram mode\n\ +\n"; + + EXAM_CHECK( s.str() == sample ); + return EXAM_RESULT; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |