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>
26 * Condition for a single property.
28 * This condition is true only if the property returns a boolean
31 class SGPropertyCondition : public SGCondition
34 SGPropertyCondition ( SGPropertyNode *prop_root,
35 const char * propname );
36 virtual ~SGPropertyCondition ();
37 virtual bool test () const { return _node->getBoolValue(); }
38 virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
39 { props.insert(_node.get()); }
41 SGConstPropertyNode_ptr _node;
45 * Condition with constant value
48 class SGConstantCondition : public SGCondition
51 SGConstantCondition (bool v) : _value(v) { ; }
52 virtual bool test () const { return _value; }
58 * Condition for a 'not' operator.
60 * This condition is true only if the child condition is false.
62 class SGNotCondition : public SGCondition
65 SGNotCondition (SGCondition * condition);
66 virtual ~SGNotCondition ();
67 virtual bool test () const;
68 virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
70 SGSharedPtr<SGCondition> _condition;
75 * Condition for an 'and' group.
77 * This condition is true only if all of the conditions
78 * in the group are true.
80 class SGAndCondition : public SGCondition
84 virtual ~SGAndCondition ();
85 virtual bool test () const;
86 // transfer pointer ownership
87 virtual void addCondition (SGCondition * condition);
88 virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
90 std::vector<SGSharedPtr<SGCondition> > _conditions;
95 * Condition for an 'or' group.
97 * This condition is true if at least one of the conditions in the
100 class SGOrCondition : public SGCondition
104 virtual ~SGOrCondition ();
105 virtual bool test () const;
106 // transfer pointer ownership
107 virtual void addCondition (SGCondition * condition);
108 virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
110 std::vector<SGSharedPtr<SGCondition> > _conditions;
115 * Abstract base class for property comparison conditions.
117 class SGComparisonCondition : public SGCondition
125 SGComparisonCondition (Type type, bool reverse = false);
126 virtual ~SGComparisonCondition ();
127 virtual bool test () const;
128 virtual void setLeftProperty( SGPropertyNode *prop_root,
129 const char * propname );
130 virtual void setRightProperty( SGPropertyNode *prop_root,
131 const char * propname );
132 virtual void setPrecisionProperty( SGPropertyNode *prop_root,
133 const char * propname );
134 // will make a local copy
135 virtual void setLeftValue (const SGPropertyNode * value);
136 virtual void setRightValue (const SGPropertyNode * value);
137 virtual void setPrecisionValue (const SGPropertyNode * value);
139 void setLeftDExpression(SGExpressiond* dexp);
140 void setRightDExpression(SGExpressiond* dexp);
141 void setPrecisionDExpression(SGExpressiond* dexp);
143 virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
147 SGPropertyNode_ptr _left_property;
148 SGPropertyNode_ptr _right_property;
149 SGPropertyNode_ptr _precision_property;
151 SGSharedPtr<SGExpressiond> _left_dexp;
152 SGSharedPtr<SGExpressiond> _right_dexp;
153 SGSharedPtr<SGExpressiond> _precision_dexp;
157 ////////////////////////////////////////////////////////////////////////
158 // Implementation of SGCondition.
159 ////////////////////////////////////////////////////////////////////////
161 SGCondition::SGCondition ()
165 SGCondition::~SGCondition ()
170 ////////////////////////////////////////////////////////////////////////
171 // Implementation of SGPropertyCondition.
172 ////////////////////////////////////////////////////////////////////////
174 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
175 const char *propname )
176 : _node( prop_root->getNode(propname, true) )
180 SGPropertyCondition::~SGPropertyCondition ()
185 ////////////////////////////////////////////////////////////////////////
186 // Implementation of SGNotCondition.
187 ////////////////////////////////////////////////////////////////////////
189 SGNotCondition::SGNotCondition (SGCondition * condition)
190 : _condition(condition)
194 SGNotCondition::~SGNotCondition ()
199 SGNotCondition::test () const
201 return !(_condition->test());
205 SGNotCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
207 _condition->collectDependentProperties(props);
210 ////////////////////////////////////////////////////////////////////////
211 // Implementation of SGAndCondition.
212 ////////////////////////////////////////////////////////////////////////
214 SGAndCondition::SGAndCondition ()
218 SGAndCondition::~SGAndCondition ()
223 SGAndCondition::test () const
225 for( size_t i = 0; i < _conditions.size(); i++ )
227 if (!_conditions[i]->test())
234 SGAndCondition::addCondition (SGCondition * condition)
236 _conditions.push_back(condition);
240 SGAndCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
242 for( size_t i = 0; i < _conditions.size(); i++ )
243 _conditions[i]->collectDependentProperties(props);
247 ////////////////////////////////////////////////////////////////////////
248 // Implementation of SGOrCondition.
249 ////////////////////////////////////////////////////////////////////////
251 SGOrCondition::SGOrCondition ()
255 SGOrCondition::~SGOrCondition ()
260 SGOrCondition::test () const
262 for( size_t i = 0; i < _conditions.size(); i++ )
264 if (_conditions[i]->test())
271 SGOrCondition::addCondition (SGCondition * condition)
273 _conditions.push_back(condition);
277 SGOrCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
279 for( size_t i = 0; i < _conditions.size(); i++ )
280 _conditions[i]->collectDependentProperties(props);
284 ////////////////////////////////////////////////////////////////////////
285 // Implementation of SGComparisonCondition.
286 ////////////////////////////////////////////////////////////////////////
289 static int doComp( T v1, T v2, T e )
293 return SGComparisonCondition::LESS_THAN;
295 return SGComparisonCondition::GREATER_THAN;
297 return SGComparisonCondition::EQUALS;
301 doComparison (const SGPropertyNode * left, const SGPropertyNode * right, const SGPropertyNode * precision )
303 using namespace simgear;
304 switch (left->getType()) {
306 bool v1 = left->getBoolValue();
307 bool v2 = right->getBoolValue();
309 return SGComparisonCondition::LESS_THAN;
311 return SGComparisonCondition::GREATER_THAN;
313 return SGComparisonCondition::EQUALS;
317 return doComp<int>(left->getIntValue(), right->getIntValue(),
318 precision ? std::abs(precision->getIntValue()/2) : 0 );
321 return doComp<long>(left->getLongValue(), right->getLongValue(),
322 precision ? std::abs(precision->getLongValue()/2L) : 0L );
325 return doComp<float>(left->getFloatValue(), right->getFloatValue(),
326 precision ? std::fabs(precision->getFloatValue()/2.0f) : 0.0f );
329 return doComp<double>(left->getDoubleValue(), right->getDoubleValue(),
330 precision ? std::fabs(precision->getDoubleValue()/2.0) : 0.0 );
334 case props::UNSPECIFIED: {
335 size_t l = precision ? precision->getLongValue() : string::npos;
336 string v1 = string(left->getStringValue()).substr(0,l);
337 string v2 = string(right->getStringValue()).substr(0,l);
339 return SGComparisonCondition::LESS_THAN;
341 return SGComparisonCondition::GREATER_THAN;
343 return SGComparisonCondition::EQUALS;
347 throw sg_exception("condition: unrecognized node type in comparison");
354 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
360 SGComparisonCondition::~SGComparisonCondition ()
365 SGComparisonCondition::test () const
367 // Always fail if incompletely specified
368 if (!_left_property || !_right_property)
371 // Get LESS_THAN, EQUALS, or GREATER_THAN
373 _left_property->setDoubleValue(_left_dexp->getValue(NULL));
377 _right_property->setDoubleValue(_right_dexp->getValue(NULL));
380 if (_precision_dexp) {
381 _precision_property->setDoubleValue(_precision_dexp->getValue(NULL));
384 int cmp = doComparison(_left_property, _right_property, _precision_property );
386 return (cmp == _type);
388 return (cmp != _type);
392 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
393 const char * propname )
395 _left_property = prop_root->getNode(propname, true);
399 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
400 const char * propname )
402 _right_property = prop_root->getNode(propname, true);
406 SGComparisonCondition::setPrecisionProperty( SGPropertyNode *prop_root,
407 const char * propname )
409 _precision_property = prop_root->getNode(propname, true);
413 SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
415 _left_property = new SGPropertyNode(*node);
419 SGComparisonCondition::setPrecisionValue (const SGPropertyNode *node)
421 _precision_property = new SGPropertyNode(*node);
425 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
427 _right_property = new SGPropertyNode(*node);
431 SGComparisonCondition::setLeftDExpression(SGExpressiond* dexp)
433 _left_property = new SGPropertyNode();
438 SGComparisonCondition::setRightDExpression(SGExpressiond* dexp)
440 _right_property = new SGPropertyNode();
445 SGComparisonCondition::setPrecisionDExpression(SGExpressiond* dexp)
447 _precision_property = new SGPropertyNode();
448 _precision_dexp = dexp;
452 SGComparisonCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
455 _left_dexp->collectDependentProperties(props);
457 props.insert(_left_property);
460 _right_dexp->collectDependentProperties(props);
462 props.insert(_right_property);
465 _precision_dexp->collectDependentProperties(props);
466 else if (_precision_property)
467 props.insert(_precision_property);
471 ////////////////////////////////////////////////////////////////////////
472 // Read a condition and use it if necessary.
473 ////////////////////////////////////////////////////////////////////////
475 // Forward declaration
476 static SGCondition * readCondition( SGPropertyNode *prop_root,
477 const SGPropertyNode *node );
480 readPropertyCondition( SGPropertyNode *prop_root,
481 const SGPropertyNode *node )
483 return new SGPropertyCondition( prop_root, node->getStringValue() );
487 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
489 int nChildren = node->nChildren();
490 for (int i = 0; i < nChildren; i++) {
491 const SGPropertyNode * child = node->getChild(i);
492 SGCondition * condition = readCondition(prop_root, child);
494 return new SGNotCondition(condition);
496 SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
501 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
503 SGAndCondition * andCondition = new SGAndCondition;
504 int nChildren = node->nChildren();
505 for (int i = 0; i < nChildren; i++) {
506 const SGPropertyNode * child = node->getChild(i);
507 SGCondition * condition = readCondition(prop_root, child);
509 andCondition->addCondition(condition);
515 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
517 SGOrCondition * orCondition = new SGOrCondition;
518 int nChildren = node->nChildren();
519 for (int i = 0; i < nChildren; i++) {
520 const SGPropertyNode * child = node->getChild(i);
521 SGCondition * condition = readCondition(prop_root, child);
523 orCondition->addCondition(condition);
529 readComparison( SGPropertyNode *prop_root,
530 const SGPropertyNode *node,
531 SGComparisonCondition::Type type,
534 SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
535 if (node->nChildren() < 2 || node->nChildren() > 3 ) {
536 throw sg_exception("condition: comparison without two or three children");
539 const SGPropertyNode* left = node->getChild(0),
540 *right = node->getChild(1);
543 string leftName(left->getName());
544 if (leftName == "property") {
545 condition->setLeftProperty(prop_root, left->getStringValue());
546 } else if (leftName == "value") {
547 condition->setLeftValue(left);
548 } else if (leftName == "expression") {
549 SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
550 condition->setLeftDExpression(exp);
552 throw sg_exception("Unknown condition comparison left child:" + leftName);
557 string rightName(right->getName());
558 if (rightName == "property") {
559 condition->setRightProperty(prop_root, right->getStringValue());
560 } else if (rightName == "value") {
561 condition->setRightValue(right);
562 } else if (rightName == "expression") {
563 SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
564 condition->setRightDExpression(exp);
566 throw sg_exception("Unknown condition comparison right child:" + rightName);
570 if( node->nChildren() == 3 ) {
571 const SGPropertyNode *n = node->getChild(2);
572 string name(n->getName());
573 if (name == "precision-property") {
574 condition->setPrecisionProperty(prop_root, n->getStringValue());
575 } else if (name == "precision-value") {
576 condition->setPrecisionValue(n);
577 } else if (name == "precision-expression") {
578 SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
579 condition->setPrecisionDExpression(exp);
581 throw sg_exception("Unknown condition comparison precision child:" + name );
589 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
591 const string &name = node->getName();
592 if (name == "property")
593 return readPropertyCondition(prop_root, node);
594 else if (name == "not")
595 return readNotCondition(prop_root, node);
596 else if (name == "and")
597 return readAndConditions(prop_root, node);
598 else if (name == "or")
599 return readOrConditions(prop_root, node);
600 else if (name == "less-than")
601 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
603 else if (name == "less-than-equals")
604 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
606 else if (name == "greater-than")
607 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
609 else if (name == "greater-than-equals")
610 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
612 else if (name == "equals")
613 return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
615 else if (name == "not-equals")
616 return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
617 else if (name == "false")
618 return new SGConstantCondition(false);
619 else if (name == "true")
620 return new SGConstantCondition(true);
626 ////////////////////////////////////////////////////////////////////////
627 // Implementation of SGConditional.
628 ////////////////////////////////////////////////////////////////////////
630 SGConditional::SGConditional ()
635 SGConditional::~SGConditional ()
640 SGConditional::setCondition (SGCondition * condition)
642 _condition = condition;
646 SGConditional::test () const
648 return ((_condition == 0) || _condition->test());
652 // The top-level is always an implicit 'and' group
654 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
656 return readAndConditions(prop_root, node);
660 // end of condition.cxx