Removed old configuration system, started implementing new one.
authorethereal <ethereal@ethv.net>
Sun, 10 Nov 2013 06:13:50 +0000 (23:13 -0700)
committerethereal <ethereal@ethv.net>
Sun, 10 Nov 2013 06:13:50 +0000 (23:13 -0700)
22 files changed:
data/config.xml [new file with mode: 0644]
newclass.pl
src/CMakeLists.txt
src/MessageSystem.cpp
src/MessageSystem.h
src/config/ArgvParser.cpp [deleted file]
src/config/ArgvParser.h [deleted file]
src/config/Parser.cpp [deleted file]
src/config/Parser.h [deleted file]
src/config/Tree.cpp [deleted file]
src/config/Tree.h [deleted file]
src/config/TreeNode.cpp [deleted file]
src/config/TreeNode.h [deleted file]
src/main.cpp
src/resource/Element.cpp [new file with mode: 0644]
src/resource/Element.h [new file with mode: 0644]
src/resource/File.cpp [new file with mode: 0644]
src/resource/File.h [new file with mode: 0644]
src/resource/Registry.cpp [new file with mode: 0644]
src/resource/Registry.h [new file with mode: 0644]
src/resource/XML.cpp [new file with mode: 0644]
src/resource/XML.h [new file with mode: 0644]

diff --git a/data/config.xml b/data/config.xml
new file mode 100644 (file)
index 0000000..49d2784
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" ?>
+
+<config>
+
+</config>
index 3d04f4b..883755d 100755 (executable)
@@ -1,6 +1,8 @@
 #!/usr/bin/perl
 # Perl script by DWK to create a new .cpp/.h combination template
 
+my $project = "Skeleton";
+
 if(scalar(@ARGV) < 1) {
     die "Usage: $0 <C++-name-of-class>\n" .
         "  e.g. $0 Socket::UDPSocket\n";
@@ -75,7 +77,7 @@ sub create_h_file {
 
 sub generate_namespaces {
     my $class = shift;
-    my @spaces = ();
+    my @spaces = ($project);
     
     while($class =~ /([^:]+)::/g) {
         push(@spaces, $1);
index 7fc0d88..ff851ac 100644 (file)
@@ -7,10 +7,12 @@ include_directories(. ${pugixmlInclude})
 aux_source_directory(. dotSources)
 aux_source_directory(config configSources)
 aux_source_directory(math mathSources)
+aux_source_directory(resource resourceSources)
 set(sources
     ${dotSources}
     ${configSources}
     ${mathSources}
+    ${resourceSources}
 )
 
 #find_package(Boost COMPONENTS )
@@ -18,6 +20,6 @@ set(sources
 
 add_executable(skeleton ${sources})
 
-target_link_libraries(skeleton m
+target_link_libraries(skeleton m pugixml
     #${Boost_LIBRARIES}
     )
index 304bd43..330c877 100644 (file)
@@ -5,7 +5,7 @@
 #include <fstream>
 
 #include "MessageSystem.h"
-#include "config/Tree.h"
+//#include "config/Tree.h"
 
 namespace Skeleton {
 
@@ -70,9 +70,10 @@ void MessageSystem::message(Subsystem system, MessageType type,
     struct tm *lt = std::localtime(&t);
 
     char buffer[4096];
-    if(Config::Tree::instance() &&
+    /*if(Config::Tree::instance() &&
         Config::Tree::instance()->node("runtime.extended_log")->get<bool>(
-            true)) {
+            true)) {*/
+    if(true) {
 
         std::snprintf(buffer, sizeof(buffer),
             "[%02i:%02i:%02i %-12s %-7s]         %s\n",
index 42b5288..8f7b379 100644 (file)
@@ -14,7 +14,8 @@ namespace Skeleton {
     General is a special subsystem and must always be present. */
 #define MS_Subsystems \
     MS_Subsystem(General), \
-    MS_Subsystem(Config)
+    MS_Subsystem(Config), \
+    MS_Subsystem(Resource)
 
 /* Log message types. Fatal is a special type that must always be present. */
 #define MS_Types \
diff --git a/src/config/ArgvParser.cpp b/src/config/ArgvParser.cpp
deleted file mode 100644 (file)
index 1abc151..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-#include "ArgvParser.h"
-#include "Tree.h"
-
-namespace Config {
-
-int ArgvParser::parse() {
-    auto tree = Tree::instance();
-
-    // skip argv[0].
-    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;
-}
-
-}  // namespace Config
diff --git a/src/config/ArgvParser.h b/src/config/ArgvParser.h
deleted file mode 100644 (file)
index 599be6f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef METAFRASTIS_CONFIG__ARGV_PARSER_H
-#define METAFRASTIS_CONFIG__ARGV_PARSER_H
-
-namespace Config {
-
-class ArgvParser {
-private:
-    char **m_argv;
-public:
-    ArgvParser(char **argv) : m_argv(argv) {}
-
-    int parse();
-};
-
-}  // namespace Config
-
-#endif
diff --git a/src/config/Parser.cpp b/src/config/Parser.cpp
deleted file mode 100644 (file)
index 95898dd..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-#include <cctype>
-#include <fstream>
-
-#include "Parser.h"
-
-#include "MessageSystem.h"
-
-namespace Config {
-
-void Parser::parseString(const std::string &s) {
-    m_string = s;
-    m_stringOffset = 0;
-
-    std::vector<std::shared_ptr<TreeNode>> nodeStack;
-
-    nodeStack.push_back(m_tree->root());
-
-    while(!atEnd()) {
-        skipWhitespace();
-
-        // at end of string?
-        if(atEnd()) break;
-
-        // deal with closing braces first
-        if(m_string[m_stringOffset] == '}') {
-            if(nodeStack.size() == 1) {
-                Message3(Config, Error, "Additional closing braces in config");
-                break;
-            }
-            nodeStack.pop_back();
-            m_stringOffset ++;
-            continue;
-        }
-
-        std::string::size_type i = 0;
-        while(m_stringOffset + i < m_string.length()
-            && m_string[m_stringOffset + i] != ':') i ++;
-
-        if(m_stringOffset + i == m_string.length()) {
-            Message3(Config, Error, "EOF while scanning identifier in config");
-            return;
-        }
-        if(i == 0) {
-            Message3(Config, Error, "Empty identifier found");
-            return;
-        }
-
-        std::string identifier = m_string.substr(m_stringOffset, i);
-
-        // skip colon
-        m_stringOffset += i+1;
-
-        skipWhitespace();
-        if(atEnd()) {
-            Message3(Config, Error,
-                "Empty identifier content for identifier \"" << identifier
-                << "\"");
-        }
-
-        auto node = nodeStack.back()->child(identifier);
-
-        // case 1: subnode.
-        if(m_string[m_stringOffset] == '{') {
-            nodeStack.push_back(node);
-            // skip brace
-            m_stringOffset ++;
-            continue;
-        }
-        // case 2: non-subnode, i.e. a real node
-
-        std::string::size_type after = node->parse(m_string, m_stringOffset);
-        if(after == m_stringOffset) {
-            Message3(Config, Error, "Unknown config entry for identifier \""
-                << identifier << "\"");
-            return;
-        }
-        m_stringOffset = after;
-
-        skipWhitespace();
-        if(atEnd()) break;
-
-        // expect a ';' now
-        if(m_string[m_stringOffset] != ';') {
-            Message3(Config, Error, "Missing semicolon after identifier \""
-                << identifier << "\"");
-            return;
-        }
-
-        // skip semicolon
-        m_stringOffset ++;
-    }
-
-    if(nodeStack.size() != 1) {
-        Message3(Config, Error, "Unterminated {}-block in config");
-    }
-}
-
-void Parser::parseFile(const std::string &filename) {
-    std::ifstream ifile(filename);
-
-    if(!ifile.is_open()) {
-        Message3(Config, Error, "Cannot open config file \"" << filename
-            << "\"");
-        return;
-    }
-
-    std::string sum, line;
-    while(std::getline(ifile, line)) sum += line, sum += "\n";
-
-    ifile.close();
-
-    parseString(sum);
-}
-
-void Parser::skipWhitespace() {
-    while(m_stringOffset < m_string.size() && (m_string[m_stringOffset] == '\n'
-        || std::isspace(m_string[m_stringOffset]))) m_stringOffset ++;
-}
-
-bool Parser::atEnd() const {
-    return m_stringOffset == m_string.size();
-}
-
-}  // namespace Config
diff --git a/src/config/Parser.h b/src/config/Parser.h
deleted file mode 100644 (file)
index ea665e9..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef CONFIG__PARSER_H
-#define CONFIG__PARSER_H
-
-#include "Tree.h"
-
-namespace Config {
-
-class Parser {
-private:
-    std::shared_ptr<Tree> m_tree;
-    std::string m_string;
-    std::string::size_type m_stringOffset;
-public:
-    Parser(std::shared_ptr<Tree> tree) : m_tree(tree) {}
-    void parseString(const std::string &s);
-    void parseFile(const std::string &filename);
-private:
-    void skipWhitespace();
-    bool atEnd() const;
-};
-
-}  // namespace Config
-
-#endif
diff --git a/src/config/Tree.cpp b/src/config/Tree.cpp
deleted file mode 100644 (file)
index 88255ef..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#include <iostream>
-#include "Tree.h"
-
-namespace Config {
-
-std::shared_ptr<Tree> Tree::s_singleton;
-
-Tree::Tree() {
-    m_root = std::shared_ptr<TreeNode>(new TreeNode("root"));
-}
-
-Tree::~Tree() {
-    
-}
-
-std::shared_ptr<TreeNode> Tree::node(const std::string &path) {
-    std::weak_ptr<TreeNode> cursor = m_root, prev = cursor;
-
-    std::string::size_type sc = 0;
-    while(true) {
-        std::string::size_type next = path.find(".", sc);
-        std::string n = path.substr(sc, next-sc);
-
-        prev = cursor;
-        cursor = cursor.lock()->child(n);
-        if(cursor.expired()) {
-            auto node = std::make_shared<TreeNode>(n);
-            prev.lock()->addChild(node);
-            cursor = node;
-        }
-
-        if(next == std::string::npos) break;
-        sc = next+1;
-    }
-
-    return cursor.lock();
-}
-
-std::weak_ptr<TreeNode> Tree::node(const std::string &path) const {
-    std::weak_ptr<TreeNode> cursor = m_root;
-
-    std::string::size_type sc = 0;
-    while(true) {
-        std::string::size_type next = path.find(".", sc);
-        std::string n = path.substr(sc, next-sc);
-
-        if(cursor.expired()) return std::weak_ptr<TreeNode>();
-        cursor = cursor.lock()->child(n);
-
-        if(next == std::string::npos) break;
-        sc = next;
-    }
-
-    return cursor;
-}
-
-}  // namespace Config
diff --git a/src/config/Tree.h b/src/config/Tree.h
deleted file mode 100644 (file)
index a3f2a3e..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef METAFRASTIS_CONFIG__TREE_H
-#define METAFRASTIS_CONFIG__TREE_H
-
-#include <string>
-
-#include "TreeNode.h"
-
-namespace Config {
-
-class Tree {
-private:
-    static std::shared_ptr<Tree> s_singleton;
-public:
-    static std::shared_ptr<Tree> instance() {
-        if(!s_singleton) {
-            s_singleton = std::shared_ptr<Tree>(new Tree());
-        }
-        return s_singleton;
-    }
-    static void destroy() {
-        s_singleton.reset();
-    }
-private:
-    std::shared_ptr<TreeNode> m_root;
-private:
-    Tree();
-public:
-    ~Tree();
-
-    std::shared_ptr<TreeNode> root() const { return m_root; }
-
-    std::shared_ptr<TreeNode> node(const std::string &path);
-    std::weak_ptr<TreeNode> node(const std::string &path) const;
-};
-
-}  // namespace Config
-
-#endif
diff --git a/src/config/TreeNode.cpp b/src/config/TreeNode.cpp
deleted file mode 100644 (file)
index 4c937d2..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-#include <iostream>
-#include <sstream>
-#include <cctype>
-
-#include "TreeNode.h"
-
-namespace Config {
-
-/* primitive template instantiations */
-
-template<>
-std::string TreeNodeContainer<bool>::prefix = "bool";
-
-template<>
-std::string::size_type TreeNodeContainer<bool>::tryParse(
-    const std::string &s, std::string::size_type from) {
-
-    if(s.substr(from, 4) == "true") {
-        set(true);
-        return from+4;
-    }
-    else if(s.substr(from, 5) == "false") {
-        set(false);
-        return from+5;
-    }
-
-    return from;
-}
-
-template<>
-std::string TreeNodeContainer<bool>::serialize() {
-    if(get()) return "true";
-    else return "false";
-}
-
-template<>
-std::string TreeNodeContainer<char>::prefix = "char";
-
-template<>
-std::string::size_type TreeNodeContainer<char>::tryParse(const std::string &s,
-    std::string::size_type from) {
-
-    if(s.length() >= 3+from && s[from] == '\'' && s[from+2] == '\'') {
-        set(s[from+1]);
-        return from+3;
-    }
-    return from;
-}
-
-template<>
-std::string TreeNodeContainer<char>::serialize() {
-    return std::string("'") + get() + "'";
-}
-
-template<>
-std::string TreeNodeContainer<int>::prefix = "int";
-
-template<>
-std::string::size_type TreeNodeContainer<int>::tryParse(const std::string &s,
-    std::string::size_type from) {
-
-    std::istringstream iss(s.substr(from, 10));
-    int v;
-    if(iss >> v) {
-        set(v);
-        return from + iss.tellg();
-    }
-    
-    return from;
-}
-
-template<>
-std::string TreeNodeContainer<int>::serialize() {
-    std::ostringstream oss;
-    oss << get();
-    return oss.str();
-}
-
-template<>
-std::string TreeNodeContainer<std::string>::prefix = "string";
-
-template<>
-std::string::size_type TreeNodeContainer<std::string>::tryParse(
-    const std::string &s, std::string::size_type from) {
-
-    if(s.length() < from+2) return from;
-
-    if(s[from] != '\"') return from;
-
-    std::string::size_type cursor = from+1;
-
-    char prev = 0;
-    while(cursor < s.length() &&
-        (s[cursor] != '\"' || prev == '\\')) prev = s[cursor++];
-
-    if(cursor != s.length()) {
-        set(s.substr(from+1, cursor-from-1));
-        return cursor+1;
-    }
-    else return from;
-}
-
-template<>
-std::string TreeNodeContainer<std::string>::serialize() {
-    return '\"' + get() + '\"';
-}
-
-}  // namespace Config
diff --git a/src/config/TreeNode.h b/src/config/TreeNode.h
deleted file mode 100644 (file)
index f123a5b..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-#ifndef CONFIG__NEW_TREE_NODE_H
-#define CONFIG__NEW_TREE_NODE_H
-
-#include <iostream> // for debugging
-#include <string>
-#include <map>
-#include <vector>
-#include <memory>
-#include <type_traits>
-
-#include "MessageSystem.h"
-
-namespace Config {
-
-namespace MP {
-
-/* Template metaprogramming is_vector predicate. */
-template <typename T>
-struct is_vector { 
-    static const bool value = false;
-};
-
-template<class T>
-struct is_vector<std::vector<T> > {
-    static bool const value = true;
-};
-
-} // namespace MP
-
-template<typename T>
-class TreeNodeContainer {
-private:
-    T m_tval;
-    int m_typeIndex;
-public:
-    TreeNodeContainer(int index) : m_typeIndex(index) {}
-
-    int typeIndex() const { return m_typeIndex; }
-
-    std::string::size_type tryParse(const std::string &s,
-        std::string::size_type from);
-    
-    std::string serialize();
-
-    T &get() { return m_tval; }
-    const T &get() const { return m_tval; }
-    void set(const T &val) { m_tval = val; }
-
-    static std::string prefix;
-};
-
-template<int index, typename... ConfigTypes> class TreeNodeHelper;
-
-template<int index>
-class TreeNodeHelper<index> {
-protected:
-    int m_index;
-
-    int getIndex() const { return m_index; }
-    void setIndex(int v) { m_index = v; }
-public:
-    TreeNodeHelper<index>() : m_index(-1) {}
-    std::string::size_type parse(const std::string __attribute__((unused)) &s,
-        std::string::size_type __attribute__((unused)) from) { return from; }
-
-    std::string serialize() {
-        return "<invalid>";
-    }
-};
-
-template<int index, typename T, typename... ConfigTypes>
-class TreeNodeHelper<index, T, ConfigTypes...> : 
-    public TreeNodeHelper<index+1, ConfigTypes...>,
-    public TreeNodeContainer<T> {
-private:
-    typedef TreeNodeHelper<index+1, ConfigTypes...> NextType;
-    typedef TreeNodeContainer<T> ContainerType;
-protected:
-    int getIndex() const { return NextType::getIndex(); }
-    void setIndex(int v) { NextType::setIndex(v); }
-public:
-    TreeNodeHelper<index, T, ConfigTypes...>() : ContainerType(index) {}
-
-    template<typename TT>
-    typename std::enable_if<
-        MP::is_vector<TT>::value && MP::is_vector<T>::value,
-        std::string::size_type>::type parse_helper(const std::string &s,
-            std::string::size_type from) {
-
-        const std::string &prefix =
-            TreeNodeContainer<typename T::value_type>::prefix;
-        if(s.length() <= from+prefix.length()+2) {
-            return from;
-        }
-
-        if(s.substr(from, prefix.length()) != prefix) {
-            return from;
-        }
-        if(s[from + prefix.length()] != '[') {
-            return from;
-        }
-
-        std::string::size_type cursor = from+prefix.length()+1;
-        // T is std::vector<something>.
-        T values;
-        while(cursor < s.length()) {
-            // skip whitespace
-            while(cursor < s.length() && std::isspace(s[cursor])) cursor ++;
-            // unexpected end
-            if(cursor == s.length()) break;
-
-            if(s[cursor] == ']') break;
-
-            TreeNodeContainer<typename T::value_type> tnc(-1);
-            std::string::size_type atp = tnc.tryParse(s, cursor);
-            // if it didn't work...
-            if(atp == cursor) {
-                return from;
-            }
-            cursor = atp;
-
-            // skip whitespace
-            while(cursor < s.length() && std::isspace(s[cursor])) cursor ++;
-
-            // expect a semicolon afterwards
-            if(s[cursor] != ';') return from;
-            // skip semicolon
-            cursor ++;
-
-            // save parsed value
-            values.push_back(tnc.get());
-        }
-
-        if(cursor == s.length()) {
-            return from;
-        }
-        ContainerType::set(values);
-
-        return cursor+1;
-    }
-
-    template<typename TT>
-    typename std::enable_if<!MP::is_vector<TT>::value
-        && !MP::is_vector<T>::value, std::string::size_type>::type 
-        parse_helper(const std::string &s, std::string::size_type from) {
-
-        return ContainerType::tryParse(s, from);
-    }
-
-    std::string::size_type parse(const std::string &s,
-        std::string::size_type from) {
-
-        // only allow things to be re-parsed with the same type.
-        if(getIndex() != -1 && getIndex() != index) {
-            return NextType::parse(s, from);
-        }
-
-        std::string::size_type result = parse_helper<T>(s, from);
-        if(result != from) {
-            setIndex(index);
-            return result;
-        }
-
-        return NextType::parse(s, from);
-    }
-
-    template<typename TT>
-    typename std::enable_if<
-        MP::is_vector<TT>::value && MP::is_vector<T>::value,
-        std::string>::type serialize_helper() {
-
-        std::string result = TreeNodeContainer<typename T::value_type>::prefix;
-        result += "[";
-        for(unsigned i = 0; i < ContainerType::get().size(); i ++) {
-            TreeNodeContainer<typename T::value_type> tnc(-1);
-            tnc.set(ContainerType::get()[i]);
-            result += tnc.serialize();
-            result += ";";
-        }
-        result += "]";
-        return result;
-    }
-
-    template<typename TT>
-    typename std::enable_if<
-        !MP::is_vector<TT>::value && !MP::is_vector<T>::value,
-        std::string>::type serialize_helper() {
-
-        return ContainerType::serialize();
-    }
-
-    std::string serialize() {
-        if(getIndex() == index) return serialize_helper<T>();
-        else return NextType::serialize();
-    }
-};
-
-template<typename... ConfigTypes>
-class TreeNodeWrapper : private TreeNodeHelper<0, ConfigTypes...>,
-    public std::enable_shared_from_this<TreeNodeWrapper<ConfigTypes...>> {
-private:
-    typedef TreeNodeWrapper<ConfigTypes...> ThisType;
-    typedef TreeNodeHelper<0, ConfigTypes...> NextType;
-private:
-    std::string m_name;
-    std::vector<std::shared_ptr<ThisType>> m_children;
-    std::map<std::string, std::shared_ptr<ThisType>> m_childMap;
-public:
-    TreeNodeWrapper<ConfigTypes...>(const std::string &name) : m_name(name) {}
-    
-    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();
-
-        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 T &def) const {
-        int nindex = NextType::getIndex();
-        int tindex = TreeNodeContainer<T>::typeIndex();
-        if(nindex == -1) return def;
-
-        if(nindex != tindex) {
-            Message3(Config, Fatal, "TreeNode get type mismatch (have: "
-                << nindex << ", expected: " << tindex);
-        }
-        return TreeNodeContainer<T>::get();
-    }
-
-    template<typename T>
-    void set(const T &value) {
-        int nindex = NextType::getIndex();
-        int tindex = TreeNodeContainer<T>::typeIndex();
-        if(nindex != tindex && nindex != -1) {
-
-            Message3(Config, Fatal, "TreeNode set type mismatch");
-        }
-        else {
-            TreeNodeContainer<T>::set(value);
-            NextType::setIndex(tindex);
-        }
-    }
-
-    std::string::size_type parse(const std::string &s,
-        std::string::size_type from) {
-
-        return NextType::parse(s, from);
-    }
-
-    std::string serialize() {
-        return m_name + ": " + NextType::serialize();
-    }
-
-    int childCount() const { return m_children.size(); }
-    std::shared_ptr<ThisType> child(int index) const
-        { return m_children[index]; }
-
-    std::shared_ptr<ThisType> child(const std::string &name,
-        std::string::size_type off = 0) {
-
-        std::string::size_type dotpos = name.find(".", off);
-        if(dotpos != std::string::npos) {
-            const std::string &subname = name.substr(off, dotpos - off);
-            auto nc = child(subname);
-
-            if(nc) return nc->child(name, dotpos+1);
-            addChild(std::make_shared<ThisType>(subname));
-            // repeat recursively
-            return m_childMap[subname];
-        }
-        else {
-            const std::string &subname = name.substr(off);
-            auto it = m_childMap.find(subname);
-            if(it == m_childMap.end()) {
-                addChild(std::make_shared<ThisType>(subname));
-                return m_childMap[subname];
-            }
-            return it->second;
-        }
-    }
-
-    void addChild(std::shared_ptr<ThisType> child) {
-        m_children.push_back(child);
-        m_childMap[child->name()] = child;
-    }
-
-    const std::vector<std::shared_ptr<ThisType>> &childrenVector() const
-        { return m_children; }
-};
-
-typedef TreeNodeWrapper<int, char, bool, std::string,
-    std::vector<int>, std::vector<std::string>> TreeNode;
-
-}  // namespace Config
-
-#endif
index 23ce187..7360b1d 100644 (file)
@@ -2,6 +2,18 @@
 #include <cstdio>
 
 #include "MessageSystem.h"
+#include "resource/XML.h"
+#include "resource/Registry.h"
+
+int main(int argc, char *argv[]) {
+    using namespace Skeleton;
+
+    auto result = Resource::Registry::get<Resource::XML>("data/config.xml");
+
+    return 0;
+}
+
+#if 0
 
 #include "config/ArgvParser.h"
 #include "config/Parser.h"
@@ -48,3 +60,5 @@ int main(int argc, char *argv[]) {
 
     return 0;
 }
+
+#endif
diff --git a/src/resource/Element.cpp b/src/resource/Element.cpp
new file mode 100644 (file)
index 0000000..afee32d
--- /dev/null
@@ -0,0 +1,5 @@
+#include "Element.h"
+
+namespace Resource {
+
+}  // namespace Resource
diff --git a/src/resource/Element.h b/src/resource/Element.h
new file mode 100644 (file)
index 0000000..f123b27
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef SKELETON_RESOURCE__ELEMENT_H
+#define SKELETON_RESOURCE__ELEMENT_H
+
+#include <map>
+#include <string>
+#include <memory>
+
+#define RESOURCE_ELEMENT_CLASS(type) \
+    private: \
+    friend class Skeleton::Resource::Registry; \
+    static std::map<std::string, std::shared_ptr<type>> s_registryElements;
+
+#define RESOURCE_ELEMENT_IMPL(type) \
+    std::map<std::string, std::shared_ptr<type>> type::s_registryElements;
+
+namespace Skeleton {
+namespace Resource {
+
+class Registry;
+
+}  // namespace Resource
+}  // namespace Skeleton
+
+#endif
diff --git a/src/resource/File.cpp b/src/resource/File.cpp
new file mode 100644 (file)
index 0000000..d305b61
--- /dev/null
@@ -0,0 +1,58 @@
+#include <fstream>
+
+#include "File.h"
+
+namespace Skeleton {
+namespace Resource {
+
+RESOURCE_ELEMENT_IMPL(File)
+
+File::File(std::string filename) : m_filename(filename) {
+    std::ifstream f(filename.c_str());
+    if(f.is_open()) m_exists = true;
+    else m_exists = false;
+    m_loaded = false;
+}
+
+void File::load() {
+    if(m_loaded) return;
+
+    std::ifstream f(m_filename.c_str());
+
+    f.seekg (0, f.end);
+    int length = f.tellg();
+    f.seekg (0, f.beg);
+
+    char *buffer = new char[length];
+    f.read(buffer, length);
+    m_content = std::string(buffer, length);
+    delete[] buffer;
+
+    m_loaded = true;
+}
+
+void File::contentStream(std::stringstream &tofill) {
+    load();
+    tofill << m_content;
+}
+
+std::vector<std::string> File::fileLines() {
+    if(!m_loaded) load();
+
+    std::vector<std::string> lines;
+
+    /*boost::split(lines, m_content, boost::algorithm::is_any_of("\n\r"),
+        boost::algorithm::token_compress_off);*/
+    std::string::size_type cursor = 0;
+    do {
+        std::string::size_type end = m_content.find_first_of("\n\r", cursor);
+        lines.push_back(m_content.substr(cursor, end));
+        cursor = end;
+    } while(cursor != std::string::npos);
+
+    return lines;
+}
+
+
+}  // namespace Resource
+}  // namespace Skeleton
diff --git a/src/resource/File.h b/src/resource/File.h
new file mode 100644 (file)
index 0000000..0815290
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef RESOURCE__FILE_H
+#define RESOURCE__FILE_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+
+#include "Element.h"
+
+namespace Skeleton {
+namespace Resource {
+
+class File { RESOURCE_ELEMENT_CLASS(File)
+    static std::shared_ptr<File> loadElement(std::string identifier) {
+        return std::make_shared<File>(identifier);
+    }
+private:
+    std::string m_filename;
+    bool m_exists, m_loaded;
+    std::string m_content;
+public:
+    File(std::string filename);
+
+    bool exists() const { return m_exists; }
+
+    void load();
+
+    void contentStream(std::stringstream &tofill);
+    const std::string &contentString() { load(); return m_content; }
+    std::vector<std::string> fileLines();
+private:
+    
+};
+
+}  // namespace Resource
+}  // namespace Skeleton
+
+#endif
diff --git a/src/resource/Registry.cpp b/src/resource/Registry.cpp
new file mode 100644 (file)
index 0000000..51d6158
--- /dev/null
@@ -0,0 +1,5 @@
+#include "Registry.h"
+
+namespace Skeleton {
+
+}  // namespace Skeleton
diff --git a/src/resource/Registry.h b/src/resource/Registry.h
new file mode 100644 (file)
index 0000000..c56a2e8
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef SKELETON_RESOURCE__REGISTRY_H
+#define SKELETON_RESOURCE__REGISTRY_H
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "MessageSystem.h"
+
+namespace Skeleton {
+namespace Resource {
+
+class Registry {
+private:
+    // prevent construction
+    Registry() {}
+public:
+    template<typename ResourceType>
+    static std::shared_ptr<ResourceType> alias(std::string existing,
+        std::string newname) {
+
+        auto &reg = ResourceType::s_registryElements;
+
+        reg[newname] = reg[existing];
+    }
+
+    template<typename ResourceType>
+    static std::shared_ptr<ResourceType> get(std::string identifier) {
+        auto &reg = ResourceType::s_registryElements;
+
+        auto ir = reg.find(identifier);
+
+        std::shared_ptr<ResourceType> result;
+        if(ir == reg.end()) {
+            result = ResourceType::loadElement(identifier);
+            if(!result) {
+                Message3(Resource, Error,
+                    "Could not locate resource with identifier \""
+                    << identifier << "\"");
+            }
+            reg[identifier] = result;
+        }
+        else result = (*ir).second;
+
+        return std::dynamic_pointer_cast<ResourceType>(result);
+    }
+
+    template<typename ResourceType>
+    static void unload(std::string identifier) {
+        auto &reg = ResourceType::s_registryElements;
+        
+        auto ir = reg.find(identifier);
+        if(ir != reg.end()) reg.erase(ir);
+    }
+};
+
+}  // namespace Resource
+}  // namespace Skeleton
+
+#endif
diff --git a/src/resource/XML.cpp b/src/resource/XML.cpp
new file mode 100644 (file)
index 0000000..8e4d687
--- /dev/null
@@ -0,0 +1,30 @@
+#include "XML.h"
+#include "File.h"
+#include "Registry.h"
+
+#include "MessageSystem.h"
+
+namespace Skeleton {
+namespace Resource {
+
+RESOURCE_ELEMENT_IMPL(XML)
+
+XML::XML(std::string filename) {
+    auto file = Registry::get<File>(filename);
+    if(!file || !file->exists()) {
+        Message3(Resource, Error, "Could not find XML file \"" << filename
+            << "\"");
+        return;
+    }
+
+    auto result = m_doc.load_buffer(file->contentString().c_str(),
+        file->contentString().length());
+
+    if(!result) {
+        Message3(Resource, Error, "Could not load XML resource " << filename 
+            << ": " << result.description());
+    }
+}
+
+}  // namespace Resource
+}  // namespace Skeleton
diff --git a/src/resource/XML.h b/src/resource/XML.h
new file mode 100644 (file)
index 0000000..0470708
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef RESOURCE__XML_H
+#define RESOURCE__XML_H
+
+#include <pugixml.hpp>
+
+#include "Element.h"
+
+namespace Skeleton {
+namespace Resource {
+
+class XML { RESOURCE_ELEMENT_CLASS(XML)
+    static std::shared_ptr<XML> loadElement(std::string identifier) {
+        return std::make_shared<XML>(identifier);
+    }
+private:
+    pugi::xml_document m_doc;
+public:
+    XML(std::string filename);
+
+    const pugi::xml_document &doc() const { return m_doc; }
+};
+
+}  // namespace Resource
+}  // namespace Skeleton
+
+#endif