add config file parsing
authorKonrad Rosenbaum <konrad@silmor.de>
Mon, 30 Apr 2012 13:51:08 +0000 (15:51 +0200)
committerKonrad Rosenbaum <konrad@silmor.de>
Mon, 30 Apr 2012 13:51:08 +0000 (15:51 +0200)
client.cpp
optparse.cpp
optparse.h

index 7087ba0..3bc2841 100644 (file)
@@ -315,8 +315,10 @@ int main(int argc,char**argv)
                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){
index c85a267..38b6b1a 100644 (file)
 
 #include "optparse.h"
 
-#include<algorithm>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <functional> 
+#include <locale>
+
 
 using namespace std;
 using namespace OptParse;
@@ -84,28 +89,80 @@ void Parser::parseArguments(int argc, const char *const* argv,bool ig) const
 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);
+       }
+}
+
+
index 84e58c2..00c4a1c 100644 (file)
@@ -53,7 +53,7 @@ inline Option operator"" _Opt(char s){std::string st;st+=s;return Option(st);}
 
 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)
@@ -62,6 +62,7 @@ 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";
        }
 }
@@ -91,6 +92,9 @@ class Argument
                
                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
@@ -125,7 +129,7 @@ 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