]> git.mxchange.org Git - simgear.git/commitdiff
Collect properties from expression/condition trees.
authorJames Turner <zakalawe@mac.com>
Mon, 11 Mar 2013 16:53:52 +0000 (16:53 +0000)
committerJames Turner <zakalawe@mac.com>
Mon, 11 Mar 2013 16:53:52 +0000 (16:53 +0000)
Initial ground-work to support efficient updating of condition/expression results; allow collecting all the dependent property values from the hierarchy, so they can be observed. Also add a very small test-case for this.

simgear/misc/test_macros.hxx [new file with mode: 0644]
simgear/props/condition.cxx
simgear/props/condition.hxx
simgear/structure/CMakeLists.txt
simgear/structure/SGExpression.hxx
simgear/structure/expression_test.cxx [new file with mode: 0644]
simgear/structure/state_machine_test.cxx

diff --git a/simgear/misc/test_macros.hxx b/simgear/misc/test_macros.hxx
new file mode 100644 (file)
index 0000000..df154bc
--- /dev/null
@@ -0,0 +1,19 @@
+
+#ifndef SG_MISC_TEST_MACROS_HXX
+#define SG_MISC_TEST_MACROS_HXX
+
+#define COMPARE(a, b) \
+    if ((a) != (b))  { \
+        std::cerr << "failed:" << #a << " != " << #b << std::endl; \
+        std::cerr << "\tgot:'" << a << "'" << std::endl; \
+        exit(1); \
+    }
+
+#define VERIFY(a) \
+    if (!(a))  { \
+        std::cerr << "failed:" << #a << std::endl; \
+        exit(1); \
+    }
+    
+    
+#endif // of SG_MISC_TEST_MACROS_HXX
index 86f627f480f47c710dd2f8c709089a427295d097..bfc1bf618fd0beff674b1071fe9e50dff70331a2 100644 (file)
@@ -35,6 +35,8 @@ public:
                         const char * propname  );
   virtual ~SGPropertyCondition ();
   virtual bool test () const { return _node->getBoolValue(); }
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+    { props.insert(_node.get()); }
 private:
   SGConstPropertyNode_ptr _node;
 };
@@ -63,6 +65,7 @@ public:
   SGNotCondition (SGCondition * condition);
   virtual ~SGNotCondition ();
   virtual bool test () const;
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
 private:
   SGSharedPtr<SGCondition> _condition;
 };
@@ -82,6 +85,7 @@ public:
   virtual bool test () const;
                                // transfer pointer ownership
   virtual void addCondition (SGCondition * condition);
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
 private:
   std::vector<SGSharedPtr<SGCondition> > _conditions;
 };
@@ -101,6 +105,7 @@ public:
   virtual bool test () const;
                                // transfer pointer ownership
   virtual void addCondition (SGCondition * condition);
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
 private:
   std::vector<SGSharedPtr<SGCondition> > _conditions;
 };
@@ -135,6 +140,7 @@ public:
   void setRightDExpression(SGExpressiond* dexp);
   void setPrecisionDExpression(SGExpressiond* dexp);
   
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
 private:
   Type _type;
   bool _reverse;
@@ -195,6 +201,11 @@ SGNotCondition::test () const
   return !(_condition->test());
 }
 
+void
+SGNotCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+{
+    _condition->collectDependentProperties(props);
+}
 
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGAndCondition.
@@ -225,6 +236,13 @@ SGAndCondition::addCondition (SGCondition * condition)
   _conditions.push_back(condition);
 }
 
+void
+SGAndCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+{
+  for( size_t i = 0; i < _conditions.size(); i++ )
+    _conditions[i]->collectDependentProperties(props);
+}
+
 
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGOrCondition.
@@ -255,6 +273,13 @@ SGOrCondition::addCondition (SGCondition * condition)
   _conditions.push_back(condition);
 }
 
+void
+SGOrCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+{
+  for( size_t i = 0; i < _conditions.size(); i++ )
+    _conditions[i]->collectDependentProperties(props);
+}
+
 
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGComparisonCondition.
@@ -421,7 +446,29 @@ SGComparisonCondition::setPrecisionDExpression(SGExpressiond* dexp)
 {
   _precision_property = new SGPropertyNode();
   _precision_dexp = dexp;
-}////////////////////////////////////////////////////////////////////////
+}
+
+void
+SGComparisonCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+{
+  if (_left_dexp)
+    _left_dexp->collectDependentProperties(props);
+  else
+    props.insert(_left_property);
+  
+  if (_right_dexp)
+    _right_dexp->collectDependentProperties(props);
+  else
+    props.insert(_right_property);
+  
+  if (_precision_dexp)
+    _precision_dexp->collectDependentProperties(props);
+  else if (_precision_property)
+    props.insert(_precision_property);
+  
+}
+
+////////////////////////////////////////////////////////////////////////
 // Read a condition and use it if necessary.
 ////////////////////////////////////////////////////////////////////////
 
index f18e4b84b210191c7267d2c932ef7f30e509d10f..128cdfaf0c85fd374c723616af6335712a2c9f12 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef __SG_CONDITION_HXX
 #define __SG_CONDITION_HXX
 
+#include <set>
 #include <simgear/structure/SGReferenced.hxx>
 #include <simgear/structure/SGSharedPtr.hxx>
 
@@ -34,6 +35,7 @@ public:
   SGCondition ();
   virtual ~SGCondition ();
   virtual bool test () const = 0;
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const { }
 };
 
 
index 2ce3646a85d52d48ca5b76b45aa99573b9317d45..f7e29a7645f78ce4e98af785548fb23e5baeb456 100644 (file)
@@ -57,4 +57,9 @@ add_executable(test_state_machine state_machine_test.cxx)
 target_link_libraries(test_state_machine ${TEST_LIBS})
 add_test(test_state_machine ${EXECUTABLE_OUTPUT_PATH}/test_state_machine)
 
+add_executable(test_expressions expression_test.cxx)
+target_link_libraries(test_expressions ${TEST_LIBS})
+add_test(test_expressions ${EXECUTABLE_OUTPUT_PATH}/test_expressions)
+
+
 endif(ENABLE_TESTS)
index 1832c3a34165e7e2090c082b8b3d383af958fd09..c5ef8761ffbbca2e3773128fabb42fd89491c163 100644 (file)
@@ -25,7 +25,8 @@
 #include <string>
 #include <vector>
 #include <functional>
-
+#include <set>
+   
 #include <simgear/props/condition.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/math/interpolater.hxx>
@@ -136,6 +137,8 @@ public:
   {
     return simgear::expression::TypeTraits<T>::typeTag;
   }
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  { }
 };
 
 /// Constant value expression
@@ -184,7 +187,9 @@ public:
     _expression = _expression->simplify();
     return SGExpression<T>::simplify();
   }
-
+  
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+    { _expression->collectDependentProperties(props); }  
 protected:
   SGUnaryExpression(SGExpression<T>* expression = 0)
   { setOperand(expression); }
@@ -218,6 +223,12 @@ public:
     return SGExpression<T>::simplify();
   }
 
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  {
+    _expressions[0]->collectDependentProperties(props);
+    _expressions[1]->collectDependentProperties(props); 
+  } 
+  
 protected:
   SGBinaryExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
   { setOperand(0, expr0); setOperand(1, expr1); }
@@ -266,6 +277,11 @@ public:
     return SGExpression<T>::simplify();
   }
 
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  {
+    for (size_t i = 0; i < _expressions.size(); ++i)
+      _expressions[i]->collectDependentProperties(props);
+  } 
 protected:
   SGNaryExpression()
   { }
@@ -288,6 +304,9 @@ public:
   { _prop = prop; }
   virtual void eval(T& value, const simgear::expression::Binding*) const
   { doEval(value); }
+  
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+    { props.insert(_prop.get()); }
 private:
   void doEval(float& value) const
   { if (_prop) value = _prop->getFloatValue(); }
@@ -713,6 +732,12 @@ public:
       return getOperand()->simplify();
     return SGUnaryExpression<T>::simplify();
   }
+  
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  {
+    SGUnaryExpression<T>::collectDependentProperties(props);
+    _enable->collectDependentProperties(props);
+  }
 
   using SGUnaryExpression<T>::getOperand;
 private:
diff --git a/simgear/structure/expression_test.cxx b/simgear/structure/expression_test.cxx
new file mode 100644 (file)
index 0000000..f1ba16f
--- /dev/null
@@ -0,0 +1,110 @@
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
+#ifdef NDEBUG
+// Always enable DEBUG mode in test application, otherwise "assert" test
+// statements have no effect and don't actually test anything (catch 17 ;-) ).
+#undef NDEBUG
+#endif
+
+#include <simgear/compiler.h>
+
+#include <iostream>
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+
+#include <simgear/misc/test_macros.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/structure/SGExpression.hxx>
+#include <simgear/props/condition.hxx>
+#include <simgear/props/props.hxx>
+#include <simgear/props/props_io.hxx>
+
+using namespace std;    
+using namespace simgear;
+
+SGPropertyNode_ptr propertyTree;
+
+void initPropTree()
+{
+  const char* xml = "<?xml version=\"1.0\"?>"
+      "<PropertyList>"
+          "<group-a>"
+              "<foo>one</foo>"
+              "<bar>2</bar>"
+              "<zot>99</zot>"
+          "</group-a>"
+          "<group-b>"
+              "<thing-1 type=\"bool\">false</thing-1>"
+          "</group-b>"
+      "</PropertyList>";
+  
+  propertyTree = new SGPropertyNode;
+  readProperties(xml, strlen(xml), propertyTree.ptr());
+}
+
+void testBasic()
+{
+  
+}
+
+void testParse()
+{
+    initPropTree();
+  
+    const char* xml = "<?xml version=\"1.0\"?>"
+        "<PropertyList>"
+            "<expression>"
+              "<and>"
+              "<greater-than>"
+                "<property>/group-a/bar</property>"
+                "<value>42</value>"
+              "</greater-than>"
+              "<less-than>"
+                "<property>/group-a/zot</property>"
+                "<value>50</value>"
+              "</less-than>"
+              "</and>"
+            "</expression>"
+        "</PropertyList>";
+    
+    const char* xml2 = "<?xml version=\"1.0\"?>"
+        "<PropertyList>"
+              "<sqr>"
+                "<max>"
+                  "<property>/group-a/bar</property>"
+                  "<property>/group-a/zot</property>"
+                  "<property>/group-b/thing-1</property>"    
+                "</max>"
+              "</sqr>"
+        "</PropertyList>";
+    
+    SGPropertyNode* desc = new SGPropertyNode;
+    readProperties(xml2, strlen(xml2), desc);
+    
+    SGSharedPtr<SGExpressiond> expr = SGReadDoubleExpression(propertyTree, desc->getChild(0));
+    
+    std::set<const SGPropertyNode*> deps;
+    expr->collectDependentProperties(deps);
+    
+    COMPARE(deps.size(), 3);
+    SGPropertyNode* barProp = propertyTree->getNode("group-a/bar");
+    VERIFY(deps.find(barProp) != deps.end());
+
+    VERIFY(deps.find(propertyTree->getNode("group-a/zot")) != deps.end());
+    VERIFY(deps.find(propertyTree->getNode("group-b/thing-1")) != deps.end());
+}
+
+int main(int argc, char* argv[])
+{
+    sglog().setLogLevels( SG_ALL, SG_INFO );
+  
+    testBasic();
+    testParse();
+    
+    cout << __FILE__ << ": All tests passed" << endl;
+    return EXIT_SUCCESS;
+}
+
index 2d31d63d2014427f41dfeda7051084b6271f6d98..0703ce622ef12e8016c1bd1b5d3c1ea611af5028 100644 (file)
@@ -23,6 +23,7 @@
 #include <simgear/props/props.hxx>
 #include <simgear/props/props_io.hxx>
 #include <simgear/structure/commands.hxx>
+#include <simgear/misc/test_macros.hxx>
 
 using std::string;
 using std::cout;
@@ -57,19 +58,6 @@ public:
     int dummy_cmd_state;
 };
 
-#define COMPARE(a, b) \
-    if ((a) != (b))  { \
-        cerr << "failed:" << #a << " != " << #b << endl; \
-        cerr << "\tgot:'" << a << "'" << endl; \
-        exit(1); \
-    }
-
-#define VERIFY(a) \
-    if (!(a))  { \
-        cerr << "failed:" << #a << endl; \
-        exit(1); \
-    }
-    
 using namespace simgear;
 
 #define BUILD_MACHINE_1() \