📄 args2.cc
字号:
//
// args.cc
//
// $Id: args2.cc,v 1.1.1.1 2001/02/28 00:28:35 cstolte Exp $
//
#include <iostream>
#include <sgl/args2.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
static char *
Strdup(const char *c2) {
char *ret = 0;
if (c2) {
ret = new char[strlen(c2) + 1];
strcpy(ret, c2);
}
return ret;
}
class Arg {
public:
Arg(const char *sw, const char *helpstr, bool req, int n);
virtual ~Arg();
virtual void printVal(std::ostream &os) const = 0;
virtual void set(int index, const char *str) = 0;
virtual bool process(char **&argv);
void help(std::ostream &os) const;
void print(std::ostream &os) const;
const char *get_switch() const { return c_switch; }
bool requiredButNotSet() const { return required && !valSet; }
Arg *next;
protected:
char *helpstr;
char *c_switch;
int num;
bool required, valSet;
};
Arg::Arg(const char *sw, const char *hstr, bool req, int n)
{
if (!strcmp(sw, "help")) {
std::cerr << "sgl/args: sorry. '-help' switch is reserved." << std::endl;
exit(1);
}
c_switch = new char[strlen(sw) + 2];
c_switch[0] = '\0';
strcat(c_switch, "-");
strcat(c_switch, sw);
helpstr = Strdup(hstr);
required = req;
valSet = false;
num = n;
next = 0;
}
Arg::~Arg()
{
delete[] helpstr;
delete[] c_switch;
}
void
Arg::help(std::ostream &os) const
{
os << "[" << c_switch << " (" << helpstr << ")";
if (num != 1)
os << " x " << num;
os << "]";
}
void
Arg::print(std::ostream &os) const
{
help(os);
os << " = ";
printVal(os);
}
bool
Arg::process(char **&argv) {
if (!strcmp(argv[0], get_switch())) {
for (int i = 0; i < num; ++i) {
++argv;
if (!argv[0]) {
std::cerr << "sgl/args: not enough arguments for '" <<
get_switch() << "' switch." << std::endl;
exit(1);
}
set(i, *argv);
}
++argv;
valSet = true;
return true;
}
return false;
}
class IntArg : public Arg {
public:
IntArg(const char *sw, const char *helps, bool req, int num, int *i)
: Arg(sw, helps, req, num), ptr(i) { }
void printVal(std::ostream &os) const
{ for (int i = 0; i < num; ++i) os << ptr[i] << " "; }
void set(int index, const char *str) { ptr[index] = atoi(str); }
private:
int *ptr;
};
class DoubleArg : public Arg {
public:
DoubleArg(const char *sw, const char *helps, bool req,
int num, double *d)
: Arg(sw, helps, req, num), ptr(d) { }
void printVal(std::ostream &os) const
{ for (int i = 0; i < num; ++i) os << ptr[i] << " "; }
void set(int index, const char *str) { ptr[index] = atof(str); }
private:
double *ptr;
};
class FloatArg : public Arg {
public:
FloatArg(const char *sw, const char *helps, bool req,
int num, float *f)
: Arg(sw, helps, req, num), ptr(f) { }
void printVal(std::ostream &os) const
{ for (int i = 0; i < num; ++i) os << ptr[i] << " "; }
void set(int index, const char *str) { ptr[index] = atof(str); }
private:
float *ptr;
};
class StringArg : public Arg {
public:
StringArg(const char *sw, const char *helps, bool req,
int num, char **str)
: Arg(sw, helps, req, num), ptr(str) { }
void printVal(std::ostream &os) const
{ for (int i = 0; i < num; ++i) os << ptr[i] << " "; }
void set(int index, const char *str)
{ ptr[index] = Strdup(str); }
private:
char **ptr;
};
class BoolArg : public Arg {
public:
BoolArg(const char *sw, const char *helps, bool *b)
: Arg(sw, helps, false, 1), ptr(b) { }
bool process(char **&argv);
void printVal(std::ostream &os) const
{ os << *ptr ? "true" : "false"; }
void set(int , const char *) { *ptr = !*ptr; }
private:
bool *ptr;
};
bool
BoolArg::process(char **&argv) {
if (!strcmp(argv[0], get_switch())) {
*ptr = !*ptr;
++argv;
valSet = true;
return true;
}
return false;
}
////////////
// ArgParser2
ArgParser2::ArgParser2() {
item_list = 0;
added_floaters = false;
floaters_required = false;
wanted_floaters = floaters_pos = 0;
floaters = 0;
floater_help = 0;
}
ArgParser2::~ArgParser2() {
delete[] floater_help;
Arg *arg = item_list;
while (arg) {
Arg *next = arg->next;
delete arg;
arg = next;
}
}
void
ArgParser2::optional(const char *c, const char *helpstr,
int *i, int num) {
Arg *a = new IntArg(c, helpstr, false, num, i);
add_arg(a);
}
void
ArgParser2::optional(const char *c, const char *helpstr,
double *d, int num) {
Arg *a = new DoubleArg(c, helpstr, false, num, d);
add_arg(a);
}
void
ArgParser2::optional(const char *c, const char *helpstr,
float *f, int num) {
Arg *a = new FloatArg(c, helpstr, false, num, f);
add_arg(a);
}
void
ArgParser2::optional(const char *c, const char *helpstr,
char **str, int num) {
Arg *a = new StringArg(c, helpstr, false, num, str);
add_arg(a);
}
void
ArgParser2::optional(const char *c, const char *helpstr, bool *b) {
Arg *a = new BoolArg(c, helpstr, b);
add_arg(a);
}
void
ArgParser2::optional(char ***fl, const char *helpstr, int num) {
if (added_floaters) {
std::cerr << "sgl/args: you've already added floating string arguments."
<< std::endl;
exit(1);
}
added_floaters = true;
wanted_floaters = num;
floaters = new char *[wanted_floaters];
for (int i = 0; i < wanted_floaters; ++i)
floaters[i] = 0;
*fl = floaters;
floater_help = Strdup(helpstr);
floaters_required = false;
}
void
ArgParser2::optional(char **floater, const char *helpstr) {
if (added_floaters) {
std::cerr << "sgl/args: you've already added floating string arguments."
<< std::endl;
exit(1);
}
floaters = floater;
added_floaters = true;
wanted_floaters = 1;
floater_help = Strdup(helpstr);
floaters_required = false;
}
void
ArgParser2::required(const char *c, const char *helpstr,
int *i, int num) {
Arg *a = new IntArg(c, helpstr, true, num, i);
add_arg(a);
}
void
ArgParser2::required(const char *c, const char *helpstr,
double *d, int num) {
Arg *a = new DoubleArg(c, helpstr, true, num, d);
add_arg(a);
}
void
ArgParser2::required(const char *c, const char *helpstr,
float *f, int num) {
Arg *a = new FloatArg(c, helpstr, true, num, f);
add_arg(a);
}
void
ArgParser2::required(const char *c, const char *helpstr,
char **str, int num) {
Arg *a = new StringArg(c, helpstr, true, num, str);
add_arg(a);
}
void
ArgParser2::required(char ***fl, const char *helpstr, int num) {
if (added_floaters) {
std::cerr << "sgl/args: you've already added floating string arguments."
<< std::endl;
exit(1);
}
added_floaters = true;
wanted_floaters = num;
floaters = new char *[wanted_floaters];
for (int i = 0; i < wanted_floaters; ++i)
floaters[i] = 0;
*fl = floaters;
floater_help = Strdup(helpstr);
floaters_required = true;
}
void
ArgParser2::required(char **floater, const char *helpstr) {
if (added_floaters) {
std::cerr << "sgl/args: you've already added floating string arguments."
<< std::endl;
exit(1);
}
floaters = floater;
added_floaters = true;
wanted_floaters = 1;
floater_help = Strdup(helpstr);
floaters_required = true;
}
void
ArgParser2::add_arg(Arg *a) {
Arg *arg = item_list;
while (arg) {
if (!strcmp(a->get_switch(), arg->get_switch())) {
std::cerr << "sgl/args: switch '" << a->get_switch() <<
"' is already taken." << std::endl;
exit(1);
}
arg = arg->next;
}
a->next = item_list;
item_list = a;
}
void
ArgParser2::process(const char *prog_name, int, char **argv) {
++argv;
while (*argv) {
if (!strcmp(*argv, "-help")) {
print_help(prog_name);
exit(1);
}
Arg *arg = item_list;
while (arg) {
if (arg->process(argv))
break;
arg = arg->next;
}
if (!arg) {
// nothing matched. floating arg?
if (wanted_floaters == 0 || wanted_floaters == floaters_pos) {
// no floaters wanted or we already got as many of
// them as we want
std::cerr << prog_name << ": unrecognized argument " << *argv
<< std::endl;
print_help(prog_name);
exit(1);
}
else {
floaters[floaters_pos++] = Strdup(*argv);
++argv;
}
}
}
Arg *arg = item_list;
bool some_missing = false;
while (arg) {
if (arg->requiredButNotSet()) {
some_missing = true;
std::cerr << prog_name << ": '-" << arg->get_switch()
<< "' switch must be set." << std::endl;
}
arg = arg->next;
}
if (floaters_required && floaters_pos < wanted_floaters) {
some_missing = true;
std::cerr << prog_name << ": " << wanted_floaters << " " <<
floater_help << " must be specified." << std::endl;
}
if (some_missing == true) {
print_help(prog_name);
exit(1);
}
}
void
ArgParser2::print_help(const char *prog_name) const {
std::cerr << "usage: " << prog_name << " ";
if (added_floaters) {
std::cerr << "[" << floater_help;
if (wanted_floaters > 1)
std::cerr << " x " << wanted_floaters;
std::cerr << "] ";
}
Arg *a = item_list;
while (a) {
a->help(std::cerr);
std::cerr << ' ';
a = a->next;
}
std::cerr << std::endl;
}
std::ostream &
operator<<(std::ostream &os, const ArgParser2 &ap) {
Arg *a = ap.item_list;
while (a) {
a->print(os);
os << std::endl;
a = a->next;
}
if (ap.floaters && ap.floaters_pos) {
os << ap.floater_help << ": ";
for (int i = 0; i < ap.floaters_pos; ++i)
std::cerr << ap.floaters[i] << " ";
os << std::endl;
}
return os;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -