]> git.mxchange.org Git - simgear.git/blobdiff - simgear/props/condition.cxx
Fix missing include in simgear/misc/strutils_test.cxx
[simgear.git] / simgear / props / condition.cxx
index 85c539cfe7183e001cb164a32538fe5c8ce4d0e2..1da575a4dbfe3c51623f59fc8633f5ed627ac373 100644 (file)
 #include "props.hxx"
 #include "condition.hxx"
 
-#include <simgear/math/SGMath.hxx>
 #include <simgear/structure/SGExpression.hxx>
 
 using std::istream;
 using std::ostream;
-\f
+using std::string;
+
 /**
  * Condition for a single property.
  *
@@ -37,6 +37,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;
 };
@@ -65,8 +67,9 @@ public:
   SGNotCondition (SGCondition * condition);
   virtual ~SGNotCondition ();
   virtual bool test () const;
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
 private:
-  SGSharedPtr<SGCondition> _condition;
+  SGConditionRef _condition;
 };
 
 
@@ -84,8 +87,9 @@ 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;
+  std::vector<SGConditionRef> _conditions;
 };
 
 
@@ -103,8 +107,9 @@ 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;
+  std::vector<SGConditionRef> _conditions;
 };
 
 
@@ -126,21 +131,28 @@ public:
                                 const char * propname );
   virtual void setRightProperty( SGPropertyNode *prop_root,
                                  const char * propname );
+  virtual void setPrecisionProperty( SGPropertyNode *prop_root,
+                                 const char * propname );
   // will make a local copy
   virtual void setLeftValue (const SGPropertyNode * value);
   virtual void setRightValue (const SGPropertyNode * value);
+  virtual void setPrecisionValue (const SGPropertyNode * value);
   
   void setLeftDExpression(SGExpressiond* dexp);
   void setRightDExpression(SGExpressiond* dexp);
+  void setPrecisionDExpression(SGExpressiond* dexp);
   
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
 private:
   Type _type;
   bool _reverse;
   SGPropertyNode_ptr _left_property;
   SGPropertyNode_ptr _right_property;
+  SGPropertyNode_ptr _precision_property;
   
   SGSharedPtr<SGExpressiond> _left_dexp;
   SGSharedPtr<SGExpressiond> _right_dexp;
+  SGSharedPtr<SGExpressiond> _precision_dexp;
 };
 
 
@@ -157,7 +169,6 @@ SGCondition::~SGCondition ()
 }
 
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGPropertyCondition.
 ////////////////////////////////////////////////////////////////////////
@@ -173,7 +184,6 @@ SGPropertyCondition::~SGPropertyCondition ()
 }
 
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGNotCondition.
 ////////////////////////////////////////////////////////////////////////
@@ -193,8 +203,12 @@ SGNotCondition::test () const
   return !(_condition->test());
 }
 
+void
+SGNotCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+{
+    _condition->collectDependentProperties(props);
+}
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGAndCondition.
 ////////////////////////////////////////////////////////////////////////
@@ -210,8 +224,8 @@ SGAndCondition::~SGAndCondition ()
 bool
 SGAndCondition::test () const
 {
-  int nConditions = _conditions.size();
-  for (int i = 0; i < nConditions; i++) {
+  for( size_t i = 0; i < _conditions.size(); i++ )
+  {
     if (!_conditions[i]->test())
       return false;
   }
@@ -224,8 +238,14 @@ 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);
+}
+
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGOrCondition.
 ////////////////////////////////////////////////////////////////////////
@@ -241,8 +261,8 @@ SGOrCondition::~SGOrCondition ()
 bool
 SGOrCondition::test () const
 {
-  int nConditions = _conditions.size();
-  for (int i = 0; i < nConditions; i++) {
+  for( size_t i = 0; i < _conditions.size(); i++ )
+  {
     if (_conditions[i]->test())
       return true;
   }
@@ -255,14 +275,32 @@ 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);
+}
+
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGComparisonCondition.
 ////////////////////////////////////////////////////////////////////////
 
+template<typename T> 
+static int doComp( T v1, T v2, T e )
+{
+  T d = v1 - v2;
+  if( d < -e )
+    return SGComparisonCondition::LESS_THAN;
+  else if( d > e )
+    return SGComparisonCondition::GREATER_THAN;
+  else
+    return SGComparisonCondition::EQUALS;
+}
+
 static int
-doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
+doComparison (const SGPropertyNode * left, const SGPropertyNode * right, const SGPropertyNode * precision )
 {
   using namespace simgear;
   switch (left->getType()) {
@@ -277,55 +315,28 @@ doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
       return SGComparisonCondition::EQUALS;
     break;
   }
-  case props::INT: {
-    int v1 = left->getIntValue();
-    int v2 = right->getIntValue();
-    if (v1 < v2)
-      return SGComparisonCondition::LESS_THAN;
-    else if (v1 > v2)
-      return SGComparisonCondition::GREATER_THAN;
-    else
-      return SGComparisonCondition::EQUALS;
-    break;
-  }
-  case props::LONG: {
-    long v1 = left->getLongValue();
-    long v2 = right->getLongValue();
-    if (v1 < v2)
-      return SGComparisonCondition::LESS_THAN;
-    else if (v1 > v2)
-      return SGComparisonCondition::GREATER_THAN;
-    else
-      return SGComparisonCondition::EQUALS;
-    break;
-  }
-  case props::FLOAT: {
-    float v1 = left->getFloatValue();
-    float v2 = right->getFloatValue();
-    if (v1 < v2)
-      return SGComparisonCondition::LESS_THAN;
-    else if (v1 > v2)
-      return SGComparisonCondition::GREATER_THAN;
-    else
-      return SGComparisonCondition::EQUALS;
-    break;
-  }
-  case props::DOUBLE: {
-    double v1 = left->getDoubleValue();
-    double v2 = right->getDoubleValue();
-    if (v1 < v2)
-      return SGComparisonCondition::LESS_THAN;
-    else if (v1 > v2)
-      return SGComparisonCondition::GREATER_THAN;
-    else
-      return SGComparisonCondition::EQUALS;
-    break;
-  }
+  case props::INT:
+    return doComp<int>(left->getIntValue(), right->getIntValue(), 
+           precision ? std::abs(precision->getIntValue()/2) : 0 );
+
+  case props::LONG:
+    return doComp<long>(left->getLongValue(), right->getLongValue(), 
+           precision ? std::abs(precision->getLongValue()/2L) : 0L );
+
+  case props::FLOAT:
+    return doComp<float>(left->getFloatValue(), right->getFloatValue(), 
+           precision ? std::fabs(precision->getFloatValue()/2.0f) : 0.0f );
+
+  case props::DOUBLE:
+    return doComp<double>(left->getDoubleValue(), right->getDoubleValue(), 
+           precision ? std::fabs(precision->getDoubleValue()/2.0) : 0.0 );
+
   case props::STRING:
   case props::NONE:
   case props::UNSPECIFIED: {
-    string v1 = left->getStringValue();
-    string v2 = right->getStringValue();
+    size_t l = precision ? precision->getLongValue() : string::npos;
+    string v1 = string(left->getStringValue()).substr(0,l);
+    string v2 = string(right->getStringValue()).substr(0,l);
     if (v1 < v2)
       return SGComparisonCondition::LESS_THAN;
     else if (v1 > v2)
@@ -367,8 +378,12 @@ SGComparisonCondition::test () const
   if (_right_dexp) {
     _right_property->setDoubleValue(_right_dexp->getValue(NULL));
   }
+
+  if (_precision_dexp) {
+    _precision_property->setDoubleValue(_precision_dexp->getValue(NULL));
+  }
         
-  int cmp = doComparison(_left_property, _right_property);
+  int cmp = doComparison(_left_property, _right_property, _precision_property );
   if (!_reverse)
     return (cmp == _type);
   else
@@ -389,12 +404,24 @@ SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
   _right_property = prop_root->getNode(propname, true);
 }
 
+void
+SGComparisonCondition::setPrecisionProperty( SGPropertyNode *prop_root,
+                                         const char * propname )
+{
+  _precision_property = prop_root->getNode(propname, true);
+}
+
 void
 SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
 {
   _left_property = new SGPropertyNode(*node);
 }
 
+void
+SGComparisonCondition::setPrecisionValue (const SGPropertyNode *node)
+{
+  _precision_property = new SGPropertyNode(*node);
+}
 
 void
 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
@@ -414,7 +441,35 @@ SGComparisonCondition::setRightDExpression(SGExpressiond* dexp)
 {
   _right_property = new SGPropertyNode();
   _right_dexp = dexp;
-}\f
+}
+
+void
+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.
 ////////////////////////////////////////////////////////////////////////
@@ -479,34 +534,54 @@ readComparison( SGPropertyNode *prop_root,
                bool reverse)
 {
   SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
-  if (node->nChildren() != 2) {
-    throw sg_exception("condition: comparison without two children");
+  if (node->nChildren() < 2 || node->nChildren() > 3 ) {
+    throw sg_exception("condition: comparison without two or three 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 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);
+  {
+    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);
+    }
+  }
+  
+  if( node->nChildren() == 3 ) {
+    const SGPropertyNode *n = node->getChild(2);
+    string name(n->getName());
+    if (name == "precision-property") {
+      condition->setPrecisionProperty(prop_root, n->getStringValue());
+    } else if (name == "precision-value") {
+      condition->setPrecisionValue(n);
+    } else if (name == "precision-expression") {
+      SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
+      condition->setPrecisionDExpression(exp);
+    } else {
+      throw sg_exception("Unknown condition comparison precision child:" + name );
+    }
   }
   
   return condition;
@@ -550,7 +625,6 @@ readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
 }
 
 
-\f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of SGConditional.
 ////////////////////////////////////////////////////////////////////////
@@ -577,7 +651,6 @@ SGConditional::test () const
 }
 
 
-\f
 // The top-level is always an implicit 'and' group
 SGCondition *
 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )