1 // condition.cxx - Declarations and inline methods for property conditions.
3 // Written by David Megginson, started 2000.
4 // CLO May 2003 - Split out condition specific code.
6 // This file is in the Public Domain, and comes with no warranty.
11 # include <simgear_config.h>
14 // #include <iostream>
16 #include <simgear/structure/exception.hxx>
19 #include "condition.hxx"
21 #include <simgear/structure/SGExpression.hxx>
28 * Condition for a single property.
30 * This condition is true only if the property returns a boolean
33 class SGPropertyCondition : public SGCondition
36 SGPropertyCondition ( SGPropertyNode *prop_root,
37 const char * propname );
38 virtual ~SGPropertyCondition ();
39 virtual bool test () const { return _node->getBoolValue(); }
40 virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
41 { props.insert(_node.get()); }
43 SGConstPropertyNode_ptr _node;
47 * Condition with constant value
50 class SGConstantCondition : public SGCondition
53 SGConstantCondition (bool v) : _value(v) { ; }
54 virtual bool test () const { return _value; }
60 * Condition for a 'not' operator.
62 * This condition is true only if the child condition is false.
64 class SGNotCondition : public SGCondition
67 SGNotCondition (SGCondition * condition);
68 virtual ~SGNotCondition ();
69 virtual bool test () const;
70 virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
72 SGSharedPtr<SGCondition> _condition;
77 * Condition for an 'and' group.
79 * This condition is true only if all of the conditions
80 * in the group are true.
82 class SGAndCondition : public SGCondition
86 virtual ~SGAndCondition ();
87 virtual bool test () const;
88 // transfer pointer ownership
89 virtual void addCondition (SGCondition * condition);
90 virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
92 std::vector<SGSharedPtr<SGCondition> > _conditions;
97 * Condition for an 'or' group.
99 * This condition is true if at least one of the conditions in the
102 class SGOrCondition : public SGCondition
106 virtual ~SGOrCondition ();
107 virtual bool test () const;
108 // transfer pointer ownership
109 virtual void addCondition (SGCondition * condition);
110 virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
112 std::vector<SGSharedPtr<SGCondition> > _conditions;
117 * Abstract base class for property comparison conditions.
119 class SGComparisonCondition : public SGCondition
127 SGComparisonCondition (Type type, bool reverse = false);
128 virtual ~SGComparisonCondition ();
129 virtual bool test () const;
130 virtual void setLeftProperty( SGPropertyNode *prop_root,
131 const char * propname );
132 virtual void setRightProperty( SGPropertyNode *prop_root,
133 const char * propname );
134 virtual void setPrecisionProperty( SGPropertyNode *prop_root,
135 const char * propname );
136 // will make a local copy
137 virtual void setLeftValue (const SGPropertyNode * value);
138 virtual void setRightValue (const SGPropertyNode * value);
139 virtual void setPrecisionValue (const SGPropertyNode * value);
141 void setLeftDExpression(SGExpressiond* dexp);
142 void setRightDExpression(SGExpressiond* dexp);
143 void setPrecisionDExpression(SGExpressiond* dexp);
145 virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
149 SGPropertyNode_ptr _left_property;
150 SGPropertyNode_ptr _right_property;
151 SGPropertyNode_ptr _precision_property;
153 SGSharedPtr<SGExpressiond> _left_dexp;
154 SGSharedPtr<SGExpressiond> _right_dexp;
155 SGSharedPtr<SGExpressiond> _precision_dexp;
159 ////////////////////////////////////////////////////////////////////////
160 // Implementation of SGCondition.
161 ////////////////////////////////////////////////////////////////////////
163 SGCondition::SGCondition ()
167 SGCondition::~SGCondition ()
172 ////////////////////////////////////////////////////////////////////////
173 // Implementation of SGPropertyCondition.
174 ////////////////////////////////////////////////////////////////////////
176 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
177 const char *propname )
178 : _node( prop_root->getNode(propname, true) )
182 SGPropertyCondition::~SGPropertyCondition ()
187 ////////////////////////////////////////////////////////////////////////
188 // Implementation of SGNotCondition.
189 ////////////////////////////////////////////////////////////////////////
191 SGNotCondition::SGNotCondition (SGCondition * condition)
192 : _condition(condition)
196 SGNotCondition::~SGNotCondition ()
201 SGNotCondition::test () const
203 return !(_condition->test());
207 SGNotCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
209 _condition->collectDependentProperties(props);
212 ////////////////////////////////////////////////////////////////////////
213 // Implementation of SGAndCondition.
214 ////////////////////////////////////////////////////////////////////////
216 SGAndCondition::SGAndCondition ()
220 SGAndCondition::~SGAndCondition ()
225 SGAndCondition::test () const
227 for( size_t i = 0; i < _conditions.size(); i++ )
229 if (!_conditions[i]->test())
236 SGAndCondition::addCondition (SGCondition * condition)
238 _conditions.push_back(condition);
242 SGAndCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
244 for( size_t i = 0; i < _conditions.size(); i++ )
245 _conditions[i]->collectDependentProperties(props);
249 ////////////////////////////////////////////////////////////////////////
250 // Implementation of SGOrCondition.
251 ////////////////////////////////////////////////////////////////////////
253 SGOrCondition::SGOrCondition ()
257 SGOrCondition::~SGOrCondition ()
262 SGOrCondition::test () const
264 for( size_t i = 0; i < _conditions.size(); i++ )
266 if (_conditions[i]->test())
273 SGOrCondition::addCondition (SGCondition * condition)
275 _conditions.push_back(condition);
279 SGOrCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
281 for( size_t i = 0; i < _conditions.size(); i++ )
282 _conditions[i]->collectDependentProperties(props);
286 ////////////////////////////////////////////////////////////////////////
287 // Implementation of SGComparisonCondition.
288 ////////////////////////////////////////////////////////////////////////
291 static int doComp( T v1, T v2, T e )
295 return SGComparisonCondition::LESS_THAN;
297 return SGComparisonCondition::GREATER_THAN;
299 return SGComparisonCondition::EQUALS;
303 doComparison (const SGPropertyNode * left, const SGPropertyNode * right, const SGPropertyNode * precision )
305 using namespace simgear;
306 switch (left->getType()) {
308 bool v1 = left->getBoolValue();
309 bool v2 = right->getBoolValue();
311 return SGComparisonCondition::LESS_THAN;
313 return SGComparisonCondition::GREATER_THAN;
315 return SGComparisonCondition::EQUALS;
319 return doComp<int>(left->getIntValue(), right->getIntValue(),
320 precision ? std::abs(precision->getIntValue()/2) : 0 );
323 return doComp<long>(left->getLongValue(), right->getLongValue(),
324 precision ? std::abs(precision->getLongValue()/2L) : 0L );
327 return doComp<float>(left->getFloatValue(), right->getFloatValue(),
328 precision ? std::fabs(precision->getFloatValue()/2.0f) : 0.0f );
331 return doComp<double>(left->getDoubleValue(), right->getDoubleValue(),
332 precision ? std::fabs(precision->getDoubleValue()/2.0) : 0.0 );
336 case props::UNSPECIFIED: {
337 size_t l = precision ? precision->getLongValue() : string::npos;
338 string v1 = string(left->getStringValue()).substr(0,l);
339 string v2 = string(right->getStringValue()).substr(0,l);
341 return SGComparisonCondition::LESS_THAN;
343 return SGComparisonCondition::GREATER_THAN;
345 return SGComparisonCondition::EQUALS;
349 throw sg_exception("condition: unrecognized node type in comparison");
356 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
362 SGComparisonCondition::~SGComparisonCondition ()
367 SGComparisonCondition::test () const
369 // Always fail if incompletely specified
370 if (!_left_property || !_right_property)
373 // Get LESS_THAN, EQUALS, or GREATER_THAN
375 _left_property->setDoubleValue(_left_dexp->getValue(NULL));
379 _right_property->setDoubleValue(_right_dexp->getValue(NULL));
382 if (_precision_dexp) {
383 _precision_property->setDoubleValue(_precision_dexp->getValue(NULL));
386 int cmp = doComparison(_left_property, _right_property, _precision_property );
388 return (cmp == _type);
390 return (cmp != _type);
394 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
395 const char * propname )
397 _left_property = prop_root->getNode(propname, true);
401 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
402 const char * propname )
404 _right_property = prop_root->getNode(propname, true);
408 SGComparisonCondition::setPrecisionProperty( SGPropertyNode *prop_root,
409 const char * propname )
411 _precision_property = prop_root->getNode(propname, true);
415 SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
417 _left_property = new SGPropertyNode(*node);
421 SGComparisonCondition::setPrecisionValue (const SGPropertyNode *node)
423 _precision_property = new SGPropertyNode(*node);
427 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
429 _right_property = new SGPropertyNode(*node);
433 SGComparisonCondition::setLeftDExpression(SGExpressiond* dexp)
435 _left_property = new SGPropertyNode();
440 SGComparisonCondition::setRightDExpression(SGExpressiond* dexp)
442 _right_property = new SGPropertyNode();
447 SGComparisonCondition::setPrecisionDExpression(SGExpressiond* dexp)
449 _precision_property = new SGPropertyNode();
450 _precision_dexp = dexp;
454 SGComparisonCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
457 _left_dexp->collectDependentProperties(props);
459 props.insert(_left_property);
462 _right_dexp->collectDependentProperties(props);
464 props.insert(_right_property);
467 _precision_dexp->collectDependentProperties(props);
468 else if (_precision_property)
469 props.insert(_precision_property);
473 ////////////////////////////////////////////////////////////////////////
474 // Read a condition and use it if necessary.
475 ////////////////////////////////////////////////////////////////////////
477 // Forward declaration
478 static SGCondition * readCondition( SGPropertyNode *prop_root,
479 const SGPropertyNode *node );
482 readPropertyCondition( SGPropertyNode *prop_root,
483 const SGPropertyNode *node )
485 return new SGPropertyCondition( prop_root, node->getStringValue() );
489 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
491 int nChildren = node->nChildren();
492 for (int i = 0; i < nChildren; i++) {
493 const SGPropertyNode * child = node->getChild(i);
494 SGCondition * condition = readCondition(prop_root, child);
496 return new SGNotCondition(condition);
498 SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
503 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
505 SGAndCondition * andCondition = new SGAndCondition;
506 int nChildren = node->nChildren();
507 for (int i = 0; i < nChildren; i++) {
508 const SGPropertyNode * child = node->getChild(i);
509 SGCondition * condition = readCondition(prop_root, child);
511 andCondition->addCondition(condition);
517 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
519 SGOrCondition * orCondition = new SGOrCondition;
520 int nChildren = node->nChildren();
521 for (int i = 0; i < nChildren; i++) {
522 const SGPropertyNode * child = node->getChild(i);
523 SGCondition * condition = readCondition(prop_root, child);
525 orCondition->addCondition(condition);
531 readComparison( SGPropertyNode *prop_root,
532 const SGPropertyNode *node,
533 SGComparisonCondition::Type type,
536 SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
537 if (node->nChildren() < 2 || node->nChildren() > 3 ) {
538 throw sg_exception("condition: comparison without two or three children");
541 const SGPropertyNode* left = node->getChild(0),
542 *right = node->getChild(1);
545 string leftName(left->getName());
546 if (leftName == "property") {
547 condition->setLeftProperty(prop_root, left->getStringValue());
548 } else if (leftName == "value") {
549 condition->setLeftValue(left);
550 } else if (leftName == "expression") {
551 SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
552 condition->setLeftDExpression(exp);
554 throw sg_exception("Unknown condition comparison left child:" + leftName);
559 string rightName(right->getName());
560 if (rightName == "property") {
561 condition->setRightProperty(prop_root, right->getStringValue());
562 } else if (rightName == "value") {
563 condition->setRightValue(right);
564 } else if (rightName == "expression") {
565 SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
566 condition->setRightDExpression(exp);
568 throw sg_exception("Unknown condition comparison right child:" + rightName);
572 if( node->nChildren() == 3 ) {
573 const SGPropertyNode *n = node->getChild(2);
574 string name(n->getName());
575 if (name == "precision-property") {
576 condition->setPrecisionProperty(prop_root, n->getStringValue());
577 } else if (name == "precision-value") {
578 condition->setPrecisionValue(n);
579 } else if (name == "precision-expression") {
580 SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
581 condition->setPrecisionDExpression(exp);
583 throw sg_exception("Unknown condition comparison precision child:" + name );
591 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
593 const string &name = node->getName();
594 if (name == "property")
595 return readPropertyCondition(prop_root, node);
596 else if (name == "not")
597 return readNotCondition(prop_root, node);
598 else if (name == "and")
599 return readAndConditions(prop_root, node);
600 else if (name == "or")
601 return readOrConditions(prop_root, node);
602 else if (name == "less-than")
603 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
605 else if (name == "less-than-equals")
606 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
608 else if (name == "greater-than")
609 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
611 else if (name == "greater-than-equals")
612 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
614 else if (name == "equals")
615 return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
617 else if (name == "not-equals")
618 return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
619 else if (name == "false")
620 return new SGConstantCondition(false);
621 else if (name == "true")
622 return new SGConstantCondition(true);
628 ////////////////////////////////////////////////////////////////////////
629 // Implementation of SGConditional.
630 ////////////////////////////////////////////////////////////////////////
632 SGConditional::SGConditional ()
637 SGConditional::~SGConditional ()
642 SGConditional::setCondition (SGCondition * condition)
644 _condition = condition;
648 SGConditional::test () const
650 return ((_condition == 0) || _condition->test());
654 // The top-level is always an implicit 'and' group
656 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
658 return readAndConditions(prop_root, node);
662 // end of condition.cxx