⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 args.cc

📁 一个用MATLAB语言编写的摄像机标定工具箱,内容丰富
💻 CC
字号:
//
// args.cc
//
// $Id: args.cc,v 1.1.1.1 2001/02/28 00:28:35 cstolte Exp $
//

#include <iostream>
#include <sgl/args.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

/////////////////////////////////////////////////////////////////////////////
// Inside the argument parser, we keep a list of the arguments that the
// user has told us about--each one is recorded in an APItem in
// item_list. The "floating argument"--the optional string argument that
// isn't prefixed by any switch--is recorded separately. floating_arg 
// holds a pointer to it, floating_name holds a description of what
// it is (for error messages), floating_required is true if it must be
// specified.

ArgParser::ArgParser() {
    floating_arg = 0;
    floating_name = 0;
    floating_required = false;
    floating_set = false;
    item_list = 0;
}

ArgParser::~ArgParser() {
    delete floating_name;

    APItem *i = item_list;
    while (i) {
	APItem *next = i->next;
	delete i;
	i = next;
    }
}

/////////////////////////////////////////////////////////////////////////////
// Here's where the floating argument is added to the arg parser's internal
// state. 

void 
ArgParser::operator()(char **fl, const char *float_name,
		      ArgRequired required) {
    floating_arg = fl;
    delete [] floating_name;
    floating_name = new char[1 + strlen(float_name)];
    strcpy(floating_name, float_name);
    floating_required = required == Required ? true : false;
}

////////////////////////////////////////////////////////////////////////////
// And here's where all other types of arguments are added to item_list.
// operator() is overloaded based on the type of the argument that we're
// adding. By default, arguments aren't required, and only one value
// after a switch is used to intialize its argument.

void 
ArgParser::operator()(char c, const char *str, int *i,
		      ArgRequired req, u_int num) {
    APItem *item = new APItem;
    item->c_switch = c;
    item->str_switch = new char[1 + strlen(str)];
    strcpy(item->str_switch, str);    
    
    item->num = num;
    item->required = req == Required ? true : false;
    item->initialized = false;
    item->type = APItem::I;
    item->i = i;
    
    add_item_to_list(item);
}

void 
ArgParser::operator()(char c, const char *str, double *d,
		      ArgRequired req, u_int num) {
    APItem*item = new APItem;
    item->c_switch = c;
    item->str_switch = new char[1 + strlen(str)];
    strcpy(item->str_switch, str);    
    
    item->num = num;
    item->required = req == Required ? true : false;
    item->initialized = false;
    item->type = APItem::D;
    item->d = d;
    
    add_item_to_list(item);
}

void 
ArgParser::operator()(char c, const char *str, u_int *ui,
		      ArgRequired req, u_int num) {
    APItem *item = new APItem;
    item->c_switch = c;
    item->str_switch = new char[1 + strlen(str)];
    strcpy(item->str_switch, str);    
    
    item->num = num;
    item->required = req == Required ? true : false;
    item->initialized =  false;
    item->type = APItem::UI;
    item->ui = ui;
    
    add_item_to_list(item);
}

void 
ArgParser::operator()(char c, const char *str, char **s, 
		      ArgRequired req, u_int num) {
    APItem *item = new APItem;
    item->c_switch = c;
    item->str_switch = new char[1 + strlen(str)];
    strcpy(item->str_switch, str);    
    
    item->num = num;
    item->required = req == Required ? true : false;
    item->initialized = false;
    item->type = APItem::S;
    item->s = s;
    
    add_item_to_list(item);
}

/////////////////////////////////////////////////////////////////////////////
// Switches for booleans are a bit special, since no argument after them
// is looked at--each time a boolean's switch is found, it's just toggled.
// Thus, we don't need to worry about stuff like whether it's a 
// required switch, or how many arguments after it to process.

void 
ArgParser::operator()(char c, const char *str, bool *b) {
    u_int num = 0;
    bool req = false;

    APItem *item = new APItem;
    item->c_switch = c;
    item->str_switch = new char[1 + strlen(str)];
    strcpy(item->str_switch, str);    

    item->num = num;
    item->required = req;
    item->initialized = false;
    item->type = APItem::B;
    item->b = b;

    add_item_to_list(item);
}

void 
ArgParser::add_item_to_list(APItem *item) {
    assert(item);
    if(item->c_switch == 'h' || !strcmp(item->str_switch,"help")) {
	std::cerr << "ArgParser: '-h' and '--help' are reserved for help!"
	     << std::endl;
	exit(1);
    }

    APItem *i = item_list;
    while (i) {
	if(i->c_switch == item->c_switch ||
	   !strcmp(i->str_switch, item->str_switch)) {
	    std::cerr << "ArgParser: switch '-" << i->c_switch << "' or '--"
		 << i->str_switch << "' is already taken." << std::endl;
	    exit(1);
	}
	i = i->next;
    }
    item->next = item_list;
    item_list = item;
}

void 
ArgParser::process(const char *prog_name, int, char **argv) {
    ++argv;
    while(*argv) {
	if(*argv[0]!='-') {
	    if(!floating_arg || floating_set == true) {
		std::cerr << prog_name << ": unknown argument " << argv[0]
		     << std::endl;
	    }
	    else {
		*floating_arg = new char[1 + strlen(*argv)];
		strcpy(*floating_arg, *argv);
		floating_set = true;
	    }
	}
	else {
	    if(argv[0][1] == '-') {
		const char *long_switch = &argv[0][2];
		if (!strcmp(long_switch, "help"))
		    print_help(prog_name);
		else {
		    APItem *i = item_list;
		    while(i) {
			if (!strcmp(i->str_switch, long_switch)) {
			    if(i->type == APItem::B) {
				if(*i->b == false)
				    *i->b = true;
				else
				    *i->b = false;
				break;
			    }
			    else {
				i->initialized = true;
				for(u_int k = 0; k < i->num; ++k) {
				    ++argv;
				    if(!*argv) {
					std::cerr << prog_name <<
					    ": not enough arguments for "
					     << i->str_switch << " switch." 
					     << std::endl;
					exit(1);
				    }
				    switch(i->type) {
				    case APItem::I:
					i->i[k] = atoi(*argv);
					break;
				    case APItem::UI:
					i->ui[k] = atoi(*argv);
					break;
				    case APItem::D:
					i->d[k] = atof(*argv);
					break;
				    case APItem::S:
					if (i->s[k])
					    delete[] i->s[k];
					i->s[k] = new char[1 + strlen(*argv)];
					strcpy(i->s[k], *argv);
					break;
				      default:
					break;
				    }
				}
			    }
			    break;
			}
			i = i->next;
		    }
		    if(!i) {
			std::cerr << prog_name << ": unknown switch '--" <<
			    long_switch << "'" << std::endl;
		    }
		}
	    }
	    else {
		char short_switch = argv[0][1];
		if(short_switch =='h')
		    print_help(prog_name);
		else {
		    APItem *i = item_list;
		    while(i) {
			if(i->c_switch == short_switch) {
			    if(i->type == APItem::B) {
				if(*i->b == false)
				    *i->b = true;
				else
				    *i->b = false;
				break;
			    }
			    else {
				i->initialized = true;
				for(u_int k = 0; k< i->num; ++k) {
				    ++argv;
				    if(!*argv) {
					std::cerr << prog_name << 
					    ": not enough arguments for "
					     << i->str_switch << " switch." 
					     << std::endl;
					exit(1);
				    }
				    switch(i->type) {
				    case APItem::I:
					i->i[k] = atoi(*argv);
					break;
				    case APItem::UI:
					i->ui[k] = atoi(*argv);
					break;
				    case APItem::D:
					i->d[k] = atof(*argv);
					break;
				    case APItem::S:
					if (i->s[k])
					    delete[] i->s[k];
					i->s[k] = new char[1 + strlen(*argv)];
					strcpy(i->s[k], *argv);
					break;
				    default:
					break;
				    }
				}
			    }
			    break;
			}
			i = i->next;
		    }
		    if(!i) {
			std::cerr << prog_name << ": unknown switch '-" <<
			    short_switch << "'" << std::endl;
		    }
		}
	    }
	}
	++argv;
    }

    bool missing_some = false;
    if(floating_required == true) {
	assert(floating_arg);
	if(!*floating_arg) {
	    std::cerr << prog_name << ": " << floating_name <<
		" must be specified." <<std::endl;
	    missing_some = true;
	}
    }
    APItem *i = item_list;
    while(i) {
	if(i->required == true && i->initialized == false) {
	    missing_some = true;
	    std::cerr << prog_name << ": " << i->str_switch <<
		" argument must be specified." << std::endl;
	}
	i = i->next;
    }
    if(missing_some == true) {
	print_help(prog_name);
	exit(1);
    }
#ifdef DEBUG
    print_values_of_all_switches();
#endif /* DEBUG */
}

void
ArgParser::print_help(const char *prog_name) const {
    std::cerr << "usage: " << prog_name << " [-h] [--help] ";
    if (floating_arg)
	std::cerr << "[" << floating_name << "] ";

    APItem *i = item_list;
    while(i) {
	std::cerr << "[-" << i->c_switch;
	print_args_for_item(std::cerr, i);
	std::cerr << "] [--" << i->str_switch;
	print_args_for_item(std::cerr, i);
	std::cerr << "] ";
	i = i->next;
    }
    std::cerr << std::endl;
    exit(0);
}

void ArgParser::print_args_for_item(std::ostream &os,APItem *item) const {
    if (item->type == APItem::B)
	return;

    for(u_int i = 0; i < item->num; ++i) {
	switch(item->type) {
	case APItem::I:
	    os<<" int";
	    break;
	case APItem::UI:
	    os<<" u_int";
	    break;
	case APItem::D:
	    os<<" double";
	    break;
	case APItem::S:
	    os<<" str";
	    break;
	default:
	    break;
	}
    }
}

void 
ArgParser::print_values_of_all_switches() const {
    if (floating_arg)
	std::cerr << floating_name << " = " << *floating_arg << std::endl;

    APItem *i = item_list;
    while(i) {
	std::cerr << i->str_switch << " = ";
	for(u_int u = 0; u < i->num; ++u) {
	    switch(i->type) {
	    case APItem::B:
		if(*i->b)
		    std::cerr << "true";
		else
		    std::cerr << "false";
		break;
	    case APItem::I:
		std::cerr << i->i[u];
		break;
	    case APItem::UI:
		std::cerr << i->ui[u];
		break;
	    case APItem::D:
		std::cerr << i->d[u];
		break;
	    case APItem::S:
		std::cerr << i->s[u];
		break;
	    }
	    std::cerr << ' ';
	}
	std::cerr << std::endl;
	i = i->next;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -