]> git.mxchange.org Git - simgear.git/blobdiff - simgear/structure/SGExpression.hxx
Fix use count for deleted, reference counted objects.
[simgear.git] / simgear / structure / SGExpression.hxx
index 2dac8efb1863c105bfd78b045af4289180df6c06..2cfa3dc8909d629959816210282535f3be13f37c 100644 (file)
@@ -24,6 +24,9 @@
 
 #include <string>
 #include <vector>
+#include <functional>
+#include <set>
+#include <string>
 
 #include <simgear/props/condition.hxx>
 #include <simgear/props/props.hxx>
@@ -31,6 +34,7 @@
 #include <simgear/math/SGMath.hxx>
 #include <simgear/scene/model/persparam.hxx>
 #include <simgear/structure/exception.hxx>
+#include <simgear/structure/Singleton.hxx>
 
 /// Expression tree implementation.
 
@@ -121,6 +125,9 @@ public:
   T getValue(const simgear::expression::Binding* binding = 0) const
   { T value; eval(value, binding); return value; }
 
+  double getDoubleValue(const simgear::expression::Binding* binding = 0) const
+  { T value; eval(value, binding); return value; }
+
   virtual bool isConst() const { return false; }
   virtual SGExpression* simplify();
   virtual simgear::expression::Type getType() const
@@ -131,6 +138,8 @@ public:
   {
     return simgear::expression::TypeTraits<T>::typeTag;
   }
+  virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+  { }
 };
 
 /// Constant value expression
@@ -179,7 +188,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); }
@@ -191,11 +202,11 @@ private:
 template<typename T>
 class SGBinaryExpression : public SGExpression<T> {
 public:
-  const SGExpression<T>* getOperand(unsigned i) const
+  const SGExpression<T>* getOperand(size_t i) const
   { return _expressions[i]; }
-  SGExpression<T>* getOperand(unsigned i)
+  SGExpression<T>* getOperand(size_t i)
   { return _expressions[i]; }
-  void setOperand(unsigned i, SGExpression<T>* expression)
+  void setOperand(size_t i, SGExpression<T>* expression)
   {
     if (!expression)
       expression = new SGConstExpression<T>(T());
@@ -213,6 +224,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); }
@@ -224,16 +241,16 @@ private:
 template<typename T>
 class SGNaryExpression : public SGExpression<T> {
 public:
-  unsigned getNumOperands() const
+  size_t getNumOperands() const
   { return _expressions.size(); }
-  const SGExpression<T>* getOperand(unsigned i) const
+  const SGExpression<T>* getOperand(size_t i) const
   { return _expressions[i]; }
-  SGExpression<T>* getOperand(unsigned i)
+  SGExpression<T>* getOperand(size_t i)
   { return _expressions[i]; }
-  unsigned addOperand(SGExpression<T>* expression)
+  size_t addOperand(SGExpression<T>* expression)
   {
     if (!expression)
-      return ~unsigned(0);
+      return ~size_t(0);
     _expressions.push_back(expression);
     return _expressions.size() - 1;
   }
@@ -249,18 +266,23 @@ public:
 
   virtual bool isConst() const
   {
-    for (unsigned i = 0; i < _expressions.size(); ++i)
+    for (size_t i = 0; i < _expressions.size(); ++i)
       if (!_expressions[i]->isConst())
         return false;
     return true;
   }
   virtual SGExpression<T>* simplify()
   {
-    for (unsigned i = 0; i < _expressions.size(); ++i)
+    for (size_t i = 0; i < _expressions.size(); ++i)
       _expressions[i] = _expressions[i]->simplify();
     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()
   { }
@@ -283,6 +305,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(); }
@@ -318,7 +343,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = acos(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
+  { value = acos((double)SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -331,7 +356,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = asin(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
+  { value = asin((double)SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -344,7 +369,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = atan(getOperand()->getValue(b)); }
+  { value = atan(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -357,7 +382,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = ceil(getOperand()->getValue(b)); }
+  { value = ceil(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -370,7 +395,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = cos(getOperand()->getValue(b)); }
+  { value = cos(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -383,7 +408,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = cosh(getOperand()->getValue(b)); }
+  { value = cosh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -396,7 +421,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = exp(getOperand()->getValue(b)); }
+  { value = exp(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -409,7 +434,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = floor(getOperand()->getValue(b)); }
+  { value = floor(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -422,7 +447,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = log(getOperand()->getValue(b)); }
+  { value = log(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -435,7 +460,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = log10(getOperand()->getValue(b)); }
+  { value = log10(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -448,7 +473,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = sin(getOperand()->getValue(b)); }
+  { value = sin(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -461,7 +486,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = sinh(getOperand()->getValue(b)); }
+  { value = sinh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -487,7 +512,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = sqrt(getOperand()->getValue(b)); }
+  { value = sqrt(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -500,7 +525,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = tan(getOperand()->getValue(b)); }
+  { value = tan(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -513,7 +538,7 @@ public:
   { }
 
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = tanh(getOperand()->getValue(b)); }
+  { value = tanh(getOperand()->getDoubleValue(b)); }
 
   using SGUnaryExpression<T>::getOperand;
 };
@@ -661,24 +686,16 @@ public:
 private:
   T apply_mods(T property) const
   {
-    T modprop;
-    if (_step > 0) {
-      T scrollval = 0;
-      if(_scroll > 0) {
-        // calculate scroll amount (for odometer like movement)
-        T remainder  =  _step - fmod(fabs(property), _step);
-        if (remainder < _scroll) {
-          scrollval = (_scroll - remainder) / _scroll * _step;
-        }
-      }
-      // apply stepping of input value
-      if(property > 0)
-        modprop = ((floor(property/_step) * _step) + scrollval);
-      else
-        modprop = ((ceil(property/_step) * _step) + scrollval);
-    } else {
-      modprop = property;
-    }
+    if( _step <= SGLimits<T>::min() ) return property;
+
+    // apply stepping of input value
+    T modprop = floor(property/_step)*_step;
+
+    // calculate scroll amount (for odometer like movement)
+    T remainder = property <= SGLimits<T>::min() ? -fmod(property,_step) : (_step - fmod(property,_step));
+    if( remainder > SGLimits<T>::min() && remainder < _scroll )
+      modprop += (_scroll - remainder) / _scroll * _step;
+
     return modprop;
   }
 
@@ -716,6 +733,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:
@@ -730,7 +753,7 @@ public:
     : SGBinaryExpression<T>(expr0, expr1)
   { }
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = atan2(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
+  { value = atan2(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); }
   using SGBinaryExpression<T>::getOperand;
 };
 
@@ -770,7 +793,7 @@ public:
     : SGBinaryExpression<T>(expr0, expr1)
   { }
   virtual void eval(T& value, const simgear::expression::Binding* b) const
-  { value = pow(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
+  { value = pow(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); }
   using SGBinaryExpression<T>::getOperand;
 };
 
@@ -785,14 +808,33 @@ public:
   virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
     value = T(0);
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
-    for (unsigned i = 0; i < sz; ++i)
+    size_t sz = SGNaryExpression<T>::getNumOperands();
+    for (size_t i = 0; i < sz; ++i)
       value += getOperand(i)->getValue(b);
   }
   using SGNaryExpression<T>::getValue;
   using SGNaryExpression<T>::getOperand;
 };
 
+template<typename T>
+class SGDifferenceExpression : public SGNaryExpression<T> {
+public:
+  SGDifferenceExpression()
+  { }
+  SGDifferenceExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
+    : SGNaryExpression<T>(expr0, expr1)
+  { }
+  virtual void eval(T& value, const simgear::expression::Binding* b) const
+  {
+    value = getOperand(0)->getValue(b);
+    size_t sz = SGNaryExpression<T>::getNumOperands();
+    for (size_t i = 1; i < sz; ++i)
+      value -= getOperand(i)->getValue(b);
+  }
+  using SGNaryExpression<T>::getValue;
+  using SGNaryExpression<T>::getOperand;
+};
+
 template<typename T>
 class SGProductExpression : public SGNaryExpression<T> {
 public:
@@ -804,8 +846,8 @@ public:
   virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
     value = T(1);
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
-    for (unsigned i = 0; i < sz; ++i)
+    size_t sz = SGNaryExpression<T>::getNumOperands();
+    for (size_t i = 0; i < sz; ++i)
       value *= getOperand(i)->getValue(b);
   }
   using SGNaryExpression<T>::getValue;
@@ -822,12 +864,12 @@ public:
   { }
   virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
+    size_t sz = SGNaryExpression<T>::getNumOperands();
     if (sz < 1)
       return;
     
     value = getOperand(0)->getValue(b);
-    for (unsigned i = 1; i < sz; ++i)
+    for (size_t i = 1; i < sz; ++i)
       value = SGMisc<T>::min(value, getOperand(i)->getValue(b));
   }
   using SGNaryExpression<T>::getOperand;
@@ -843,12 +885,12 @@ public:
   { }
   virtual void eval(T& value, const simgear::expression::Binding* b) const
   {
-    unsigned sz = SGNaryExpression<T>::getNumOperands();
+    size_t sz = SGNaryExpression<T>::getNumOperands();
     if (sz < 1)
       return;
     
     value = getOperand(0)->getValue(b);
-    for (unsigned i = 1; i < sz; ++i)
+    for (size_t i = 1; i < sz; ++i)
       value = SGMisc<T>::max(value, getOperand(i)->getValue(b));
   }
   using SGNaryExpression<T>::getOperand;
@@ -859,6 +901,11 @@ typedef SGExpression<float> SGExpressionf;
 typedef SGExpression<double> SGExpressiond;
 typedef SGExpression<bool> SGExpressionb;
 
+typedef SGSharedPtr<SGExpressioni> SGExpressioni_ref;
+typedef SGSharedPtr<SGExpressionf> SGExpressionf_ref;
+typedef SGSharedPtr<SGExpressiond> SGExpressiond_ref;
+typedef SGSharedPtr<SGExpressionb> SGExpressionb_ref;
+
 /**
  * Global function to make an expression out of properties.
 
@@ -903,7 +950,7 @@ namespace simgear
   {
   struct ParseError : public sg_exception
   {
-      ParseError(const string& message = std::string())
+      ParseError(const std::string& message = std::string())
           : sg_exception(message) {}
   };
     
@@ -967,8 +1014,8 @@ namespace simgear
   class BindingLayout
   {
   public:
-      int addBinding(const std::string& name, expression::Type type);
-      bool findBinding(const string& name, VariableBinding& result) const;
+      size_t addBinding(const std::string& name, expression::Type type);
+      bool findBinding(const std::string& name, VariableBinding& result) const;
       std::vector<VariableBinding> bindings;
   };
 
@@ -985,7 +1032,7 @@ namespace simgear
           ParserMap& map = getParserMap();
           ParserMap::iterator itr = map.find(exp->getName());
           if (itr == map.end())
-              throw ParseError(string("unknown expression ") + exp->getName());
+              throw ParseError(std::string("unknown expression ") + exp->getName());
           exp_parser parser = itr->second;
           return (*parser)(exp, this);
       }
@@ -1009,10 +1056,16 @@ namespace simgear
   class ExpressionParser : public Parser
   {
   public:
-      ParserMap& getParserMap() { return _parserTable; }
+      ParserMap& getParserMap()
+      {
+          return ParserMapSingleton::instance()->_parserTable;
+      }
       static void addExpParser(const std::string&, exp_parser);
   protected:
-      static ParserMap _parserTable;
+      struct ParserMapSingleton : public simgear::Singleton<ParserMapSingleton>
+      {
+          ParserMap _parserTable;
+      };
   };
 
   /**
@@ -1054,16 +1107,16 @@ namespace simgear
   class GeneralNaryExpression : public ::SGExpression<T> {
   public:
     typedef OpType operand_type;
-    unsigned getNumOperands() const
+    size_t getNumOperands() const
     { return _expressions.size(); }
-    const ::SGExpression<OpType>* getOperand(unsigned i) const
+    const ::SGExpression<OpType>* getOperand(size_t i) const
     { return _expressions[i]; }
-    ::SGExpression<OpType>* getOperand(unsigned i)
+    ::SGExpression<OpType>* getOperand(size_t i)
     { return _expressions[i]; }
-    unsigned addOperand(::SGExpression<OpType>* expression)
+    size_t addOperand(::SGExpression<OpType>* expression)
     {
       if (!expression)
-        return ~unsigned(0);
+        return ~size_t(0);
       _expressions.push_back(expression);
       return _expressions.size() - 1;
     }
@@ -1079,14 +1132,14 @@ namespace simgear
     
     virtual bool isConst() const
     {
-      for (unsigned i = 0; i < _expressions.size(); ++i)
+      for (size_t i = 0; i < _expressions.size(); ++i)
         if (!_expressions[i]->isConst())
           return false;
       return true;
     }
     virtual ::SGExpression<T>* simplify()
     {
-      for (unsigned i = 0; i < _expressions.size(); ++i)
+      for (size_t i = 0; i < _expressions.size(); ++i)
         _expressions[i] = _expressions[i]->simplify();
       return SGExpression<T>::simplify();
     }
@@ -1123,7 +1176,7 @@ namespace simgear
     }
     virtual void eval(bool& value, const simgear::expression::Binding* b) const
     {
-      unsigned sz = this->getNumOperands();
+      size_t sz = this->getNumOperands();
       if (sz != 2)
         return;
       value = _pred(this->getOperand(0)->getValue(b),
@@ -1195,7 +1248,7 @@ namespace simgear
     void eval(bool& value, const expression::Binding* b) const
     {
       value = false;
-      for (int i = 0; i < getNumOperands(); ++i) {
+      for (int i = 0; i < (int)getNumOperands(); ++i) {
         value = value || getOperand(i)->getValue(b);
         if (value)
           return;
@@ -1209,7 +1262,7 @@ namespace simgear
     void eval(bool& value, const expression::Binding* b) const
     {
       value = true;
-      for (int i = 0; i < getNumOperands(); ++i) {
+      for (int i = 0; i < (int)getNumOperands(); ++i) {
         value = value && getOperand(i)->getValue(b);
         if (!value)
           return;
@@ -1227,7 +1280,7 @@ namespace simgear
     ConvertExpression() {}
     ConvertExpression(::SGExpression<OpType>* expr0)
     {
-      addOperand(expr0);
+      this->addOperand(expr0);
     }
     virtual void eval(T& value, const simgear::expression::Binding* b) const
     {