/* Copyright (C) 2000 Daniel Heck dheck@ix.urz.uni-heidelberg.de */ #ifndef __ARGP_HH #define __ARGP_HH #include #include #include template class basic_argp { public: struct option { IDTYPE id; string param; void set(IDTYPE i, const string& p) { this->id = i; this->param = p; } }; private: struct _optiondef { _optiondef() {} _optiondef(IDTYPE i, char a, const string& l, bool t = false) : longopt(l), id(i), shortopt(a), takesparam(t) {} string longopt; IDTYPE id; char shortopt; bool takesparam; }; // Private Variables. typedef list<_optiondef>::iterator option_iterator; list<_optiondef> _opts; list _arglist; list _arguments; unsigned _status; IDTYPE _errorid, _argumentid; // Private functions. bool getlongopt(option& opt, const string& arg); bool getshortopt(option& opt, const string& arg); template static Iter find_prefix(Iter beg, Iter end, const string& val) { typename string::size_type s = val.size(); for (; beg != end; ++beg) if ((beg->longopt).compare(val, 0, s) == 0) break; return beg; } public: enum { missingparambit = 1, unknownoptbit = 2, ambiguousoptbit = 4, invalidparambit = 8, eofbit = 16, }; // Constructor. basic_argp(IDTYPE argumentid, IDTYPE errorid) : _status (0) , _errorid (errorid) , _argumentid (argumentid) {} // Error status. bool invalidparam() const { return _status & invalidparambit; } bool ambiguousopt() const { return _status & ambiguousoptbit; } bool unknownopt() const { return _status & unknownoptbit; } bool missingparam() const { return _status & missingparambit; } void eof() const { return _status & eofbit; } void clearbit(int mask) { _status &= ~mask; } void setbit(int mask) { _status |= mask; } // Functions. void def(IDTYPE id, char abbr, const char* name, bool param = false) { _opts.push_back(_optiondef(id, abbr, string("--") +name, param)); } template void feed(ForwardIterator begin, ForwardIterator end) { copy(begin, end, back_inserter(_arglist)); clearbit(eofbit); } bool getopt(option& opt); }; template bool basic_argp:: getlongopt(option& opt, const string& arg) { if (arg.size() == 2) { copy(_arglist.begin(), _arglist.end(), back_inserter(_arguments)); _arglist.clear(); return false; } string::const_iterator eqpos = find(arg.begin(), arg.end(), '='); string optname(arg.begin(), eqpos); option_iterator i, j; j = i = find_prefix(_opts.begin(), _opts.end(), optname); if (i == _opts.end()) { _status |= unknownoptbit; opt.set(_errorid, optname); } else if (find_prefix(++j, _opts.end(), optname) != _opts.end()) { _status |= ambiguousoptbit; opt.set(_errorid, optname); } else if (i->takesparam) { if (eqpos != arg.end()) { opt.id = i->id; opt.param.assign(eqpos+1, arg.end()); } else if (!_arglist.empty()) { opt.set(i->id, _arglist.front()); _arglist.pop_front(); } else { opt.set(_errorid, optname); _status |= missingparambit; } } else if (eqpos != arg.end()) { _status |= invalidparambit; opt.set(_errorid, optname); } else opt.id = i->id; return true; } template bool basic_argp:: getshortopt(option& opt, const string& arg) { option_iterator i = _opts.begin(); for (; i != _opts.end(); ++i) if (i->shortopt == arg[1]) break; if (i == _opts.end()) { _status |= unknownoptbit; opt.param = arg.substr(0, 2); } else if (i->takesparam) { opt.set(i->id, arg.substr(2)); if (opt.param.empty()) { if (!_arglist.empty()) { opt.param = _arglist.front(); _arglist.pop_front(); } else { opt.set(_errorid, arg.substr(0, 2)); _status |= missingparambit; } } } else { opt.id = i->id; string newarg("-"); newarg.append(arg.begin()+2, arg.end()); if (newarg != "-") _arglist.push_front(newarg); } return true; } template bool basic_argp:: getopt(option& opt) { if (_status) return false; while (!_arglist.empty()) { string arg = _arglist.front(); _arglist.pop_front(); if (arg.size() >= 2 && arg[0] == '-') { if (arg[1] == '-') { if (this->getlongopt(opt, arg)) return true; } else if (this->getshortopt(opt, arg)) return true; } else _arguments.push_back(arg); } if (!_arguments.empty()) { opt.id = _argumentid; opt.param = _arguments.front(); _arguments.pop_front(); return true; } _status |= eofbit; opt.id = _errorid; return false; } typedef basic_argp argp; #endif