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.
--- /dev/null
+
+#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
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;
};
SGNotCondition (SGCondition * condition);
virtual ~SGNotCondition ();
virtual bool test () const;
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
private:
SGSharedPtr<SGCondition> _condition;
};
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;
};
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;
};
void setRightDExpression(SGExpressiond* dexp);
void setPrecisionDExpression(SGExpressiond* dexp);
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
private:
Type _type;
bool _reverse;
return !(_condition->test());
}
+void
+SGNotCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+{
+ _condition->collectDependentProperties(props);
+}
////////////////////////////////////////////////////////////////////////
// Implementation of SGAndCondition.
_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.
_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.
{
_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.
////////////////////////////////////////////////////////////////////////
#ifndef __SG_CONDITION_HXX
#define __SG_CONDITION_HXX
+#include <set>
#include <simgear/structure/SGReferenced.hxx>
#include <simgear/structure/SGSharedPtr.hxx>
SGCondition ();
virtual ~SGCondition ();
virtual bool test () const = 0;
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const { }
};
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)
#include <string>
#include <vector>
#include <functional>
-
+#include <set>
+
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx>
#include <simgear/math/interpolater.hxx>
{
return simgear::expression::TypeTraits<T>::typeTag;
}
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+ { }
};
/// Constant value expression
_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); }
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); }
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()
{ }
{ _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(); }
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:
--- /dev/null
+#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;
+}
+
#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;
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() \