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/math/SGMath.hxx>
22 #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(); }
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;
69 SGSharedPtr<SGCondition> _condition;
74 * Condition for an 'and' group.
76 * This condition is true only if all of the conditions
77 * in the group are true.
79 class SGAndCondition : public SGCondition
83 virtual ~SGAndCondition ();
84 virtual bool test () const;
85 // transfer pointer ownership
86 virtual void addCondition (SGCondition * condition);
88 std::vector<SGSharedPtr<SGCondition> > _conditions;
93 * Condition for an 'or' group.
95 * This condition is true if at least one of the conditions in the
98 class SGOrCondition : public SGCondition
102 virtual ~SGOrCondition ();
103 virtual bool test () const;
104 // transfer pointer ownership
105 virtual void addCondition (SGCondition * condition);
107 std::vector<SGSharedPtr<SGCondition> > _conditions;
112 * Abstract base class for property comparison conditions.
114 class SGComparisonCondition : public SGCondition
122 SGComparisonCondition (Type type, bool reverse = false);
123 virtual ~SGComparisonCondition ();
124 virtual bool test () const;
125 virtual void setLeftProperty( SGPropertyNode *prop_root,
126 const char * propname );
127 virtual void setRightProperty( SGPropertyNode *prop_root,
128 const char * propname );
129 virtual void setPrecisionProperty( SGPropertyNode *prop_root,
130 const char * propname );
131 // will make a local copy
132 virtual void setLeftValue (const SGPropertyNode * value);
133 virtual void setRightValue (const SGPropertyNode * value);
134 virtual void setPrecisionValue (const SGPropertyNode * value);
136 void setLeftDExpression(SGExpressiond* dexp);
137 void setRightDExpression(SGExpressiond* dexp);
138 void setPrecisionDExpression(SGExpressiond* dexp);
143 SGPropertyNode_ptr _left_property;
144 SGPropertyNode_ptr _right_property;
145 SGPropertyNode_ptr _precision_property;
147 SGSharedPtr<SGExpressiond> _left_dexp;
148 SGSharedPtr<SGExpressiond> _right_dexp;
149 SGSharedPtr<SGExpressiond> _precision_dexp;
153 ////////////////////////////////////////////////////////////////////////
154 // Implementation of SGCondition.
155 ////////////////////////////////////////////////////////////////////////
157 SGCondition::SGCondition ()
161 SGCondition::~SGCondition ()
167 ////////////////////////////////////////////////////////////////////////
168 // Implementation of SGPropertyCondition.
169 ////////////////////////////////////////////////////////////////////////
171 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
172 const char *propname )
173 : _node( prop_root->getNode(propname, true) )
177 SGPropertyCondition::~SGPropertyCondition ()
183 ////////////////////////////////////////////////////////////////////////
184 // Implementation of SGNotCondition.
185 ////////////////////////////////////////////////////////////////////////
187 SGNotCondition::SGNotCondition (SGCondition * condition)
188 : _condition(condition)
192 SGNotCondition::~SGNotCondition ()
197 SGNotCondition::test () const
199 return !(_condition->test());
204 ////////////////////////////////////////////////////////////////////////
205 // Implementation of SGAndCondition.
206 ////////////////////////////////////////////////////////////////////////
208 SGAndCondition::SGAndCondition ()
212 SGAndCondition::~SGAndCondition ()
217 SGAndCondition::test () const
219 int nConditions = _conditions.size();
220 for (int i = 0; i < nConditions; i++) {
221 if (!_conditions[i]->test())
228 SGAndCondition::addCondition (SGCondition * condition)
230 _conditions.push_back(condition);
235 ////////////////////////////////////////////////////////////////////////
236 // Implementation of SGOrCondition.
237 ////////////////////////////////////////////////////////////////////////
239 SGOrCondition::SGOrCondition ()
243 SGOrCondition::~SGOrCondition ()
248 SGOrCondition::test () const
250 int nConditions = _conditions.size();
251 for (int i = 0; i < nConditions; i++) {
252 if (_conditions[i]->test())
259 SGOrCondition::addCondition (SGCondition * condition)
261 _conditions.push_back(condition);
266 ////////////////////////////////////////////////////////////////////////
267 // Implementation of SGComparisonCondition.
268 ////////////////////////////////////////////////////////////////////////
271 static int doComp( T v1, T v2, T e )
275 return SGComparisonCondition::LESS_THAN;
277 return SGComparisonCondition::GREATER_THAN;
279 return SGComparisonCondition::EQUALS;
283 doComparison (const SGPropertyNode * left, const SGPropertyNode * right, const SGPropertyNode * precision )
285 using namespace simgear;
286 switch (left->getType()) {
288 bool v1 = left->getBoolValue();
289 bool v2 = right->getBoolValue();
291 return SGComparisonCondition::LESS_THAN;
293 return SGComparisonCondition::GREATER_THAN;
295 return SGComparisonCondition::EQUALS;
299 return doComp<int>(left->getIntValue(), right->getIntValue(),
300 precision ? abs(precision->getIntValue()/2) : 0 );
303 return doComp<long>(left->getLongValue(), right->getLongValue(),
304 precision ? abs(precision->getLongValue()/2L) : 0L );
307 return doComp<float>(left->getFloatValue(), right->getFloatValue(),
308 precision ? fabs(precision->getFloatValue()/2.0f) : 0.0f );
311 return doComp<double>(left->getDoubleValue(), right->getDoubleValue(),
312 precision ? fabs(precision->getDoubleValue()/2.0) : 0.0 );
316 case props::UNSPECIFIED: {
317 size_t l = precision ? precision->getLongValue() : string::npos;
318 string v1 = string(left->getStringValue()).substr(0,l);
319 string v2 = string(right->getStringValue()).substr(0,l);
321 return SGComparisonCondition::LESS_THAN;
323 return SGComparisonCondition::GREATER_THAN;
325 return SGComparisonCondition::EQUALS;
329 throw sg_exception("condition: unrecognized node type in comparison");
336 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
342 SGComparisonCondition::~SGComparisonCondition ()
347 SGComparisonCondition::test () const
349 // Always fail if incompletely specified
350 if (!_left_property || !_right_property)
353 // Get LESS_THAN, EQUALS, or GREATER_THAN
355 _left_property->setDoubleValue(_left_dexp->getValue(NULL));
359 _right_property->setDoubleValue(_right_dexp->getValue(NULL));
362 if (_precision_dexp) {
363 _precision_property->setDoubleValue(_precision_dexp->getValue(NULL));
366 int cmp = doComparison(_left_property, _right_property, _precision_property );
368 return (cmp == _type);
370 return (cmp != _type);
374 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
375 const char * propname )
377 _left_property = prop_root->getNode(propname, true);
381 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
382 const char * propname )
384 _right_property = prop_root->getNode(propname, true);
388 SGComparisonCondition::setPrecisionProperty( SGPropertyNode *prop_root,
389 const char * propname )
391 _precision_property = prop_root->getNode(propname, true);
395 SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
397 _left_property = new SGPropertyNode(*node);
401 SGComparisonCondition::setPrecisionValue (const SGPropertyNode *node)
403 _precision_property = new SGPropertyNode(*node);
407 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
409 _right_property = new SGPropertyNode(*node);
413 SGComparisonCondition::setLeftDExpression(SGExpressiond* dexp)
415 _left_property = new SGPropertyNode();
420 SGComparisonCondition::setRightDExpression(SGExpressiond* dexp)
422 _right_property = new SGPropertyNode();
427 SGComparisonCondition::setPrecisionDExpression(SGExpressiond* dexp)
429 _precision_property = new SGPropertyNode();
430 _precision_dexp = dexp;
432 ////////////////////////////////////////////////////////////////////////
433 // Read a condition and use it if necessary.
434 ////////////////////////////////////////////////////////////////////////
436 // Forward declaration
437 static SGCondition * readCondition( SGPropertyNode *prop_root,
438 const SGPropertyNode *node );
441 readPropertyCondition( SGPropertyNode *prop_root,
442 const SGPropertyNode *node )
444 return new SGPropertyCondition( prop_root, node->getStringValue() );
448 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
450 int nChildren = node->nChildren();
451 for (int i = 0; i < nChildren; i++) {
452 const SGPropertyNode * child = node->getChild(i);
453 SGCondition * condition = readCondition(prop_root, child);
455 return new SGNotCondition(condition);
457 SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
462 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
464 SGAndCondition * andCondition = new SGAndCondition;
465 int nChildren = node->nChildren();
466 for (int i = 0; i < nChildren; i++) {
467 const SGPropertyNode * child = node->getChild(i);
468 SGCondition * condition = readCondition(prop_root, child);
470 andCondition->addCondition(condition);
476 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
478 SGOrCondition * orCondition = new SGOrCondition;
479 int nChildren = node->nChildren();
480 for (int i = 0; i < nChildren; i++) {
481 const SGPropertyNode * child = node->getChild(i);
482 SGCondition * condition = readCondition(prop_root, child);
484 orCondition->addCondition(condition);
490 readComparison( SGPropertyNode *prop_root,
491 const SGPropertyNode *node,
492 SGComparisonCondition::Type type,
495 SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
496 if (node->nChildren() < 2 || node->nChildren() > 3 ) {
497 throw sg_exception("condition: comparison without two or three children");
500 const SGPropertyNode* left = node->getChild(0),
501 *right = node->getChild(1);
504 string leftName(left->getName());
505 if (leftName == "property") {
506 condition->setLeftProperty(prop_root, left->getStringValue());
507 } else if (leftName == "value") {
508 condition->setLeftValue(left);
509 } else if (leftName == "expression") {
510 SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
511 condition->setLeftDExpression(exp);
513 throw sg_exception("Unknown condition comparison left child:" + leftName);
518 string rightName(right->getName());
519 if (rightName == "property") {
520 condition->setRightProperty(prop_root, right->getStringValue());
521 } else if (rightName == "value") {
522 condition->setRightValue(right);
523 } else if (rightName == "expression") {
524 SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
525 condition->setRightDExpression(exp);
527 throw sg_exception("Unknown condition comparison right child:" + rightName);
531 if( node->nChildren() == 3 ) {
532 const SGPropertyNode *n = node->getChild(2);
533 string name(n->getName());
534 if (name == "precision-property") {
535 condition->setPrecisionProperty(prop_root, n->getStringValue());
536 } else if (name == "precision-value") {
537 condition->setPrecisionValue(n);
538 } else if (name == "precision-expression") {
539 SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
540 condition->setPrecisionDExpression(exp);
542 throw sg_exception("Unknown condition comparison precision child:" + name );
550 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
552 const string &name = node->getName();
553 if (name == "property")
554 return readPropertyCondition(prop_root, node);
555 else if (name == "not")
556 return readNotCondition(prop_root, node);
557 else if (name == "and")
558 return readAndConditions(prop_root, node);
559 else if (name == "or")
560 return readOrConditions(prop_root, node);
561 else if (name == "less-than")
562 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
564 else if (name == "less-than-equals")
565 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
567 else if (name == "greater-than")
568 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
570 else if (name == "greater-than-equals")
571 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
573 else if (name == "equals")
574 return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
576 else if (name == "not-equals")
577 return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
578 else if (name == "false")
579 return new SGConstantCondition(false);
580 else if (name == "true")
581 return new SGConstantCondition(true);
588 ////////////////////////////////////////////////////////////////////////
589 // Implementation of SGConditional.
590 ////////////////////////////////////////////////////////////////////////
592 SGConditional::SGConditional ()
597 SGConditional::~SGConditional ()
602 SGConditional::setCondition (SGCondition * condition)
604 _condition = condition;
608 SGConditional::test () const
610 return ((_condition == 0) || _condition->test());
615 // The top-level is always an implicit 'and' group
617 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
619 return readAndConditions(prop_root, node);
623 // end of condition.cxx