]> git.mxchange.org Git - simgear.git/blob - simgear/props/condition.cxx
Fix some warnings
[simgear.git] / simgear / props / condition.cxx
1 // condition.cxx - Declarations and inline methods for property conditions.
2 //
3 // Written by David Megginson, started 2000.
4 // CLO May 2003 - Split out condition specific code.
5 //
6 // This file is in the Public Domain, and comes with no warranty.
7 //
8 // $Id$
9
10 #ifdef HAVE_CONFIG_H
11 #  include <simgear_config.h>
12 #endif
13
14 // #include <iostream>
15
16 #include <simgear/structure/exception.hxx>
17
18 #include "props.hxx"
19 #include "condition.hxx"
20
21 #include <simgear/structure/SGExpression.hxx>
22
23 using std::istream;
24 using std::ostream;
25 /**
26  * Condition for a single property.
27  *
28  * This condition is true only if the property returns a boolean
29  * true value.
30  */
31 class SGPropertyCondition : public SGCondition
32 {
33 public:
34   SGPropertyCondition ( SGPropertyNode *prop_root,
35                         const char * propname  );
36   virtual ~SGPropertyCondition ();
37   virtual bool test () const { return _node->getBoolValue(); }
38 private:
39   SGConstPropertyNode_ptr _node;
40 };
41
42 /**
43  * Condition with constant value
44  *
45  */
46 class SGConstantCondition : public SGCondition
47 {
48 public:
49   SGConstantCondition (bool v) : _value(v) { ; }
50   virtual bool test () const { return _value; }
51 private:
52   bool _value;
53 };
54
55 /**
56  * Condition for a 'not' operator.
57  *
58  * This condition is true only if the child condition is false.
59  */
60 class SGNotCondition : public SGCondition
61 {
62 public:
63   SGNotCondition (SGCondition * condition);
64   virtual ~SGNotCondition ();
65   virtual bool test () const;
66 private:
67   SGSharedPtr<SGCondition> _condition;
68 };
69
70
71 /**
72  * Condition for an 'and' group.
73  *
74  * This condition is true only if all of the conditions
75  * in the group are true.
76  */
77 class SGAndCondition : public SGCondition
78 {
79 public:
80   SGAndCondition ();
81   virtual ~SGAndCondition ();
82   virtual bool test () const;
83                                 // transfer pointer ownership
84   virtual void addCondition (SGCondition * condition);
85 private:
86   std::vector<SGSharedPtr<SGCondition> > _conditions;
87 };
88
89
90 /**
91  * Condition for an 'or' group.
92  *
93  * This condition is true if at least one of the conditions in the
94  * group is true.
95  */
96 class SGOrCondition : public SGCondition
97 {
98 public:
99   SGOrCondition ();
100   virtual ~SGOrCondition ();
101   virtual bool test () const;
102                                 // transfer pointer ownership
103   virtual void addCondition (SGCondition * condition);
104 private:
105   std::vector<SGSharedPtr<SGCondition> > _conditions;
106 };
107
108
109 /**
110  * Abstract base class for property comparison conditions.
111  */
112 class SGComparisonCondition : public SGCondition
113 {
114 public:
115   enum Type {
116     LESS_THAN,
117     GREATER_THAN,
118     EQUALS
119   };
120   SGComparisonCondition (Type type, bool reverse = false);
121   virtual ~SGComparisonCondition ();
122   virtual bool test () const;
123   virtual void setLeftProperty( SGPropertyNode *prop_root,
124                                 const char * propname );
125   virtual void setRightProperty( SGPropertyNode *prop_root,
126                                  const char * propname );
127   virtual void setPrecisionProperty( SGPropertyNode *prop_root,
128                                  const char * propname );
129   // will make a local copy
130   virtual void setLeftValue (const SGPropertyNode * value);
131   virtual void setRightValue (const SGPropertyNode * value);
132   virtual void setPrecisionValue (const SGPropertyNode * value);
133   
134   void setLeftDExpression(SGExpressiond* dexp);
135   void setRightDExpression(SGExpressiond* dexp);
136   void setPrecisionDExpression(SGExpressiond* dexp);
137   
138 private:
139   Type _type;
140   bool _reverse;
141   SGPropertyNode_ptr _left_property;
142   SGPropertyNode_ptr _right_property;
143   SGPropertyNode_ptr _precision_property;
144   
145   SGSharedPtr<SGExpressiond> _left_dexp;
146   SGSharedPtr<SGExpressiond> _right_dexp;
147   SGSharedPtr<SGExpressiond> _precision_dexp;
148 };
149
150
151 ////////////////////////////////////////////////////////////////////////
152 // Implementation of SGCondition.
153 ////////////////////////////////////////////////////////////////////////
154
155 SGCondition::SGCondition ()
156 {
157 }
158
159 SGCondition::~SGCondition ()
160 {
161 }
162
163
164 ////////////////////////////////////////////////////////////////////////
165 // Implementation of SGPropertyCondition.
166 ////////////////////////////////////////////////////////////////////////
167
168 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
169                                            const char *propname )
170     : _node( prop_root->getNode(propname, true) )
171 {
172 }
173
174 SGPropertyCondition::~SGPropertyCondition ()
175 {
176 }
177
178
179 ////////////////////////////////////////////////////////////////////////
180 // Implementation of SGNotCondition.
181 ////////////////////////////////////////////////////////////////////////
182
183 SGNotCondition::SGNotCondition (SGCondition * condition)
184   : _condition(condition)
185 {
186 }
187
188 SGNotCondition::~SGNotCondition ()
189 {
190 }
191
192 bool
193 SGNotCondition::test () const
194 {
195   return !(_condition->test());
196 }
197
198
199 ////////////////////////////////////////////////////////////////////////
200 // Implementation of SGAndCondition.
201 ////////////////////////////////////////////////////////////////////////
202
203 SGAndCondition::SGAndCondition ()
204 {
205 }
206
207 SGAndCondition::~SGAndCondition ()
208 {
209 }
210
211 bool
212 SGAndCondition::test () const
213 {
214   for( size_t i = 0; i < _conditions.size(); i++ )
215   {
216     if (!_conditions[i]->test())
217       return false;
218   }
219   return true;
220 }
221
222 void
223 SGAndCondition::addCondition (SGCondition * condition)
224 {
225   _conditions.push_back(condition);
226 }
227
228
229 ////////////////////////////////////////////////////////////////////////
230 // Implementation of SGOrCondition.
231 ////////////////////////////////////////////////////////////////////////
232
233 SGOrCondition::SGOrCondition ()
234 {
235 }
236
237 SGOrCondition::~SGOrCondition ()
238 {
239 }
240
241 bool
242 SGOrCondition::test () const
243 {
244   for( size_t i = 0; i < _conditions.size(); i++ )
245   {
246     if (_conditions[i]->test())
247       return true;
248   }
249   return false;
250 }
251
252 void
253 SGOrCondition::addCondition (SGCondition * condition)
254 {
255   _conditions.push_back(condition);
256 }
257
258
259 ////////////////////////////////////////////////////////////////////////
260 // Implementation of SGComparisonCondition.
261 ////////////////////////////////////////////////////////////////////////
262
263 template<typename T> 
264 static int doComp( T v1, T v2, T e )
265 {
266   T d = v1 - v2;
267   if( d < -e )
268     return SGComparisonCondition::LESS_THAN;
269   else if( d > e )
270     return SGComparisonCondition::GREATER_THAN;
271   else
272     return SGComparisonCondition::EQUALS;
273 }
274
275 static int
276 doComparison (const SGPropertyNode * left, const SGPropertyNode * right, const SGPropertyNode * precision )
277 {
278   using namespace simgear;
279   switch (left->getType()) {
280   case props::BOOL: {
281     bool v1 = left->getBoolValue();
282     bool v2 = right->getBoolValue();
283     if (v1 < v2)
284       return SGComparisonCondition::LESS_THAN;
285     else if (v1 > v2)
286       return SGComparisonCondition::GREATER_THAN;
287     else
288       return SGComparisonCondition::EQUALS;
289     break;
290   }
291   case props::INT:
292     return doComp<int>(left->getIntValue(), right->getIntValue(), 
293            precision ? std::abs(precision->getIntValue()/2) : 0 );
294
295   case props::LONG:
296     return doComp<long>(left->getLongValue(), right->getLongValue(), 
297            precision ? std::abs(precision->getLongValue()/2L) : 0L );
298
299   case props::FLOAT:
300     return doComp<float>(left->getFloatValue(), right->getFloatValue(), 
301            precision ? std::fabs(precision->getFloatValue()/2.0f) : 0.0f );
302
303   case props::DOUBLE:
304     return doComp<double>(left->getDoubleValue(), right->getDoubleValue(), 
305            precision ? std::fabs(precision->getDoubleValue()/2.0) : 0.0 );
306
307   case props::STRING:
308   case props::NONE:
309   case props::UNSPECIFIED: {
310     size_t l = precision ? precision->getLongValue() : string::npos;
311     string v1 = string(left->getStringValue()).substr(0,l);
312     string v2 = string(right->getStringValue()).substr(0,l);
313     if (v1 < v2)
314       return SGComparisonCondition::LESS_THAN;
315     else if (v1 > v2)
316       return SGComparisonCondition::GREATER_THAN;
317     else
318       return SGComparisonCondition::EQUALS;
319     break;
320   }
321   default:
322     throw sg_exception("condition: unrecognized node type in comparison");
323   }
324   
325   return 0;
326 }
327
328
329 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
330   : _type(type),
331     _reverse(reverse)
332 {
333 }
334
335 SGComparisonCondition::~SGComparisonCondition ()
336 {
337 }
338
339 bool
340 SGComparisonCondition::test () const
341 {
342                                 // Always fail if incompletely specified
343   if (!_left_property || !_right_property)
344     return false;
345
346   // Get LESS_THAN, EQUALS, or GREATER_THAN
347   if (_left_dexp) {
348     _left_property->setDoubleValue(_left_dexp->getValue(NULL));
349   }
350   
351   if (_right_dexp) {
352     _right_property->setDoubleValue(_right_dexp->getValue(NULL));
353   }
354
355   if (_precision_dexp) {
356     _precision_property->setDoubleValue(_precision_dexp->getValue(NULL));
357   }
358         
359   int cmp = doComparison(_left_property, _right_property, _precision_property );
360   if (!_reverse)
361     return (cmp == _type);
362   else
363     return (cmp != _type);
364 }
365
366 void
367 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
368                                         const char * propname )
369 {
370   _left_property = prop_root->getNode(propname, true);
371 }
372
373 void
374 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
375                                          const char * propname )
376 {
377   _right_property = prop_root->getNode(propname, true);
378 }
379
380 void
381 SGComparisonCondition::setPrecisionProperty( SGPropertyNode *prop_root,
382                                          const char * propname )
383 {
384   _precision_property = prop_root->getNode(propname, true);
385 }
386
387 void
388 SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
389 {
390   _left_property = new SGPropertyNode(*node);
391 }
392
393 void
394 SGComparisonCondition::setPrecisionValue (const SGPropertyNode *node)
395 {
396   _precision_property = new SGPropertyNode(*node);
397 }
398
399 void
400 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
401 {
402   _right_property = new SGPropertyNode(*node);
403 }
404
405 void
406 SGComparisonCondition::setLeftDExpression(SGExpressiond* dexp)
407 {
408   _left_property = new SGPropertyNode();
409   _left_dexp = dexp;
410 }
411
412 void
413 SGComparisonCondition::setRightDExpression(SGExpressiond* dexp)
414 {
415   _right_property = new SGPropertyNode();
416   _right_dexp = dexp;
417 }
418
419 void
420 SGComparisonCondition::setPrecisionDExpression(SGExpressiond* dexp)
421 {
422   _precision_property = new SGPropertyNode();
423   _precision_dexp = dexp;
424 }////////////////////////////////////////////////////////////////////////
425 // Read a condition and use it if necessary.
426 ////////////////////////////////////////////////////////////////////////
427
428                                 // Forward declaration
429 static SGCondition * readCondition( SGPropertyNode *prop_root,
430                                     const SGPropertyNode *node );
431
432 static SGCondition *
433 readPropertyCondition( SGPropertyNode *prop_root,
434                        const SGPropertyNode *node )
435 {
436   return new SGPropertyCondition( prop_root, node->getStringValue() );
437 }
438
439 static SGCondition *
440 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
441 {
442   int nChildren = node->nChildren();
443   for (int i = 0; i < nChildren; i++) {
444     const SGPropertyNode * child = node->getChild(i);
445     SGCondition * condition = readCondition(prop_root, child);
446     if (condition != 0)
447       return new SGNotCondition(condition);
448   }
449   SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
450   return 0;
451 }
452
453 static SGCondition *
454 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
455 {
456   SGAndCondition * andCondition = new SGAndCondition;
457   int nChildren = node->nChildren();
458   for (int i = 0; i < nChildren; i++) {
459     const SGPropertyNode * child = node->getChild(i);
460     SGCondition * condition = readCondition(prop_root, child);
461     if (condition != 0)
462       andCondition->addCondition(condition);
463   }
464   return andCondition;
465 }
466
467 static SGCondition *
468 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
469 {
470   SGOrCondition * orCondition = new SGOrCondition;
471   int nChildren = node->nChildren();
472   for (int i = 0; i < nChildren; i++) {
473     const SGPropertyNode * child = node->getChild(i);
474     SGCondition * condition = readCondition(prop_root, child);
475     if (condition != 0)
476       orCondition->addCondition(condition);
477   }
478   return orCondition;
479 }
480
481 static SGCondition *
482 readComparison( SGPropertyNode *prop_root,
483                 const SGPropertyNode *node,
484                 SGComparisonCondition::Type type,
485                 bool reverse)
486 {
487   SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
488   if (node->nChildren() < 2 || node->nChildren() > 3 ) {
489     throw sg_exception("condition: comparison without two or three children");
490   }
491   
492   const SGPropertyNode* left = node->getChild(0), 
493     *right = node->getChild(1);
494
495   {
496     string leftName(left->getName());
497     if (leftName == "property") {
498       condition->setLeftProperty(prop_root, left->getStringValue());
499     } else if (leftName == "value") {
500       condition->setLeftValue(left);
501     } else if (leftName == "expression") {
502       SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
503       condition->setLeftDExpression(exp);
504     } else {
505       throw sg_exception("Unknown condition comparison left child:" + leftName);
506     }
507   }
508     
509   {
510     string rightName(right->getName());
511     if (rightName == "property") {
512       condition->setRightProperty(prop_root, right->getStringValue());
513     } else if (rightName == "value") {
514       condition->setRightValue(right);
515     } else if (rightName == "expression") {
516       SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
517       condition->setRightDExpression(exp);
518     } else {
519       throw sg_exception("Unknown condition comparison right child:" + rightName);
520     }
521   }
522   
523   if( node->nChildren() == 3 ) {
524     const SGPropertyNode *n = node->getChild(2);
525     string name(n->getName());
526     if (name == "precision-property") {
527       condition->setPrecisionProperty(prop_root, n->getStringValue());
528     } else if (name == "precision-value") {
529       condition->setPrecisionValue(n);
530     } else if (name == "precision-expression") {
531       SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
532       condition->setPrecisionDExpression(exp);
533     } else {
534       throw sg_exception("Unknown condition comparison precision child:" + name );
535     }
536   }
537   
538   return condition;
539 }
540
541 static SGCondition *
542 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
543 {
544   const string &name = node->getName();
545   if (name == "property")
546     return readPropertyCondition(prop_root, node);
547   else if (name == "not")
548     return readNotCondition(prop_root, node);
549   else if (name == "and")
550     return readAndConditions(prop_root, node);
551   else if (name == "or")
552     return readOrConditions(prop_root, node);
553   else if (name == "less-than")
554     return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
555                           false);
556   else if (name == "less-than-equals")
557     return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
558                           true);
559   else if (name == "greater-than")
560     return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
561                           false);
562   else if (name == "greater-than-equals")
563     return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
564                           true);
565   else if (name == "equals")
566     return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
567                           false);
568   else if (name == "not-equals")
569     return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
570   else if (name == "false") 
571     return new SGConstantCondition(false);
572   else if (name == "true")
573     return new SGConstantCondition(true);
574   else
575     return 0;
576 }
577
578
579 ////////////////////////////////////////////////////////////////////////
580 // Implementation of SGConditional.
581 ////////////////////////////////////////////////////////////////////////
582
583 SGConditional::SGConditional ()
584   : _condition (0)
585 {
586 }
587
588 SGConditional::~SGConditional ()
589 {
590 }
591
592 void
593 SGConditional::setCondition (SGCondition * condition)
594 {
595   _condition = condition;
596 }
597
598 bool
599 SGConditional::test () const
600 {
601   return ((_condition == 0) || _condition->test());
602 }
603
604
605 // The top-level is always an implicit 'and' group
606 SGCondition *
607 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
608 {
609   return readAndConditions(prop_root, node);
610 }
611
612
613 // end of condition.cxx