Collect properties from expression/condition trees.
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.
This commit is contained in:
parent
0dcb64dca3
commit
1a5467aec8
19
simgear/misc/test_macros.hxx
Normal file
19
simgear/misc/test_macros.hxx
Normal file
@ -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
|
@ -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.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -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 { }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
110
simgear/structure/expression_test.cxx
Normal file
110
simgear/structure/expression_test.cxx
Normal file
@ -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;
|
||||
}
|
||||
|
@ -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() \
|
||||
|
Loading…
Reference in New Issue
Block a user