// $Id$
#ifdef HAVE_CONFIG_H
-# include <simgear/compiler.h>
+# include <simgear_config.h>
#endif
-// #include STL_IOSTREAM
+// #include <iostream>
#include <simgear/structure/exception.hxx>
#include "props.hxx"
#include "condition.hxx"
-SG_USING_STD(istream);
-SG_USING_STD(ostream);
+#include <simgear/math/SGMath.hxx>
+#include <simgear/structure/SGExpression.hxx>
+using std::istream;
+using std::ostream;
+\f
+/**
+ * Condition for a single property.
+ *
+ * This condition is true only if the property returns a boolean
+ * true value.
+ */
+class SGPropertyCondition : public SGCondition
+{
+public:
+ SGPropertyCondition ( SGPropertyNode *prop_root,
+ const char * propname );
+ virtual ~SGPropertyCondition ();
+ virtual bool test () const { return _node->getBoolValue(); }
+private:
+ SGConstPropertyNode_ptr _node;
+};
+
+/**
+ * Condition with constant value
+ *
+ */
+class SGConstantCondition : public SGCondition
+{
+public:
+ SGConstantCondition (bool v) : _value(v) { ; }
+ virtual bool test () const { return _value; }
+private:
+ bool _value;
+};
+
+/**
+ * Condition for a 'not' operator.
+ *
+ * This condition is true only if the child condition is false.
+ */
+class SGNotCondition : public SGCondition
+{
+public:
+ SGNotCondition (SGCondition * condition);
+ virtual ~SGNotCondition ();
+ virtual bool test () const;
+private:
+ SGSharedPtr<SGCondition> _condition;
+};
+
+
+/**
+ * Condition for an 'and' group.
+ *
+ * This condition is true only if all of the conditions
+ * in the group are true.
+ */
+class SGAndCondition : public SGCondition
+{
+public:
+ SGAndCondition ();
+ virtual ~SGAndCondition ();
+ virtual bool test () const;
+ // transfer pointer ownership
+ virtual void addCondition (SGCondition * condition);
+private:
+ std::vector<SGSharedPtr<SGCondition> > _conditions;
+};
+
+
+/**
+ * Condition for an 'or' group.
+ *
+ * This condition is true if at least one of the conditions in the
+ * group is true.
+ */
+class SGOrCondition : public SGCondition
+{
+public:
+ SGOrCondition ();
+ virtual ~SGOrCondition ();
+ virtual bool test () const;
+ // transfer pointer ownership
+ virtual void addCondition (SGCondition * condition);
+private:
+ std::vector<SGSharedPtr<SGCondition> > _conditions;
+};
+
+
+/**
+ * Abstract base class for property comparison conditions.
+ */
+class SGComparisonCondition : public SGCondition
+{
+public:
+ enum Type {
+ LESS_THAN,
+ GREATER_THAN,
+ EQUALS
+ };
+ SGComparisonCondition (Type type, bool reverse = false);
+ virtual ~SGComparisonCondition ();
+ virtual bool test () const;
+ virtual void setLeftProperty( SGPropertyNode *prop_root,
+ const char * propname );
+ virtual void setRightProperty( SGPropertyNode *prop_root,
+ const char * propname );
+ // will make a local copy
+ virtual void setLeftValue (const SGPropertyNode * value);
+ virtual void setRightValue (const SGPropertyNode * value);
+
+ void setLeftDExpression(SGExpressiond* dexp);
+ void setRightDExpression(SGExpressiond* dexp);
+
+private:
+ Type _type;
+ bool _reverse;
+ SGPropertyNode_ptr _left_property;
+ SGPropertyNode_ptr _right_property;
+
+ SGSharedPtr<SGExpressiond> _left_dexp;
+ SGSharedPtr<SGExpressiond> _right_dexp;
+};
-\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGCondition.
////////////////////////////////////////////////////////////////////////
SGNotCondition::~SGNotCondition ()
{
- delete _condition;
}
bool
SGAndCondition::~SGAndCondition ()
{
- for (unsigned int i = 0; i < _conditions.size(); i++)
- delete _conditions[i];
}
bool
SGOrCondition::~SGOrCondition ()
{
- for (unsigned int i = 0; i < _conditions.size(); i++)
- delete _conditions[i];
}
bool
static int
doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
{
+ using namespace simgear;
switch (left->getType()) {
- case SGPropertyNode::BOOL: {
+ case props::BOOL: {
bool v1 = left->getBoolValue();
bool v2 = right->getBoolValue();
if (v1 < v2)
return SGComparisonCondition::EQUALS;
break;
}
- case SGPropertyNode::INT: {
+ case props::INT: {
int v1 = left->getIntValue();
int v2 = right->getIntValue();
if (v1 < v2)
return SGComparisonCondition::EQUALS;
break;
}
- case SGPropertyNode::LONG: {
+ case props::LONG: {
long v1 = left->getLongValue();
long v2 = right->getLongValue();
if (v1 < v2)
return SGComparisonCondition::EQUALS;
break;
}
- case SGPropertyNode::FLOAT: {
+ case props::FLOAT: {
float v1 = left->getFloatValue();
float v2 = right->getFloatValue();
if (v1 < v2)
return SGComparisonCondition::EQUALS;
break;
}
- case SGPropertyNode::DOUBLE: {
+ case props::DOUBLE: {
double v1 = left->getDoubleValue();
double v2 = right->getDoubleValue();
if (v1 < v2)
return SGComparisonCondition::EQUALS;
break;
}
- case SGPropertyNode::STRING:
- case SGPropertyNode::NONE:
- case SGPropertyNode::UNSPECIFIED: {
+ case props::STRING:
+ case props::NONE:
+ case props::UNSPECIFIED: {
string v1 = left->getStringValue();
string v2 = right->getStringValue();
if (v1 < v2)
return SGComparisonCondition::EQUALS;
break;
}
+ default:
+ throw sg_exception("condition: unrecognized node type in comparison");
}
- throw sg_exception("Unrecognized node type");
+
return 0;
}
SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
: _type(type),
- _reverse(reverse),
- _left_property(0),
- _right_property(0),
- _right_value(0)
+ _reverse(reverse)
{
}
SGComparisonCondition::~SGComparisonCondition ()
{
- delete _right_value;
}
bool
SGComparisonCondition::test () const
{
// Always fail if incompletely specified
- if (_left_property == 0 ||
- (_right_property == 0 && _right_value == 0))
+ if (!_left_property || !_right_property)
return false;
- // Get LESS_THAN, EQUALS, or GREATER_THAN
- int cmp =
- doComparison(_left_property,
- (_right_property != 0 ? _right_property : _right_value));
+ // Get LESS_THAN, EQUALS, or GREATER_THAN
+ if (_left_dexp) {
+ _left_property->setDoubleValue(_left_dexp->getValue(NULL));
+ }
+
+ if (_right_dexp) {
+ _right_property->setDoubleValue(_right_dexp->getValue(NULL));
+ }
+
+ int cmp = doComparison(_left_property, _right_property);
if (!_reverse)
return (cmp == _type);
else
SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
const char * propname )
{
- delete _right_value;
- _right_value = 0;
_right_property = prop_root->getNode(propname, true);
}
+void
+SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
+{
+ _left_property = new SGPropertyNode(*node);
+}
+
+
void
SGComparisonCondition::setRightValue (const SGPropertyNode *node)
{
- _right_property = 0;
- delete _right_value;
- _right_value = new SGPropertyNode(*node);
+ _right_property = new SGPropertyNode(*node);
}
+void
+SGComparisonCondition::setLeftDExpression(SGExpressiond* dexp)
+{
+ _left_property = new SGPropertyNode();
+ _left_dexp = dexp;
+}
-\f
+void
+SGComparisonCondition::setRightDExpression(SGExpressiond* dexp)
+{
+ _right_property = new SGPropertyNode();
+ _right_dexp = dexp;
+}\f
////////////////////////////////////////////////////////////////////////
// Read a condition and use it if necessary.
////////////////////////////////////////////////////////////////////////
if (condition != 0)
return new SGNotCondition(condition);
}
- SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
+ SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
return 0;
}
bool reverse)
{
SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
- condition->setLeftProperty(prop_root, node->getStringValue("property[0]"));
- if (node->hasValue("property[1]"))
- condition->setRightProperty(prop_root, node->getStringValue("property[1]"));
- else
- condition->setRightValue(node->getChild("value", 0));
-
+ if (node->nChildren() != 2) {
+ throw sg_exception("condition: comparison without two children");
+ }
+
+ const SGPropertyNode* left = node->getChild(0),
+ *right = node->getChild(1);
+ string leftName(left->getName());
+ if (leftName == "property") {
+ condition->setLeftProperty(prop_root, left->getStringValue());
+ } else if (leftName == "value") {
+ condition->setLeftValue(left);
+ } else if (leftName == "expression") {
+ SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
+ condition->setLeftDExpression(exp);
+ } else {
+ throw sg_exception("Unknown condition comparison left child:" + leftName);
+ }
+
+ string rightName(right->getName());
+ if (rightName == "property") {
+ condition->setRightProperty(prop_root, right->getStringValue());
+ } else if (rightName == "value") {
+ condition->setRightValue(right);
+ } else if (rightName == "expression") {
+ SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
+ condition->setRightDExpression(exp);
+ } else {
+ throw sg_exception("Unknown condition comparison right child:" + rightName);
+ }
+
return condition;
}
false);
else if (name == "not-equals")
return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
+ else if (name == "false")
+ return new SGConstantCondition(false);
+ else if (name == "true")
+ return new SGConstantCondition(true);
else
return 0;
}
SGConditional::~SGConditional ()
{
- delete _condition;
}
void
SGConditional::setCondition (SGCondition * condition)
{
- delete _condition;
_condition = condition;
}