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
|
|
|
|
|
2012-09-11 13:52:46 +00:00
|
|
|
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
|
|
|
{
|
2012-09-11 13:52:46 +00:00
|
|
|
std::istringstream sin(arg);
|
2012-09-11 14:30:12 +00:00
|
|
|
return ((sin >> (*location)) && (sin.eof()));
|
2012-09-11 13:52:46 +00:00
|
|
|
}
|
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
|
|
|
|
2012-09-11 13:52:46 +00:00
|
|
|
template<class T>
|
|
|
|
void dump_value(std::ostream & out, const T & v)
|
|
|
|
{
|
|
|
|
out << v;
|
|
|
|
}
|
2012-09-10 09:01:15 +00:00
|
|
|
|
2012-09-11 13:52:46 +00:00
|
|
|
extern void dump_value(std::ostream & out, const std::string & v);
|
2012-09-10 09:01:15 +00:00
|
|
|
|
|
|
|
|
2012-09-11 13:52:46 +00:00
|
|
|
class ArgParser
|
|
|
|
{
|
2012-09-10 09:01:15 +00:00
|
|
|
public:
|
2012-09-11 13:52:46 +00:00
|
|
|
~ArgParser(void);
|
2012-09-10 09:01:15 +00:00
|
|
|
|
2012-09-11 13:52:46 +00:00
|
|
|
typedef void (*ArgParserCallBack) (const char * arg);
|
2012-09-10 09:01:15 +00:00
|
|
|
|
2012-09-11 13:52:46 +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
|
|
|
|
2012-09-11 13:52:46 +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);
|
|
|
|
|
2012-09-11 13:52:46 +00:00
|
|
|
|
|
|
|
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;
|
2012-09-11 13:52:46 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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))
|
2012-09-11 13:52:46 +00:00
|
|
|
, 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)
|
|
|
|
{
|
2012-09-26 16:17:56 +00:00
|
|
|
sout << " <arg>";
|
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 << ' ';
|
2013-01-28 22:26:07 +00:00
|
|
|
|
|
|
|
out << " " << description;
|
|
|
|
|
|
|
|
if(need_arg && !dont_show_default)
|
|
|
|
{
|
|
|
|
out << " (default is ";
|
|
|
|
dump_value(out, default_value);
|
|
|
|
out << ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
out << std::endl;
|
2012-09-10 09:01:15 +00:00
|
|
|
}
|
|
|
|
|
2012-09-11 13:52:46 +00:00
|
|
|
} // namespace ArgParser
|
|
|
|
|
2012-09-10 09:01:15 +00:00
|
|
|
#endif //ARGPARSER_H__
|