hs.hsadmin/hsacppcli/hsadminc/source/abstractcmdlineparser.h

418 lines
17 KiB
C
Raw Normal View History

/***************************************************************************
* 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 <vector>
#include <string>
#include "logger.h"
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/algorithm/string.hpp>
/** 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 Options,class parserResult> class CmdLineParser {
public:
/** \brief this actually not only instatiates the parser but also parses Parameters.
*
* takes the Options in a vector<string>
*/
CmdLineParser(vector<string> 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<parserResult> 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 &parameter, shared_ptr<parseResult> result)'
* if you have 'hasParameter' set to true or 'bool handle(shared_ptr<parseResult> result)' otherwise. There you
* can actually store your values in your parseResult.
*/
template <bool hasLongName, bool hasShortName, bool hasParameter,class parseResult> class CmdLineOption {
public:
//! the actual parser function.
bool parseThis(vector<string>& options, shared_ptr<parseResult> 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 &parameter, shared_ptr<parseResult> result)'.
* There you can actually store your values in your parseResult.
*/
template <class parseResult> class CmdLineOption<true, true, true,parseResult> {
public:
//! the actual parser function.
bool parseThis(vector<string>& options, shared_ptr<parseResult> 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 &parameter, shared_ptr<parseResult> 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<parseResult> result)'.
* There you can actually store your values in your parseResult.
*/
template <class parseResult> class CmdLineOption<true, true, false,parseResult> {
public:
//! the actual parser function.
bool parseThis(vector<string>& options, shared_ptr<parseResult> 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<parseResult> 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 &parameter, shared_ptr<parseResult> result)'.
* There you can actually store your values in your parseResult.
*/
template <class parseResult> class CmdLineOption<true, false, true,parseResult> {
public:
//! the actual parser function.
bool parseThis(vector<string>& options, shared_ptr<parseResult> 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 &parameter, shared_ptr<parseResult> 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<parseResult> result)'.
* There you can actually store your values in your parseResult.
*/
template <class parseResult> class CmdLineOption<true, false, false,parseResult> {
public:
//! the actual parser function.
bool parseThis(vector<string>& options, shared_ptr<parseResult> 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<parseResult> 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 &parameter, shared_ptr<parseResult> result)'.
* There you can actually store your values in your parseResult.
*/
template <class parseResult> class CmdLineOption<false, true, true,parseResult> {
public:
//! the actual parser function.
bool parseThis(vector<string>& options, shared_ptr<parseResult> 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 &parameter, shared_ptr<parseResult> 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<parseResult> result)'.
* There you can actually store your values in your parseResult.
*/
template <class parseResult> class CmdLineOption<false, true, false,parseResult> {
public:
//! the actual parser function.
bool parseThis(vector<string>& options, shared_ptr<parseResult> 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<parseResult> 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 &parameter, shared_ptr<parseResult> result)'.
* There you can actually store your values in your parseResult.
*/
template <class parseResult> class CmdLineOption<false, false, true,parseResult> {
public:
//! the actual parser function.
bool parseThis(vector<string>& options, shared_ptr<parseResult> 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 &parameter, shared_ptr<parseResult> 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<parseResult> result)'.
* There you can actually store your values in your parseResult.
*/
template <class parseResult> class CmdLineOption<false, false, false,parseResult> {
public:
//! the actual parser function.
bool parseThis(vector<string>& options, shared_ptr<parseResult> 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<parseResult> result) { return true; };
};
//! just needed for typelists
class nullType {};
//! typelist for multiple Options parser
template<class CAR, class CDR> 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 tl, class parseResult> class CmdLineOptionList : public CmdLineOption<false,false,false,parseResult> {
public:
//! the actual parser function.
bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
return m_first.parseThis(options,result) || m_second.parseThis(options,result);
}
private:
typename tl::car m_first;
CmdLineOptionList<typename tl::cdr,parseResult> m_second;
};
/** \brief specialisation for empty type list
*/
template<class parseResult> class CmdLineOptionList<nullType,parseResult> : public CmdLineOption<false,false,false,parseResult> {
public:
//! the actual parser function; always returns false.
bool parseThis(vector<string>& options, shared_ptr<parseResult> result) {
return false;
}
};
#define Parameterlist1(t1) \
abstractcommandlineparser::typelist<t1,abstractcommandlineparser::nullType>
#define Parameterlist2(t1,t2) \
abstractcommandlineparser::typelist<t1,Parameterlist1(t2) >
#define Parameterlist3(t1,t2,t3) \
abstractcommandlineparser::typelist<t1,Parameterlist2(t2,t3) >
#define Parameterlist4(t1,t2,t3,t4) \
abstractcommandlineparser::typelist<t1,Parameterlist3(t2,t3,t4) >
#define Parameterlist5(t1,t2,t3,t4,t5) \
abstractcommandlineparser::typelist<t1,Parameterlist4(t2,t3,t4,t5) >
#define Parameterlist6(t1,t2,t3,t4,t5,t6) \
abstractcommandlineparser::typelist<t1,Parameterlist5(t2,t3,t4,t5,t6) >
#define Parameterlist7(t1,t2,t3,t4,t5,t6,t7) \
abstractcommandlineparser::typelist<t1,Parameterlist6(t2,t3,t4,t5,t6,t7) >
#define Parameterlist8(t1,t2,t3,t4,t5,t6,t7,t8) \
abstractcommandlineparser::typelist<t1,Parameterlist7(t2,t3,t4,t5,t6,t7,t8) >
#define Parameterlist9(t1,t2,t3,t4,t5,t6,t7,t8,t9) \
abstractcommandlineparser::typelist<t1,Parameterlist8(t2,t3,t4,t5,t6,t7,t8,t9) >
#define Parameterlist10(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10) \
abstractcommandlineparser::typelist<t1,Parameterlist9(t2,t3,t4,t5,t6,t7,t8,t9,t10) >
#define Parameterlist11(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) \
abstractcommandlineparser::typelist<t1,Parameterlist10(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11) >
#define Parameterlist12(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) \
abstractcommandlineparser::typelist<t1,Parameterlist11(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12) >
#define Parameterlist13(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) \
abstractcommandlineparser::typelist<t1,Parameterlist12(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13) >
#define Parameterlist14(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) \
abstractcommandlineparser::typelist<t1,Parameterlist13(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14) >
#define Parameterlist15(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15) \
abstractcommandlineparser::typelist<t1,Parameterlist14(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15) >
#define Parameterlist16(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16) \
abstractcommandlineparser::typelist<t1,Parameterlist15(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16) >
#define Parameterlist17(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17) \
abstractcommandlineparser::typelist<t1,Parameterlist16(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17) >
#define Parameterlist18(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18) \
abstractcommandlineparser::typelist<t1,Parameterlist17(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18) >
#define Parameterlist19(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19) \
abstractcommandlineparser::typelist<t1,Parameterlist18(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19) >
#define Parameterlist20(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20) \
abstractcommandlineparser::typelist<t1,Parameterlist19(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20) >
#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<t1,Parameterlist20(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21) >
#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<t1,Parameterlist21(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22) >
#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<t1,Parameterlist22(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23) >
#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<t1,Parameterlist23(t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24) >
#else
template<class Options,class parseResult> class CmdLineParser;
template <bool hasLongName, bool hasShortName, bool hasParameter,class parseResult> class CmdLineOption;
class nullType;
template<class CAR, class CDR> class typelist;
template<class tl, class parseResult> class CmdLineOptionList;
#endif /* HSADMIN_ABSTRACTCMDLINEPARSER */
};