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

205 lines
5.2 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>
2012-09-10 17:53:33 +00:00
#ifndef nullptr
#define nullptr (NULL)
#endif
namespace pdf2htmlEX {
//helper
template<class T>
2012-09-11 14:30:12 +00:00
bool read_value(const char * arg, T * location)
2012-09-10 09:01:15 +00:00
{
std::istringstream sin(arg);
2012-09-11 14:30:12 +00:00
return ((sin >> (*location)) && (sin.eof()));
}
2012-09-10 09:01:15 +00:00
2012-09-11 14:30:12 +00:00
extern bool read_value(const char * arg, char * location);
extern bool read_value(const char * arg, std::string * location);
2012-09-10 09:01:15 +00:00
template<class T>
void dump_value(std::ostream & out, const T & v)
{
out << v;
}
2012-09-10 09:01:15 +00:00
extern void dump_value(std::ostream & out, const std::string & v);
2012-09-10 09:01:15 +00:00
// type names helper
template<typename>
struct type_name {
static char const* value() { return "unknown"; }
};
template<> struct type_name<int> {
static char const* value() { return "int"; }
};
template<> struct type_name<double> {
static char const* value() { return "fp"; }
};
template<> struct type_name<std::string> {
static char const* value() { return "string"; }
};
2012-09-10 09:01:15 +00:00
class ArgParser
{
2012-09-10 09:01:15 +00:00
public:
~ArgParser(void);
2012-09-10 09:01:15 +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>
2012-09-26 16:17:56 +00:00
ArgParser & add(const char * optname, T * location, const Tv & default_value, const char * description, ArgParserCallBack callback = nullptr, bool dont_show_default = false);
2012-09-10 09:01:15 +00:00
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;
virtual void parse (const char * arg) const = 0;
virtual void show_usage (std::ostream & out) const = 0;
};
template <class T, class Tv>
class ArgEntry : public ArgEntryBase
{
public:
2012-09-26 16:17:56 +00:00
ArgEntry(const char * name,
T * location, const Tv & deafult_value,
ArgParserCallBack callback,
const char * description, bool dont_show_default);
virtual void parse (const char * arg) const;
virtual void show_usage (std::ostream & out) const;
private:
T * location;
T default_value;
ArgParserCallBack callback;
2012-09-26 16:17:56 +00:00
bool dont_show_default;
};
std::vector<ArgEntryBase *> arg_entries, optional_arg_entries;
static const int arg_col_width;
2012-09-10 09:01:15 +00:00
};
template<class T, class Tv>
2012-09-26 16:17:56 +00:00
ArgParser & ArgParser::add(const char * optname, T * location, const Tv & default_value, const char * description, ArgParserCallBack callback, bool dont_show_default)
2012-09-10 09:01:15 +00:00
{
2012-09-10 14:22:01 +00:00
// use "" in case nullptr is provided
if((!optname) || (!optname[0]))
2012-09-26 16:17:56 +00:00
optional_arg_entries.push_back(new ArgEntry<T, Tv>("", location, default_value, callback, "", dont_show_default));
2012-09-10 14:22:01 +00:00
else
2012-09-26 16:17:56 +00:00
arg_entries.push_back(new ArgEntry<T, Tv>(optname, location, default_value, callback, description, dont_show_default));
2012-09-10 09:01:15 +00:00
return *this;
}
template<class T, class Tv>
2012-09-26 16:17:56 +00:00
ArgParser::ArgEntry<T, Tv>::ArgEntry(const char * name, T * location, const Tv & default_value, ArgParserCallBack callback, const char * description, bool dont_show_default)
2012-09-10 09:01:15 +00:00
: ArgEntryBase(name, description, (location != nullptr))
, location(location)
, default_value(default_value)
, callback(callback)
2012-09-26 16:17:56 +00:00
, dont_show_default(dont_show_default)
2012-09-10 09:01:15 +00:00
{
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;
2012-09-11 14:30:12 +00:00
if(!read_value(arg, location))
throw std::string("Invalid argument: ") + arg;
2012-09-10 14:22:01 +00:00
}
if(callback)
(*callback)(arg);
}
2012-09-10 09:01:15 +00:00
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 << " <" << type_name<T>::value() << ">";
2012-09-10 09:01:15 +00:00
}
std::string s = sout.str();
out << s;
for(int i = s.size(); i < arg_col_width; ++i)
out << ' ';
out << " " << description;
if(need_arg && !dont_show_default)
{
2013-01-29 10:39:25 +00:00
out << " (default: ";
dump_value(out, default_value);
out << ")";
}
out << std::endl;
2012-09-10 09:01:15 +00:00
}
} // namespace ArgParser
2012-09-10 09:01:15 +00:00
#endif //ARGPARSER_H__