vmime/tests/lib/unit++/optmap.cc
Laurent Richard 27fb7a5b96 New unit test system: Unit++.
Added test for header::getAllByName/Type
2004-10-07 11:02:31 +00:00

146 lines
2.8 KiB
C++

// Copyright (C) 2001 Claus Dræby
// Terms of use are in the file COPYING
#include <iostream>
#include <cstdlib>
#include "optmap.h"
using namespace std;
using namespace options_utils;
optmap::optmap(const char* usage)
: i(1), prog("program"), tail(usage)
{
}
optmap::~optmap()
{
for (group_t::iterator p = group.begin(); p != group.end(); ++p)
delete p->first;
}
optmap& optmap::add(const char* c, cmd* h)
{
if (cmds.find(c) != cmds.end())
throw invalid_argument(string("duplicated option: ")+c);
cmds[c] = h;
if (group[h].size() == 0)
gvec.push_back(h);
group[h].push_back(c);
return *this;
}
optmap& optmap::alias(const char* new_opt, const char* old_opt)
{
cmd* h = cmds[old_opt];
if (!h)
throw invalid_argument(string("no alias: ")+old_opt);
return add(new_opt, h);
}
bool optmap::parse(int c, const char** v)
{
argc = c;
argv = v;
prog = argv[0];
for (; i < argc; ++i) {
multichar = false;
const char* s = argv[i];
size_t l = strlen(s);
if (*s != '-' || l == 1)
return true;
if (s[1] == '-') {
if (l == 2) { // end of options marker `--'
++i;
return true;
}
if (!do_cmd(s+2))
return false;
} else {
char cmd[2];
cmd[1] = '\0';
multichar = l > 2;
first_multi = true;
for (const char* p = s+1; *p; ++p) {
cmd[0] = *p;
if (!do_cmd(cmd))
return false;;
first_multi = false;
if (!multichar) // get_arg used it
break;
}
}
}
return true;
}
const char* optmap::get_arg()
{
if (multichar) {
if (!first_multi) {
cerr << "internal option requires argument " << argv[i] << endl;
return 0;
}
multichar = false;
return argv[i]+2;
}
return i < argc - 1 ? argv[++i] : 0;
}
void optmap::usage(bool abort)
{
cerr << "usage: " << prog;
for (gvec_t::iterator p = gvec.begin(); p != gvec.end(); ++p) {
cmd* h = *p;
vector<string>& v(group[h]);
string arg = h->arg();
bool need_par = arg.size() > 0 && v.size() > 1;
bool first = true;
cerr << " [";
if (need_par)
cerr << "(";
for (vector<string>::iterator s = v.begin(); s != v.end(); ++s) {
cerr << (first ? " " : " | ") << (s->size() != 1 ? "--":"-") << *s;
first = false;
}
if (need_par)
cerr << ")";
if (arg.size())
cerr << ' ' << arg;
cerr << " ]";
}
cerr << (tail.size() ? " " : "") << tail << endl;
if (abort)
exit(1);
}
bool optmap::do_cmd(const string& opt)
{
cmd* c = cmds[opt];
if (!c) {
cerr << "unknown option: " << opt << endl;
return false;
}
return c->do_cmd(this);
}
bool opt_int::do_cmd(optmap* om)
{
const char* arg = om->get_arg();
if (!arg)
return false;
char* end;
int v = strtol(arg, &end, 10);
if (*end) {
cerr << "failed to parse int argument: " << arg << endl;
return false;
}
val = v;
return true;
}
bool opt_string::do_cmd(optmap* om)
{
const char* arg = om->get_arg();
if (!arg)
return false;
val = arg;
return true;
}