Implemented vector/tuple-sensitive parsing.
authorethereal <ethereal@ethv.net>
Sun, 10 Nov 2013 20:47:43 +0000 (13:47 -0700)
committerethereal <ethereal@ethv.net>
Sun, 10 Nov 2013 20:47:43 +0000 (13:47 -0700)
Next up: do the same for serialization.

src/TemplateMP.h [new file with mode: 0644]
src/main.cpp
src/math/Quaternion.cpp
src/math/Vector.cpp
src/resource/XMLInterface.cpp
src/resource/XMLInterface.h

diff --git a/src/TemplateMP.h b/src/TemplateMP.h
new file mode 100644 (file)
index 0000000..eb090ac
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef SKELETON__TEMPLATE_MP_H
+#define SKELETON__TEMPLATE_MP_H
+
+#include <vector>
+
+namespace Skeleton {
+namespace MP {
+
+template<typename T>
+struct is_vector {
+    static const bool value = false;
+};
+
+template<typename T>
+struct is_vector<std::vector<T>> {
+    static const bool value = true;
+};
+
+template<typename T>
+struct is_tuple {
+    static const bool value = false;
+};
+
+template<typename... T>
+struct is_tuple<std::tuple<T...>> {
+    static const bool value = true;
+};
+
+}  // namespace MP
+}  // namespace Skeleton
+
+#endif
index abaf621..b17488c 100644 (file)
@@ -3,7 +3,9 @@
 
 #include "MessageSystem.h"
 #include "resource/XML.h"
+#include "resource/XMLInterface.h"
 #include "resource/Registry.h"
+#include "TemplateMP.h"
 
 int main(int argc, char *argv[]) {
     using namespace Skeleton;
@@ -11,6 +13,29 @@ int main(int argc, char *argv[]) {
     auto configXML = Resource::Registry::get<Resource::XML>("data/config.xml");
     Resource::Registry::alias<Resource::XML>("data/config.xml", "config");
 
+
+    {
+        auto v = XMLParse<std::vector<int>>("[2,3,3,4]");
+        std::cout << v.size() << std::endl;
+        std::cout << "Contents: " << std::endl;
+        for(auto e : v) std::cout << "\t" << e << std::endl;
+    }
+    {
+        typedef std::tuple<int, int> Test;
+        auto v = XMLParse<Test>("(2,3)");
+        std::cout << "Contents: " << std::endl;
+        std::cout << "\t" << std::get<0>(v) << std::endl;
+        std::cout << "\t" << std::get<1>(v) << std::endl;
+    }
+    {
+        bool value;
+        auto v = XMLParse<std::tuple<int, std::tuple<int, int>>>("(1,(2,3))", value);
+        std::cout << "Contents: " << std::endl;
+        std::cout << "\t" << std::get<0>(v) << std::endl;
+        std::cout << "\t\t" << std::get<0>(std::get<1>(v)) << std::endl;
+        std::cout << "\t\t" << std::get<1>(std::get<1>(v)) << std::endl;
+    }
+
     return 0;
 }
 
index a2e2471..502aa60 100644 (file)
@@ -1,6 +1,28 @@
 #include "Quaternion.h"
 
+#include "resource/XMLInterface.h"
+
 namespace Skeleton {
+
+#if 0
+template<>
+Math::Quaternion XMLParse<Math::Quaternion>(const std::string &from,
+    bool &worked) {
+    
+}
+
+template<>
+std::string XMLSerialize<Math::Quaternion>(const Math::Quaternion &from) {
+    Math::Vector axis;
+    double angle;
+
+    from.toAxisAngle(axis, angle);
+
+    return XMLSerialize<Math::Vector>(axis) + ","
+        + XMLSerialize<double>(angle);
+}
+#endif
+
 namespace Math {
 
 Quaternion::Quaternion(const Vector &axis, double angle) {
index 89a1c9e..bca0e1b 100644 (file)
@@ -7,29 +7,23 @@
 
 namespace Skeleton {
 
+#if 0
 template<>
 Math::Vector XMLParse<Math::Vector>(const std::string &from, bool &worked) {
     worked = false;
 
-    std::istringstream ss(from);
-    char c;
-    ss >> c;
-    if(c != ')') return Math::Vector();
-    double x, y, z;
-    ss >> x >> c;
-    if(c != ',') return Math::Vector();
-    ss >> y >> c;
-    if(c != ',') return Math::Vector();
-    ss >> z >> c;
-    if(c != ')') return Math::Vector();
-    worked = true;
-    return Math::Vector(x,y,z);
+    /*auto result = XMLParse<std::tuple<double,double,double>>(from, worked);*/
+    if(!worked) return Math::Vector();
+    /*return Math::Vector(std::get<0>(result), std::get<1>(result),
+        std::get<2>(result));*/
 }
 
 template<>
 std::string XMLSerialize<Math::Vector>(const Math::Vector &vector) {
-    return StreamAsString() << "(" << vector.x() << "," << vector.y() << "," << vector.z() << ")";
+    /*return XMLSerialize<std::tuple<double,double,double>>(
+        std::tuple<double,double,double>(vector.x(), vector.y(), vector.z()));*/
 }
+#endif
 
 namespace Math {
 
index f86ec4e..38f4f0a 100644 (file)
@@ -1,9 +1,20 @@
 #include <sstream>
+#include <cstring>
 
 #include "XMLInterface.h"
 
 namespace Skeleton {
 
+// int functions
+template<>
+int XMLParse<int>(std::istringstream &from, bool &worked) {
+    int value;
+    worked = (from >> value);
+
+    return value;
+}
+
+/*
 // std::string functions
 template<>
 std::string XMLParse<std::string>(const std::string &from, bool &worked) {
@@ -56,4 +67,37 @@ std::string XMLSerialize<bool>(const bool &from) {
     else return "false";
 }
 
+// float functions
+template<>
+float XMLParse<float>(const std::string &from, bool &worked) {
+    std::istringstream ss(from);
+    float value;
+    if(ss >> value) worked = true;
+    return value;
+}
+
+template<>
+std::string XMLSerialize<float>(const float &from) {
+    std::ostringstream ss;
+    ss << from;
+    return ss.str();
+}
+
+// double functions
+template<>
+double XMLParse<double>(const std::string &from, bool &worked) {
+    std::istringstream ss(from);
+    double value;
+    if(ss >> value) worked = true;
+    return value;
+}
+
+template<>
+std::string XMLSerialize<double>(const double &from) {
+    std::ostringstream ss;
+    ss << from;
+    return ss.str();
+}
+*/
+
 }  // namespace Skeleton
index 40cb602..ab68f30 100644 (file)
 #ifndef SKELETON_RESOURCE__XMLINTERFACE_H
 #define SKELETON_RESOURCE__XMLINTERFACE_H
 
+#include <iostream> // debugging
+
+#include <sstream>
+#include <tuple>
 #include <string>
+#include <type_traits>
+
+#include "TemplateMP.h"
 
 namespace Skeleton {
 
 template<typename T>
-T XMLParse(const std::string &from, bool &worked);
+typename std::enable_if<!MP::is_vector<T>::value && !MP::is_tuple<T>::value,
+    T>::type XMLParse(std::istringstream &from, bool &worked);
+template<typename T>
+typename std::enable_if<MP::is_vector<T>::value, T>::type XMLParse(
+    std::istringstream &from, bool &worked);
+template<typename T>
+typename std::enable_if<MP::is_tuple<T>::value, T>::type XMLParse(
+    std::istringstream &from, bool &worked);
+
+    
+// vector specialization
+template<typename T>
+typename std::enable_if<MP::is_vector<T>::value, T>::type XMLParse(
+    std::istringstream &from, bool &worked) {
+
+    worked = false;
+    if(!from.good()) return T();
+
+    char next;
+    from >> next;
+    if(next != '[') return T();
+
+    if(from.peek() == ']') {
+        worked = true;
+        return T();
+    }
+    if(!from.good()) return T();
+
+    T result;
+
+    while(from.good()) {
+        result.push_back(
+            XMLParse<typename T::value_type>(from, worked)
+        );
+        if(!worked) return T();
+
+        if(!from.good()) { worked = false; break; }
+
+        if(from.peek() == ']') { from.get(); worked = true; break; }
+        if(from.peek() != ',') break;
+        else from.get();
+    }
+
+    if(!worked) return T();
+    return result;
+}
+
+template<std::size_t index, typename T>
+typename std::enable_if<index == std::tuple_size<T>::value, void>::type
+XMLParseTupleHelper(std::istringstream &from, bool &worked, T &result) {
+    // empty, nothing more to parse
+}
+
+template<std::size_t index, typename T>
+typename std::enable_if<index != std::tuple_size<T>::value, void>::type
+XMLParseTupleHelper(std::istringstream &from, bool &worked, T &result) {
+
+    std::get<index>(result) = XMLParse<
+        typename std::tuple_element<index, T>::type>(from, worked);
+
+    // if not last, expect a comma.
+    if(index+1 != std::tuple_size<T>::value) {
+        if(!from.good()) { worked = false; return; }
+        if(from.get() != ',') { worked = false; return; }
+    }
+    
+    XMLParseTupleHelper<index+1, T>(from, worked, result);
+}
+
+template<typename T>
+T XMLParseTupleHelper(std::istringstream &from, bool &worked) {
+    T result;
+
+    XMLParseTupleHelper<0, T>(from, worked, result);
+
+    return result;
+}
+
+// tuple specialization
+template<typename T>
+typename std::enable_if<MP::is_tuple<T>::value, T>::type XMLParse(
+    std::istringstream &from, bool &worked) {
+
+    worked = false;
+    if(!from.good()) return T();
+
+    char next;
+    from >> next;
+    if(next != '(') return T();
+
+    if(from.peek() == ')') {
+        worked = true;
+        return T();
+    }
+    if(!from.good()) return T();
+
+    return XMLParseTupleHelper<T>(from, worked);
+
+    #if 0
+    T result;
+
+    while(from.good()) {
+        /*result.push_back(
+            XMLParse<typename T::value_type>(from, worked)
+        );*/
+        if(!worked) return T();
+
+        if(!from.good()) { worked = false; break; }
+
+        if(from.peek() == ')') { from.get(); worked = true; break; }
+        if(from.peek() != ',') break;
+        else from.get();
+    }
+
+    if(!worked) return T();
+    return result;
+    #endif
+}
+
+
+template<typename T>
+T XMLParse(const std::string &from, bool &worked) {
+    std::istringstream ss(from);
+    return XMLParse<T>(ss, worked);
+}
+
 template<typename T>
-std::string XMLSerialize(const T &from);
+T XMLParse(const std::string &from) {
+    std::istringstream ss(from);
+    bool worked = false;
+    return XMLParse<T>(ss, worked);
+}
 
 }  // namespace Skeleton