]> git.mxchange.org Git - simgear.git/blobdiff - simgear/props/condition.cxx
Melchior FRANZ: fix SGPropertyNode::LAST_USED_ATTRIBUTE
[simgear.git] / simgear / props / condition.cxx
index 014aff4596639790268236db06871d7e7f5cae8b..85c539cfe7183e001cb164a32538fe5c8ce4d0e2 100644 (file)
 // $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.
 ////////////////////////////////////////////////////////////////////////
@@ -65,7 +185,6 @@ SGNotCondition::SGNotCondition (SGCondition * condition)
 
 SGNotCondition::~SGNotCondition ()
 {
-  delete _condition;
 }
 
 bool
@@ -86,8 +205,6 @@ SGAndCondition::SGAndCondition ()
 
 SGAndCondition::~SGAndCondition ()
 {
-  for (unsigned int i = 0; i < _conditions.size(); i++)
-    delete _conditions[i];
 }
 
 bool
@@ -119,8 +236,6 @@ SGOrCondition::SGOrCondition ()
 
 SGOrCondition::~SGOrCondition ()
 {
-  for (unsigned int i = 0; i < _conditions.size(); i++)
-    delete _conditions[i];
 }
 
 bool
@@ -149,8 +264,9 @@ SGOrCondition::addCondition (SGCondition * condition)
 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)
@@ -161,7 +277,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
       return SGComparisonCondition::EQUALS;
     break;
   }
-  case SGPropertyNode::INT: {
+  case props::INT: {
     int v1 = left->getIntValue();
     int v2 = right->getIntValue();
     if (v1 < v2)
@@ -172,7 +288,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
       return SGComparisonCondition::EQUALS;
     break;
   }
-  case SGPropertyNode::LONG: {
+  case props::LONG: {
     long v1 = left->getLongValue();
     long v2 = right->getLongValue();
     if (v1 < v2)
@@ -183,7 +299,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
       return SGComparisonCondition::EQUALS;
     break;
   }
-  case SGPropertyNode::FLOAT: {
+  case props::FLOAT: {
     float v1 = left->getFloatValue();
     float v2 = right->getFloatValue();
     if (v1 < v2)
@@ -194,7 +310,7 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
       return SGComparisonCondition::EQUALS;
     break;
   }
-  case SGPropertyNode::DOUBLE: {
+  case props::DOUBLE: {
     double v1 = left->getDoubleValue();
     double v2 = right->getDoubleValue();
     if (v1 < v2)
@@ -205,9 +321,9 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
       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)
@@ -218,38 +334,41 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
       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
@@ -267,21 +386,35 @@ void
 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.
 ////////////////////////////////////////////////////////////////////////
@@ -307,7 +440,7 @@ readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
     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;
 }
 
@@ -346,12 +479,36 @@ readComparison( SGPropertyNode *prop_root,
                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;
 }
 
@@ -384,6 +541,10 @@ readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
                           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;
 }
@@ -401,13 +562,11 @@ SGConditional::SGConditional ()
 
 SGConditional::~SGConditional ()
 {
-  delete _condition;
 }
 
 void
 SGConditional::setCondition (SGCondition * condition)
 {
-  delete _condition;
   _condition = condition;
 }