added option.cc and option.h
This commit is contained in:
parent
152b10dbbd
commit
a334214604
2 changed files with 183 additions and 0 deletions
132
option.cc
Normal file
132
option.cc
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
#include "option.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
|
option_handler::option_handler(const std::string& label,
|
||||||
|
const std::string& opt_chars,
|
||||||
|
const bool _multiple)
|
||||||
|
: handled(false), multiple(_multiple)
|
||||||
|
{
|
||||||
|
option_t opt;
|
||||||
|
|
||||||
|
for (const char * q = label.c_str(); *q; q++)
|
||||||
|
if (*q == '_')
|
||||||
|
opt.long_opt += '-';
|
||||||
|
else
|
||||||
|
opt.long_opt += *q;
|
||||||
|
|
||||||
|
handlers.insert(option_handler_pair(opt.long_opt, this));
|
||||||
|
|
||||||
|
if (! opt_chars.empty()) {
|
||||||
|
if (opt_chars[0] != ':')
|
||||||
|
opt.short_opt = opt_chars[0];
|
||||||
|
|
||||||
|
if (opt_chars[opt_chars.length() - 1] == ':')
|
||||||
|
opt.wants_arg = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
opt.handler = this;
|
||||||
|
|
||||||
|
options.push_back(opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_option(const std::string& opt, const char * arg)
|
||||||
|
{
|
||||||
|
option_handler_map::iterator handler = option_handler::handlers.find(opt);
|
||||||
|
if (handler != option_handler::handlers.end() &&
|
||||||
|
(! (*handler).second->handled || (*handler).second->multiple)) {
|
||||||
|
(*handler).second->handle_option(arg);
|
||||||
|
(*handler).second->handled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void process_option(const option_t& opt,
|
||||||
|
const char * arg = NULL) {
|
||||||
|
if (! opt.handler->handled || opt.handler->multiple) {
|
||||||
|
opt.handler->handle_option(arg);
|
||||||
|
opt.handler->handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_arguments(std::vector<char *>& args, int argc, char ** argv)
|
||||||
|
{
|
||||||
|
int index = 1;
|
||||||
|
for (char ** i = argv + 1; index < argc; i++, index++) {
|
||||||
|
if ((*i)[0] != '-') {
|
||||||
|
args.push_back(*i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --long-option
|
||||||
|
again:
|
||||||
|
if ((*i)[1] == '-') {
|
||||||
|
for (std::vector<option_t>::iterator j
|
||||||
|
= option_handler::options.begin();
|
||||||
|
j != option_handler::options.end();
|
||||||
|
j++)
|
||||||
|
if ((*j).wants_arg) {
|
||||||
|
if (const char * p = std::strchr(*i + 2, '=')) {
|
||||||
|
if ((*j).long_opt == std::string(*i + 2, p - (*i + 2))) {
|
||||||
|
process_option(*j, p + 1);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((*j).long_opt == *i + 2) {
|
||||||
|
process_option(*j, argv[++index]);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((*j).long_opt == *i + 2) {
|
||||||
|
process_option(*j);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "Error: illegal option " << *i << std::endl;
|
||||||
|
std::exit(1);
|
||||||
|
} else {
|
||||||
|
for (std::vector<option_t>::iterator j
|
||||||
|
= option_handler::options.begin();
|
||||||
|
j != option_handler::options.end();
|
||||||
|
j++)
|
||||||
|
if ((*i)[1] == (*j).short_opt) {
|
||||||
|
if ((*j).wants_arg) {
|
||||||
|
process_option(*j, argv[++index]);
|
||||||
|
goto next;
|
||||||
|
} else {
|
||||||
|
process_option(*j);
|
||||||
|
if ((*i)[2]) {
|
||||||
|
std::strcpy(*i + 1, *i + 2);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "Error: illegal option -- " << (*i)[1] << std::endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_environment(char ** envp)
|
||||||
|
{
|
||||||
|
for (char ** p = envp; *p; p++)
|
||||||
|
if (std::strncmp(*p, "LEDGER_", 7) == 0) {
|
||||||
|
std::string opt;
|
||||||
|
char * q;
|
||||||
|
for (q = *p + 7; *q && *q != '='; q++)
|
||||||
|
if (*q == '_')
|
||||||
|
opt += '-';
|
||||||
|
else
|
||||||
|
opt += std::tolower(*q);
|
||||||
|
|
||||||
|
if (*q == '=')
|
||||||
|
process_option(opt, q + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
option.h
Normal file
51
option.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef _OPTION_H
|
||||||
|
#define _OPTION_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct option_handler;
|
||||||
|
|
||||||
|
struct option_t {
|
||||||
|
char short_opt;
|
||||||
|
std::string long_opt;
|
||||||
|
bool wants_arg;
|
||||||
|
option_handler * handler;
|
||||||
|
|
||||||
|
option_t() : short_opt(0), wants_arg(false) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<const std::string, option_handler *> option_handler_map;
|
||||||
|
typedef std::pair<const std::string, option_handler *> option_handler_pair;
|
||||||
|
|
||||||
|
struct option_handler {
|
||||||
|
bool handled;
|
||||||
|
bool multiple;
|
||||||
|
|
||||||
|
static std::vector<option_t> options;
|
||||||
|
static option_handler_map handlers;
|
||||||
|
|
||||||
|
option_handler(const std::string& label,
|
||||||
|
const std::string& opt_chars,
|
||||||
|
const bool _multiple);
|
||||||
|
|
||||||
|
virtual void handle_option(const char * arg = NULL) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool process_option(const std::string& opt, const char * arg = NULL);
|
||||||
|
void process_arguments(std::vector<char *>& args, int argc, char ** argv);
|
||||||
|
void process_environment(char ** envp);
|
||||||
|
|
||||||
|
#define DEF_OPT_HANDLERS() \
|
||||||
|
std::vector<option_t> option_handler::options; \
|
||||||
|
option_handler_map option_handler::handlers
|
||||||
|
|
||||||
|
#define OPT_BEGIN(tag, chars, multi) \
|
||||||
|
static struct tag ## _handler : public option_handler { \
|
||||||
|
tag ## _handler() : option_handler(#tag, chars, multi) {} \
|
||||||
|
virtual void handle_option(const char * optarg)
|
||||||
|
|
||||||
|
#define OPT_END(tag) } tag ## _handler_obj
|
||||||
|
|
||||||
|
#endif // _OPTION_H
|
||||||
Loading…
Add table
Reference in a new issue