Implement ArgvParser, fix log system binary search.
authorethereal <ethereal.visage@gmail.com>
Tue, 16 Apr 2013 14:39:46 +0000 (08:39 -0600)
committerethereal <ethereal.visage@gmail.com>
Tue, 16 Apr 2013 14:39:46 +0000 (08:39 -0600)
data/arguments.config [new file with mode: 0644]
data/skeleton.config
src/MessageSystem.cpp
src/config/ArgvParser.cpp
src/config/TreeNode.cpp
src/config/TreeNode.h
src/main.cpp

diff --git a/data/arguments.config b/data/arguments.config
new file mode 100644 (file)
index 0000000..25890b5
--- /dev/null
@@ -0,0 +1,23 @@
+arguments: {
+
+long_form: {
+
+help: {
+    type: "boolean";
+    link: "runtime.help";
+    desc: "Displays a help/usage message";
+}
+
+}
+
+short_form: {
+h: "help";
+}
+
+}
+
+runtime: {
+
+help: false;
+
+}
index 8955106..c61847f 100644 (file)
@@ -1,6 +1,3 @@
-global: {
-    test: 'a';
-    test2: 42;
+log: {
+    filename: "logs/%d.log";
 }
-
-another: "something";
index a62ad6b..67a81d1 100644 (file)
@@ -36,15 +36,17 @@ void MessageSystem::setLogFile(std::string path) {
             s = path;
             s.replace(pos, 2, buf);
 
-            std::ifstream input(path.c_str());
+            std::ifstream input(s.c_str());
             if(input.is_open()) {
-                low = middle;
+                if(low == middle) low = middle+1;
+                else low = middle;
             }
             else {
                 high = middle;
             }
         }
-        path = s;
+        std::sprintf(buf, "%05d", low);
+        path.replace(pos, 2, buf);
     }
 
     s_logFile = new std::ofstream(path.c_str());
index 791dad4..1abc151 100644 (file)
@@ -10,6 +10,87 @@ int ArgvParser::parse() {
     int offset = 1;
 
     // TODO: implement
+    for(; m_argv[offset]; offset ++) {
+        std::string arg = m_argv[offset];
+
+        // break conditions
+        if(arg == "--") break;
+        else if(arg.length() == 0) break;
+        else if(arg[0] != '-') break;
+
+        if(arg.length() == 1) {
+            Message3(Config, Error, "Malformed argument \"" << arg << "\"");
+            continue;
+        }
+
+        // two cases: either short-form or long-form.
+        // if short-form, just alias to long-form.
+        std::string long_form;
+        if(arg.length() == 2) {
+            char short_form = arg[1];
+            long_form = tree->node("arguments.short_form."
+                + short_form)->get<std::string>("");
+            if(long_form == "") {
+                Message3(Config, Error, "Unknown short argument \"" << arg
+                    << "\"");
+                continue;
+            }
+        }
+        else long_form = arg.substr(2);
+
+        std::string link = tree->node("arguments.long_form."
+            + long_form + ".link")->get<std::string>("");
+        std::string type = tree->node("arguments.long_form."
+            + long_form + ".type")->get<std::string>("");
+
+        if(link == "") {
+            Message3(Config, Fatal, "Unknown argument \"" << arg << "\"");
+        }
+        else if(type == "") {
+            Message3(Config, Fatal, "Malformed argument spec for \""
+                << long_form << "\"");
+        }
+        
+        // otherwise, process!
+        // get node, disallowing creation
+        std::shared_ptr<TreeNode> node = tree->node(link);
+        
+        if(type == "boolean") {
+            node->set<bool>(true);
+        }
+        else if(type == "invboolean") {
+            node->set<bool>(false);
+        }
+        else if(type == "string") {
+            if(!m_argv[offset+1]) {
+                Message3(Config, Fatal, "Argument \"" << arg
+                    << "\" expected parameter.");
+            }
+            node->set<std::string>(std::string(m_argv[offset+1]));
+            offset ++;
+        }
+        else if(type == "parse") {
+            if(!m_argv[offset+1]) {
+                Message3(Config, Fatal, "Argument \"" << arg
+                    << "\" expected parameter.");
+            }
+            node->parse(std::string(m_argv[offset+1]), 0);
+            offset ++;
+        }
+        else {
+            Message3(Config, Fatal, "Unknown argument type \"" << type
+                << "\"");
+        }
+    }
+
+    int i;
+    tree->node("runtime.arguments")->set(std::vector<std::string>());
+    std::vector<std::string> &arglist_vector =
+        tree->node("runtime.arguments")->get<std::vector<std::string>>();
+    arglist_vector.clear();
+    for(i = offset; m_argv[i]; i ++) {
+        arglist_vector.push_back(std::string(m_argv[i]));
+    }
 
     return offset;
 }
index 34f4204..076cd02 100644 (file)
@@ -36,11 +36,11 @@ std::string::size_type TreeNodeContainer<bool>::tryParse(
 
     if(s.substr(from, 4) == "true") {
         set(true);
-        return std::string::npos;
+        return from+4;
     }
     else if(s.substr(from, 5) == "false") {
         set(false);
-        return std::string::npos;
+        return from+5;
     }
 
     return from;
index 6e5cbc4..f123a5b 100644 (file)
@@ -42,6 +42,7 @@ public:
     
     std::string serialize();
 
+    T &get() { return m_tval; }
     const T &get() const { return m_tval; }
     void set(const T &val) { m_tval = val; }
 
@@ -210,6 +211,18 @@ public:
     const std::string &name() const { return m_name; }
 
     template<typename T>
+    T &get() {
+        int nindex = NextType::getIndex();
+        int tindex = TreeNodeContainer<T>::typeIndex();
+
+        if(nindex != tindex) {
+            Message3(Config, Fatal, "TreeNode get type mismatch (have: "
+                << nindex << ", expected: " << tindex);
+        }
+        return TreeNodeContainer<T>::get();
+    }
+
+    template<typename T>
     const T &get() const {
         int nindex = NextType::getIndex();
         int tindex = TreeNodeContainer<T>::typeIndex();
@@ -235,7 +248,7 @@ public:
     }
 
     template<typename T>
-    void set(T &value) const {
+    void set(const T &value) {
         int nindex = NextType::getIndex();
         int tindex = TreeNodeContainer<T>::typeIndex();
         if(nindex != tindex && nindex != -1) {
@@ -296,7 +309,7 @@ public:
 };
 
 typedef TreeNodeWrapper<int, char, bool, std::string,
-    std::vector<int>> TreeNode;
+    std::vector<int>, std::vector<std::string>> TreeNode;
 
 }  // namespace Config
 
index 8c7bb21..33ac17e 100644 (file)
@@ -1,4 +1,5 @@
 #include <iostream>
+#include <cstdio>
 
 #include "MessageSystem.h"
 
@@ -8,8 +9,18 @@
 
 #define DATA_PATH "data/"
 
-namespace Config {
-void test();
+void usage(std::shared_ptr<Config::Tree> ctree, const char *argv0) {
+    std::cerr << "Usage: " << argv0 << " [arguments]" << std::endl;
+    std::cerr << "Arguments: " << std::endl;
+
+    auto argsnode = ctree->node("arguments.long_form");
+
+    for(int i = 0; i < argsnode->childCount(); i ++) {
+        auto argnode = argsnode->child(i);
+        std::fprintf(stderr, "\t--%-20s %s\n", argnode->name().c_str(),
+            argnode->child("desc")->get(
+                std::string("[no description]")).c_str());
+    }
 }
 
 int main(int argc, char *argv[]) {
@@ -17,37 +28,17 @@ int main(int argc, char *argv[]) {
     std::shared_ptr<Config::Tree> ctree = Config::Tree::instance();
     Config::Parser parser(ctree);
     parser.parseFile(DATA_PATH "/skeleton.config");
-    //parser.parseFile(DATA_PATH "/arguments.config");
-
-    /*parser.parseString(
-        "something: {\n"
-        "    test: \"abc\";\n"
-        "    test2: 42;\n"
-        "};\n"
-        "else: 42;\n"
-    );*/
-    parser.parseString(
-        "a: 42; "
-        "b: 21; "
-        "c: 7; "
-        "d: {e:'c';} "
-        "e: int[1;2;3;];"
-    );
-
-    Message3(General, Debug, ctree->node("a")->get<int>());
-    Message3(General, Debug, ctree->node("d.e")->get<char>());
-    Message3(General, Debug, ctree->node("e")->get<std::vector<int>>()[1]);
-    Message3(General, Debug, ctree->node("another")->get<std::string>());
-
-    parser.parseString("d.e:'f';");
-    Message3(General, Debug, ctree->node("d.e")->get<char>());
+    parser.parseFile(DATA_PATH "/arguments.config");
 
     Config::ArgvParser argvparser(argv);
     int offset = argvparser.parse();
 
-    //MessageSystem::setLogFile(ctree->get<std::string>(""));
+    if(ctree->node("runtime.help")->get<bool>(false)) {
+        usage(ctree, argv[0]);
+        return 0;
+    }
 
-    //Config::test();
+    MessageSystem::setLogFile(ctree->node("log.filename")->get<std::string>());
 
     return 0;
 }