1
0
mirror of https://github.com/pdf2htmlEX/pdf2htmlEX.git synced 2024-07-07 18:30:34 +00:00
pdf2htmlEX/src/include/ArgParser.h

157 lines
3.9 KiB
C
Raw Normal View History

2012-09-10 09:01:15 +00:00
/*
* A wrapper of getopt
*
* by WangLu
* 2012.09.10
*/
#ifndef ARGPARSER_H__
#define ARGPARSER_H__
#include <string>
#include <vector>
#include <ostream>
#include <sstream>
class ArgParser
{
public:
~ArgParser(void);
2012-09-10 14:22:01 +00:00
typedef void (*ArgParserCallBack) (const char * arg);
2012-09-10 09:01:15 +00:00
/*
* optname: name of the argment, should be provided as --optname
* description: if description is "", the argument won't be shown in show_usage()
*/
ArgParser & add(const char * optname, const char * description, ArgParserCallBack callback = nullptr);
template <class T, class Tv>
ArgParser & add(const char * optname, T * location, const Tv & default_value, const char * description, ArgParserCallBack callback = nullptr);
void parse(int argc, char ** argv) const;
void show_usage(std::ostream & out) const;
private:
class ArgEntryBase
{
public:
ArgEntryBase(const char * name, const char * description, bool need_arg);
virtual ~ArgEntryBase() { }
char shortname;
std::string name;
std::string description;
bool need_arg;
2012-09-10 14:22:01 +00:00
virtual void parse (const char * arg) const = 0;
2012-09-10 09:01:15 +00:00
virtual void show_usage (std::ostream & out) const = 0;
};
template <class T, class Tv>
class ArgEntry : public ArgEntryBase
{
public:
ArgEntry(const char * name, T * location, const Tv & deafult_value, ArgParserCallBack callback, const char * description);
2012-09-10 14:22:01 +00:00
virtual void parse (const char * arg) const;
2012-09-10 09:01:15 +00:00
virtual void show_usage (std::ostream & out) const;
private:
T * location;
T default_value;
ArgParserCallBack callback;
};
2012-09-10 14:22:01 +00:00
std::vector<ArgEntryBase *> arg_entries, optional_arg_entries;
2012-09-10 09:01:15 +00:00
static const int arg_col_width;
};
template<class T, class Tv>
ArgParser & ArgParser::add(const char * optname, T * location, const Tv & default_value, const char * description, ArgParserCallBack callback)
{
2012-09-10 14:22:01 +00:00
// use "" in case nullptr is provided
if((!optname) || (!optname[0]))
optional_arg_entries.push_back(new ArgEntry<T, Tv>("", location, default_value, callback, ""));
else
arg_entries.push_back(new ArgEntry<T, Tv>(optname, location, default_value, callback, description));
2012-09-10 09:01:15 +00:00
return *this;
}
template<class T, class Tv>
ArgParser::ArgEntry<T, Tv>::ArgEntry(const char * name, T * location, const Tv & default_value, ArgParserCallBack callback, const char * description)
: ArgEntryBase(name, description, (location != nullptr))
, location(location)
, default_value(default_value)
, callback(callback)
{
if(need_arg)
*location = T(default_value);
}
template<class T, class Tv>
2012-09-10 14:22:01 +00:00
void ArgParser::ArgEntry<T, Tv>::parse(const char * arg) const
{
if(need_arg)
{
if(!arg)
throw std::string("Missing argument of option: --") + name;
std::istringstream sin(arg);
if(!(sin >> (*location)))
throw std::string("Cannot parse argment of option: --") + name;
}
if(callback)
(*callback)(arg);
}
2012-09-10 09:01:15 +00:00
// helper
template<class T>
void dump_default_value(std::ostream & out, const T & v)
{
out << v;
}
extern void dump_default_value(std::ostream & out, const std::string & v);
template<class T, class Tv>
void ArgParser::ArgEntry<T, Tv>::show_usage(std::ostream & out) const
{
if(description == "")
return;
std::ostringstream sout;
sout << " ";
if(shortname != 0)
{
sout << "-" << shortname;
}
if(name != "")
{
if(shortname != 0)
sout << ",";
sout << "--" << name;
}
if(need_arg)
{
sout << " <arg> (=";
dump_default_value(sout, default_value);
sout << ")";
}
std::string s = sout.str();
out << s;
for(int i = s.size(); i < arg_col_width; ++i)
out << ' ';
out << " " << description << std::endl;
}
#endif //ARGPARSER_H__