/*************************************************************************** * Copyright (C) 2005 by Christof Donat * * cdonat@gmx.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include "logger.h" #include #include #include #include /** abstractcommandlineparser holds some basic stuff for making commandline-Parsers easier. */ namespace abstractcommandlineparser { #ifndef HSADMIN_ABSTRACTCMDLINEPARSER #define HSADMIN_ABSTRACTCMDLINEPARSER using std::vector; using std::string; using boost::shared_ptr; using boost::scoped_ptr; using boost::starts_with; using boost::erase_first; /** \brief template for Commandline-Parser * * Has two Parameters: * - class Options: This class must provide a method 'parseThis()'. - see template CmdLineOption for an example * - class parseResult: a shared pointer to an Object of this class is passed to the Options. */ template class CmdLineParser { public: /** \brief this actually not only instatiates the parser but also parses Parameters. * * takes the Options in a vector */ CmdLineParser(vector options) : m_parsed(new parserResult), m_parseSuccessful(false) { Options o; while( options.size() > 0 ) if( !(this->m_parseSuccessful = o.parseThis(options,m_parsed)) ) return; }; //! has the parser been successful? inline bool operator!() { return !this->m_parseSuccessful; } protected: shared_ptr m_parsed; bool m_parseSuccessful; }; /** \brief base template for Option classes * * usually you would use one of the many specialisations * has four parameters: * - bool hasLongName: the Parameter has a long name (e.g. --verbose) * - bool hasShortName: the Parameter has a short name (e.g. -v) * - bool hasParameter: the Parameter is followed by another Parameter that belongs to it * - class parseResult: takes the Parse results * * You should implement a protected virtual method 'bool handle(string ¶meter, shared_ptr result)' * if you have 'hasParameter' set to true or 'bool handle(shared_ptr result)' otherwise. There you * can actually store your values in your parseResult. */ template class CmdLineOption { public: //! the actual parser function. bool parseThis(vector& options, shared_ptr result) {}; }; /** \brief base template for Option classes - specialisation * * this is the specialisation for Parameters that do have long and short names as well as a value. * * You should implement a protected virtual method * 'bool handle(string ¶meter, shared_ptr result)'. * There you can actually store your values in your parseResult. */ template class CmdLineOption { public: //! the actual parser function. bool parseThis(vector& options, shared_ptr result) { bool rval = false; if( starts_with(options[0], "-"+m_shortName) ) { if( rval = this->handle(options[1],result) ) { if( options[0] == "-"+m_shortName) options.erase(options.begin(),options.begin()+2); else { options.erase(options.begin()+1); erase_first(options[0], m_shortName); } } } else { if( starts_with(options[0], "--"+m_longName+m_parameterSeparator) ) { string p = options[0].substr(m_longName.size()+m_parameterSeparator.size()+2); if( rval = this->handle(p,result) ) options.erase(options.begin()); } } return rval; } protected: string m_longName; string m_shortName; string m_parameterSeparator; //! the handle function. virtual bool handle(string ¶meter, shared_ptr result) { return true; }; }; /** \brief base template for Option classes - specialisation * * this is the specialisation for Parameters that do have long and short names but no value. * * You should implement a protected virtual method * 'bool handle(shared_ptr result)'. * There you can actually store your values in your parseResult. */ template class CmdLineOption { public: //! the actual parser function. bool parseThis(vector& options, shared_ptr result) { bool rval = false; if( options[0] == "-"+m_shortName || options[0] == "--"+m_longName ) { if( rval = this->handle(result) ) options.erase(options.begin()); } else if( starts_with(options[0], "-"+m_shortName) && (rval = this->handle(result)) ) erase_first(options[0], m_shortName); return rval; } protected: string m_longName; string m_shortName; //! the handle function. virtual bool handle(shared_ptr result) { return true; }; }; /** \brief base template for Option classes - specialisation * * this is the specialisation for Parameters that only have a long name and a value but no short name. * * You should implement a protected virtual method * 'bool handle(string ¶meter, shared_ptr result)'. * There you can actually store your values in your parseResult. */ template class CmdLineOption { public: //! the actual parser function. bool parseThis(vector& options, shared_ptr result) { bool rval = false; if( starts_with(options[0], "--"+m_longName+m_parameterSeparator) ) { string p = options[0].substr(m_longName.size()+m_parameterSeparator.size()+2); if ( rval = this->handle(p, result) ) options.erase(options.begin()); } return rval; } protected: string m_longName; string m_parameterSeparator; //! the handle function. virtual bool handle(string ¶meter, shared_ptr result) { return true; }; }; /** \brief base template for Option classes - specialisation * * this is the specialisation for Parameters that only have a long name but no value or short name. * * You should implement a protected virtual method * 'bool handle(shared_ptr result)'. * There you can actually store your values in your parseResult. */ template class CmdLineOption { public: //! the actual parser function. bool parseThis(vector& options, shared_ptr result) { bool rval = false; if( options[0] == "--"+m_longName && (rval = this->handle(result)) ) options.erase(options.begin()); return rval; } protected: string m_longName; //! the handle function. virtual bool handle(shared_ptr result) { return true; }; }; /** \brief base template for Option classes - specialisation * * this is the specialisation for Parameters that only have short name and a value but no long name. * * You should implement a protected virtual method * 'bool handle(string ¶meter, shared_ptr result)'. * There you can actually store your values in your parseResult. */ template class CmdLineOption { public: //! the actual parser function. bool parseThis(vector& options, shared_ptr result) { bool rval = false; if( starts_with(options[0], "-"+m_shortName) && (rval = this->handle(options[1],result)) ) { if( options[0] == "-"+m_shortName) options.erase(options.begin(),options.begin()+2); else { options.erase(options.begin()+1); erase_first(options[0], m_shortName); } } return rval; } protected: string m_shortName; //! the handle function. virtual bool handle(string ¶meter, shared_ptr result) { return true; }; }; /** \brief base template for Option classes - specialisation * * this is the specialisation for Parameters that only have short name bot no value or long name. * * You should implement a protected virtual method * 'bool handle(shared_ptr result)'. * There you can actually store your values in your parseResult. */ template class CmdLineOption { public: //! the actual parser function. bool parseThis(vector& options, shared_ptr result) { bool rval = false; if( starts_with(options[0], "-"+m_shortName) && (rval = this->handle(result)) ) { if( options[0] == "-"+m_shortName ) options.erase(options.begin()); else erase_first(options[0], m_shortName); } return rval; } protected: string m_shortName; //! the handle function. virtual bool handle(shared_ptr result) { return true; }; }; /** \brief base template for Option classes - specialisation * * this is the specialisation for Parameters that only have a value but neither a long or short name. * * You should implement a protected virtual method * 'bool handle(string ¶meter, shared_ptr result)'. * There you can actually store your values in your parseResult. */ template class CmdLineOption { public: //! the actual parser function. bool parseThis(vector& options, shared_ptr result) { bool rval = false; if( !starts_with(options[0], "-") && (rval = this->handle(options[0],result)) ) options.erase(options.begin()); return rval; } protected: //! the handle function. virtual bool handle(string ¶meter, shared_ptr result) { return true; }; }; /** \brief base template for Option classes - specialisation * * this is the specialisation for Parameters that neither have a value, a long or short name. * * You should implement a protected virtual method * 'bool handle(shared_ptr result)'. * There you can actually store your values in your parseResult. */ template class CmdLineOption { public: //! the actual parser function. bool parseThis(vector& options, shared_ptr result) { bool rval = false; if( !starts_with(options[0], "-") && (rval = this->handle(result)) ) options.erase(options.begin()); return rval; } protected: //! the handle function. virtual bool handle(shared_ptr result) { return true; }; }; //! just needed for typelists class nullType {}; //! typelist for multiple Options parser template class typelist { public: typedef CAR car; typedef CDR cdr; }; /** \brief A Commandline-Option for CmdLineParser that works with a typelist of Options. * * this is meant to combine multiple Parameters in a typelist to build a complex Command Line parser */ template class CmdLineOptionList : public CmdLineOption { public: //! the actual parser function. bool parseThis(vector& options, shared_ptr result) { return m_first.parseThis(options,result) || m_second.parseThis(options,result); } private: typename tl::car m_first; CmdLineOptionList m_second; }; /** \brief specialisation for empty type list */ template class CmdLineOptionList : public CmdLineOption { public: //! the actual parser function; always returns false. bool parseThis(vector& options, shared_ptr result) { return false; } }; #define Parameterlist1(t1) \ abstractcommandlineparser::typelist #define Parameterlist2(t1,t2) \ abstractcommandlineparser::typelist #define Parameterlist3(t1,t2,t3) \ abstractcommandlineparser::typelist #define Parameterlist4(t1,t2,t3,t4) \ abstractcommandlineparser::typelist #define Parameterlist5(t1,t2,t3,t4,t5) \ abstractcommandlineparser::typelist #define Parameterlist6(t1,t2,t3,t4,t5,t6) \ abstractcommandlineparser::typelist #define Parameterlist7(t1,t2,t3,t4,t5,t6,t7) \ abstractcommandlineparser::typelist #define Parameterlist8(t1,t2,t3,t4,t5,t6,t7,t8) \ abstractcommandlineparser::typelist #define Parameterlist9(t1,t2,t3,t4,t5,t6,t7,t8,t9) \ abstractcommandlineparser::typelist #define Parameterlist10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) \ abstractcommandlineparser::typelist #define Parameterlist11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) \ abstractcommandlineparser::typelist #define Parameterlist12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) \ abstractcommandlineparser::typelist #define Parameterlist13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) \ abstractcommandlineparser::typelist #define Parameterlist14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) \ abstractcommandlineparser::typelist #define Parameterlist15(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15) \ abstractcommandlineparser::typelist #define Parameterlist16(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16) \ abstractcommandlineparser::typelist #define Parameterlist17(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17) \ abstractcommandlineparser::typelist #define Parameterlist18(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18) \ abstractcommandlineparser::typelist #define Parameterlist19(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19) \ abstractcommandlineparser::typelist #define Parameterlist20(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20) \ abstractcommandlineparser::typelist #define Parameterlist21(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21) \ abstractcommandlineparser::typelist #define Parameterlist22(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22) \ abstractcommandlineparser::typelist #define Parameterlist23(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23) \ abstractcommandlineparser::typelist #define Parameterlist24(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24) \ abstractcommandlineparser::typelist #else template class CmdLineParser; template class CmdLineOption; class nullType; template class typelist; template class CmdLineOptionList; #endif /* HSADMIN_ABSTRACTCMDLINEPARSER */ };