Argument({"duid"_Opt,'u'_Opt,Option::ArgumentRequired}, [](string,string a){setduid(a);}),
Argument({"dev"_Opt,"device"_Opt,Option::ArgumentRequired}, [](string,string a){device=a;}),
Argument({"script"_Opt,"s"_Opt,Option::ArgumentRequired}, [](string, string a){script=a;}),
+ Argument({"file"_Opt,"config"_Opt,Option::ArgumentRequired}, [&](string,string f){pp.parseFile(f);}),
});
pp.setErrorCallback([&](string s,Error e){fprintf(stderr,"Syntax error in argument %s: %s\n",s.data(),error2String(e).data());printhelp();exit(1);});
+ pp.setNonOptionCallback([](string s){device=s;});
pp.parseArguments(argc,argv);
if(DUIDLEN==0){
#include "optparse.h"
-#include<algorithm>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <functional>
+#include <locale>
+
using namespace std;
using namespace OptParse;
void Parser::parseArguments(std::list< std::string > argv,bool ig) const
{
if(ig)argv.pop_front();
- for(auto arg:argv)parseArgument(arg);
+ for(auto arg:argv)parseArgument(arg,true);
}
-#include <iostream>
-void Parser::parseArgument(const std::string& arg)const
+static inline string trim(std::string s) {
+ static auto pred=[](char c){return !std::isspace(c);};
+ s.erase(s.begin(),find_if(s.begin(),s.end(),pred));
+ s.erase(find_if(s.rbegin(),s.rend(),pred).base(),s.end());
+ return s;
+}
+
+void Parser::parseArgument(const std::string& arg,bool useprefix)const
{
- const auto prfs=m_prefix.size();
+ const auto prfs=useprefix?m_prefix.size():0;
//is it an option style argument?
- if(m_prefix.empty() || arg.substr(0,prfs)==m_prefix){
+ if(!useprefix || m_prefix.empty() || arg.substr(0,prfs)==m_prefix){
//parse it
std::string name,val;
auto pe=arg.find('=',prfs);
+ bool haveArg=false;
if(pe==arg.npos)
- name=arg.substr(prfs);
+ name=trim(arg.substr(prfs));
else{
- name=arg.substr(prfs,pe-prfs);
- val=arg.substr(pe);
+ name=trim(arg.substr(prfs,pe-prfs));
+ val=trim(arg.substr(pe+1));
+ haveArg=true;
+ }
+ //find option
+ bool found=false;
+ for(auto argi:m_args){
+ if(argi.matches(name)){
+ found=true;
+ if(argi.needArg()==Option::NeedArg::ReqArg&&!haveArg){
+ if(m_ecall)m_ecall(arg,Error::MissingArgument);
+ return;
+ }
+ if(argi.needArg()==Option::NeedArg::NoArg&&haveArg){
+ if(m_ecall)m_ecall(arg,Error::UnexpectedArgument);
+ return;
+ }
+ argi(name,val);
+ break;
+ }
+ }
+ if(found){
+ if(m_call)m_call(name,val);
+ }else{
+ if(m_ecall)m_ecall(arg,Error::UnknownOption);
}
- cerr<<"opt "<<name<<" -- "<<val<<" : "<<prfs<<":"<<pe;
}else{
//raise as non-option
if(m_ncall)m_ncall(arg);
- cerr<<"nonopt "<<arg<<endl;
}
}
+
+void Parser::parseFile(const std::string& filename) const
+{
+ ifstream in(filename);
+ parseFile(in);
+}
+
+void Parser::parseFile(std::istream& stream) const
+{
+ //get lines
+ while(stream.good() && !stream.eof()){
+ string line;
+ getline(stream,line);
+ line=trim(line);
+ //check whether line empty
+ if(line.empty())continue;
+ //is it a comment
+ if(line[0]=='#')continue;
+ //normal parsing
+ parseArgument(line,false);
+ }
+}
+
+
typedef std::function<void(std::string,std::string)>OptionCallback;
-enum class Error{Ok=0,UnknownOption,MissingArgument};
+enum class Error{Ok=0,UnknownOption,MissingArgument,UnexpectedArgument};
typedef std::function<void(std::string,Error)>ErrorCallback;
inline std::string error2String(Error e)
case Error::Ok:return "No Error";
case Error::UnknownOption:return "unkown option";
case Error::MissingArgument:return "argument expected";
+ case Error::UnexpectedArgument:return "no argument expected";
default:return "unknown error";
}
}
void setOption(const Option&);
void setCallback(OptionCallback oc){m_call=oc;}
+
+ void operator()(std::string name,std::string value)const
+ {if(m_call)m_call(name,value);}
};
class Parser
void parseFile(const std::string &filename)const;
void parseFile(std::istream &stream)const;
private:
- void parseArgument(const std::string&)const;
+ void parseArgument(const std::string&,bool)const;
};
};//End of namespace