418 lines
17 KiB
C
418 lines
17 KiB
C
|
/***************************************************************************
|
||
|
* 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 ¶meter, 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 ¶meter, 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 ¶meter, 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 ¶meter, 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 ¶meter, 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 ¶meter, 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 ¶meter, 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 ¶meter, 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 ¶meter, 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 */
|
||
|
};
|