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>
27 * Condition for a single property.
29 * This condition is true only if the property returns a boolean
32 class SGPropertyCondition : public SGCondition
35 SGPropertyCondition ( SGPropertyNode *prop_root,
36 const char * propname );
37 virtual ~SGPropertyCondition ();
38 virtual bool test () const { return _node->getBoolValue(); }
40 SGConstPropertyNode_ptr _node;
44 * Condition with constant value
47 class SGConstantCondition : public SGCondition
50 SGConstantCondition (bool v) : _value(v) { ; }
51 virtual bool test () const { return _value; }
57 * Condition for a 'not' operator.
59 * This condition is true only if the child condition is false.
61 class SGNotCondition : public SGCondition
64 SGNotCondition (SGCondition * condition);
65 virtual ~SGNotCondition ();
66 virtual bool test () const;
68 SGSharedPtr<SGCondition> _condition;
73 * Condition for an 'and' group.
75 * This condition is true only if all of the conditions
76 * in the group are true.
78 class SGAndCondition : public SGCondition
82 virtual ~SGAndCondition ();
83 virtual bool test () const;
84 // transfer pointer ownership
85 virtual void addCondition (SGCondition * condition);
87 std::vector<SGSharedPtr<SGCondition> > _conditions;
92 * Condition for an 'or' group.
94 * This condition is true if at least one of the conditions in the
97 class SGOrCondition : public SGCondition
101 virtual ~SGOrCondition ();
102 virtual bool test () const;
103 // transfer pointer ownership
104 virtual void addCondition (SGCondition * condition);
106 std::vector<SGSharedPtr<SGCondition> > _conditions;
111 * Abstract base class for property comparison conditions.
113 class SGComparisonCondition : public SGCondition
121 SGComparisonCondition (Type type, bool reverse = false);
122 virtual ~SGComparisonCondition ();
123 virtual bool test () const;
124 virtual void setLeftProperty( SGPropertyNode *prop_root,
125 const char * propname );
126 virtual void setRightProperty( SGPropertyNode *prop_root,
127 const char * propname );
128 virtual void setPrecisionProperty( SGPropertyNode *prop_root,
129 const char * propname );
130 // will make a local copy
131 virtual void setLeftValue (const SGPropertyNode * value);
132 virtual void setRightValue (const SGPropertyNode * value);
133 virtual void setPrecisionValue (const SGPropertyNode * value);
135 void setLeftDExpression(SGExpressiond* dexp);
136 void setRightDExpression(SGExpressiond* dexp);
137 void setPrecisionDExpression(SGExpressiond* dexp);
142 SGPropertyNode_ptr _left_property;
143 SGPropertyNode_ptr _right_property;
144 SGPropertyNode_ptr _precision_property;
146 SGSharedPtr<SGExpressiond> _left_dexp;
147 SGSharedPtr<SGExpressiond> _right_dexp;
148 SGSharedPtr<SGExpressiond> _precision_dexp;
152 ////////////////////////////////////////////////////////////////////////
153 // Implementation of SGCondition.
154 ////////////////////////////////////////////////////////////////////////
156 SGCondition::SGCondition ()
160 SGCondition::~SGCondition ()
166 ////////////////////////////////////////////////////////////////////////
167 // Implementation of SGPropertyCondition.
168 ////////////////////////////////////////////////////////////////////////
170 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
171 const char *propname )
172 : _node( prop_root->getNode(propname, true) )
176 SGPropertyCondition::~SGPropertyCondition ()
182 ////////////////////////////////////////////////////////////////////////
183 // Implementation of SGNotCondition.
184 ////////////////////////////////////////////////////////////////////////
186 SGNotCondition::SGNotCondition (SGCondition * condition)
187 : _condition(condition)
191 SGNotCondition::~SGNotCondition ()
196 SGNotCondition::test () const
198 return !(_condition->test());
203 ////////////////////////////////////////////////////////////////////////
204 // Implementation of SGAndCondition.
205 ////////////////////////////////////////////////////////////////////////
207 SGAndCondition::SGAndCondition ()
211 SGAndCondition::~SGAndCondition ()
216 SGAndCondition::test () const
218 int nConditions = _conditions.size();
219 for (int i = 0; i < nConditions; i++) {
220 if (!_conditions[i]->test())
227 SGAndCondition::addCondition (SGCondition * condition)
229 _conditions.push_back(condition);
234 ////////////////////////////////////////////////////////////////////////
235 // Implementation of SGOrCondition.
236 ////////////////////////////////////////////////////////////////////////
238 SGOrCondition::SGOrCondition ()
242 SGOrCondition::~SGOrCondition ()
247 SGOrCondition::test () const
249 int nConditions = _conditions.size();
250 for (int i = 0; i < nConditions; i++) {
251 if (_conditions[i]->test())
258 SGOrCondition::addCondition (SGCondition * condition)
260 _conditions.push_back(condition);
265 ////////////////////////////////////////////////////////////////////////
266 // Implementation of SGComparisonCondition.
267 ////////////////////////////////////////////////////////////////////////
270 static int doComp( T v1, T v2, T e )
274 return SGComparisonCondition::LESS_THAN;
276 return SGComparisonCondition::GREATER_THAN;
278 return SGComparisonCondition::EQUALS;
282 doComparison (const SGPropertyNode * left, const SGPropertyNode * right, const SGPropertyNode * precision )
284 using namespace simgear;
285 switch (left->getType()) {
287 bool v1 = left->getBoolValue();
288 bool v2 = right->getBoolValue();
290 return SGComparisonCondition::LESS_THAN;
292 return SGComparisonCondition::GREATER_THAN;
294 return SGComparisonCondition::EQUALS;
298 return doComp<int>(left->getIntValue(), right->getIntValue(),
299 precision ? std::abs(precision->getIntValue()/2) : 0 );
302 return doComp<long>(left->getLongValue(), right->getLongValue(),
303 precision ? std::abs(precision->getLongValue()/2L) : 0L );
306 return doComp<float>(left->getFloatValue(), right->getFloatValue(),
307 precision ? std::fabs(precision->getFloatValue()/2.0f) : 0.0f );
310 return doComp<double>(left->getDoubleValue(), right->getDoubleValue(),
311 precision ? std::fabs(precision->getDoubleValue()/2.0) : 0.0 );
315 case props::UNSPECIFIED: {
316 size_t l = precision ? precision->getLongValue() : string::npos;
317 string v1 = string(left->getStringValue()).substr(0,l);
318 string v2 = string(right->getStringValue()).substr(0,l);
320 return SGComparisonCondition::LESS_THAN;
322 return SGComparisonCondition::GREATER_THAN;
324 return SGComparisonCondition::EQUALS;
328 throw sg_exception("condition: unrecognized node type in comparison");
335 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
341 SGComparisonCondition::~SGComparisonCondition ()
346 SGComparisonCondition::test () const
348 // Always fail if incompletely specified
349 if (!_left_property || !_right_property)
352 // Get LESS_THAN, EQUALS, or GREATER_THAN
354 _left_property->setDoubleValue(_left_dexp->getValue(NULL));
358 _right_property->setDoubleValue(_right_dexp->getValue(NULL));
361 if (_precision_dexp) {
362 _precision_property->setDoubleValue(_precision_dexp->getValue(NULL));
365 int cmp = doComparison(_left_property, _right_property, _precision_property );
367 return (cmp == _type);
369 return (cmp != _type);
373 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
374 const char * propname )
376 _left_property = prop_root->getNode(propname, true);
380 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
381 const char * propname )
383 _right_property = prop_root->getNode(propname, true);
387 SGComparisonCondition::setPrecisionProperty( SGPropertyNode *prop_root,
388 const char * propname )
390 _precision_property = prop_root->getNode(propname, true);
394 SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
396 _left_property = new SGPropertyNode(*node);
400 SGComparisonCondition::setPrecisionValue (const SGPropertyNode *node)
402 _precision_property = new SGPropertyNode(*node);
406 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
408 _right_property = new SGPropertyNode(*node);
412 SGComparisonCondition::setLeftDExpression(SGExpressiond* dexp)
414 _left_property = new SGPropertyNode();
419 SGComparisonCondition::setRightDExpression(SGExpressiond* dexp)
421 _right_property = new SGPropertyNode();
426 SGComparisonCondition::setPrecisionDExpression(SGExpressiond* dexp)
428 _precision_property = new SGPropertyNode();
429 _precision_dexp = dexp;
431 ////////////////////////////////////////////////////////////////////////
432 // Read a condition and use it if necessary.
433 ////////////////////////////////////////////////////////////////////////
435 // Forward declaration
436 static SGCondition * readCondition( SGPropertyNode *prop_root,
437 const SGPropertyNode *node );
440 readPropertyCondition( SGPropertyNode *prop_root,
441 const SGPropertyNode *node )
443 return new SGPropertyCondition( prop_root, node->getStringValue() );
447 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
449 int nChildren = node->nChildren();
450 for (int i = 0; i < nChildren; i++) {
451 const SGPropertyNode * child = node->getChild(i);
452 SGCondition * condition = readCondition(prop_root, child);
454 return new SGNotCondition(condition);
456 SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
461 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
463 SGAndCondition * andCondition = new SGAndCondition;
464 int nChildren = node->nChildren();
465 for (int i = 0; i < nChildren; i++) {
466 const SGPropertyNode * child = node->getChild(i);
467 SGCondition * condition = readCondition(prop_root, child);
469 andCondition->addCondition(condition);
475 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
477 SGOrCondition * orCondition = new SGOrCondition;
478 int nChildren = node->nChildren();
479 for (int i = 0; i < nChildren; i++) {
480 const SGPropertyNode * child = node->getChild(i);
481 SGCondition * condition = readCondition(prop_root, child);
483 orCondition->addCondition(condition);
489 readComparison( SGPropertyNode *prop_root,
490 const SGPropertyNode *node,
491 SGComparisonCondition::Type type,
494 SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
495 if (node->nChildren() < 2 || node->nChildren() > 3 ) {
496 throw sg_exception("condition: comparison without two or three children");
499 const SGPropertyNode* left = node->getChild(0),
500 *right = node->getChild(1);
503 string leftName(left->getName());
504 if (leftName == "property") {
505 condition->setLeftProperty(prop_root, left->getStringValue());
506 } else if (leftName == "value") {
507 condition->setLeftValue(left);
508 } else if (leftName == "expression") {
509 SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
510 condition->setLeftDExpression(exp);
512 throw sg_exception("Unknown condition comparison left child:" + leftName);
517 string rightName(right->getName());
518 if (rightName == "property") {
519 condition->setRightProperty(prop_root, right->getStringValue());
520 } else if (rightName == "value") {
521 condition->setRightValue(right);
522 } else if (rightName == "expression") {
523 SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
524 condition->setRightDExpression(exp);
526 throw sg_exception("Unknown condition comparison right child:" + rightName);
530 if( node->nChildren() == 3 ) {
531 const SGPropertyNode *n = node->getChild(2);
532 string name(n->getName());
533 if (name == "precision-property") {
534 condition->setPrecisionProperty(prop_root, n->getStringValue());
535 } else if (name == "precision-value") {
536 condition->setPrecisionValue(n);
537 } else if (name == "precision-expression") {
538 SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
539 condition->setPrecisionDExpression(exp);
541 throw sg_exception("Unknown condition comparison precision child:" + name );
549 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
551 const string &name = node->getName();
552 if (name == "property")
553 return readPropertyCondition(prop_root, node);
554 else if (name == "not")
555 return readNotCondition(prop_root, node);
556 else if (name == "and")
557 return readAndConditions(prop_root, node);
558 else if (name == "or")
559 return readOrConditions(prop_root, node);
560 else if (name == "less-than")
561 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
563 else if (name == "less-than-equals")
564 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
566 else if (name == "greater-than")
567 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
569 else if (name == "greater-than-equals")
570 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
572 else if (name == "equals")
573 return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
575 else if (name == "not-equals")
576 return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
577 else if (name == "false")
578 return new SGConstantCondition(false);
579 else if (name == "true")
580 return new SGConstantCondition(true);
587 ////////////////////////////////////////////////////////////////////////
588 // Implementation of SGConditional.
589 ////////////////////////////////////////////////////////////////////////
591 SGConditional::SGConditional ()
596 SGConditional::~SGConditional ()
601 SGConditional::setCondition (SGCondition * condition)
603 _condition = condition;
607 SGConditional::test () const
609 return ((_condition == 0) || _condition->test());
614 // The top-level is always an implicit 'and' group
616 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
618 return readAndConditions(prop_root, node);
622 // end of condition.cxx