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 // will make a local copy
130 virtual void setLeftValue (const SGPropertyNode * value);
131 virtual void setRightValue (const SGPropertyNode * value);
133 void setLeftDExpression(SGExpressiond* dexp);
134 void setRightDExpression(SGExpressiond* dexp);
139 SGPropertyNode_ptr _left_property;
140 SGPropertyNode_ptr _right_property;
142 SGSharedPtr<SGExpressiond> _left_dexp;
143 SGSharedPtr<SGExpressiond> _right_dexp;
147 ////////////////////////////////////////////////////////////////////////
148 // Implementation of SGCondition.
149 ////////////////////////////////////////////////////////////////////////
151 SGCondition::SGCondition ()
155 SGCondition::~SGCondition ()
161 ////////////////////////////////////////////////////////////////////////
162 // Implementation of SGPropertyCondition.
163 ////////////////////////////////////////////////////////////////////////
165 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
166 const char *propname )
167 : _node( prop_root->getNode(propname, true) )
171 SGPropertyCondition::~SGPropertyCondition ()
177 ////////////////////////////////////////////////////////////////////////
178 // Implementation of SGNotCondition.
179 ////////////////////////////////////////////////////////////////////////
181 SGNotCondition::SGNotCondition (SGCondition * condition)
182 : _condition(condition)
186 SGNotCondition::~SGNotCondition ()
191 SGNotCondition::test () const
193 return !(_condition->test());
198 ////////////////////////////////////////////////////////////////////////
199 // Implementation of SGAndCondition.
200 ////////////////////////////////////////////////////////////////////////
202 SGAndCondition::SGAndCondition ()
206 SGAndCondition::~SGAndCondition ()
211 SGAndCondition::test () const
213 int nConditions = _conditions.size();
214 for (int i = 0; i < nConditions; i++) {
215 if (!_conditions[i]->test())
222 SGAndCondition::addCondition (SGCondition * condition)
224 _conditions.push_back(condition);
229 ////////////////////////////////////////////////////////////////////////
230 // Implementation of SGOrCondition.
231 ////////////////////////////////////////////////////////////////////////
233 SGOrCondition::SGOrCondition ()
237 SGOrCondition::~SGOrCondition ()
242 SGOrCondition::test () const
244 int nConditions = _conditions.size();
245 for (int i = 0; i < nConditions; i++) {
246 if (_conditions[i]->test())
253 SGOrCondition::addCondition (SGCondition * condition)
255 _conditions.push_back(condition);
260 ////////////////////////////////////////////////////////////////////////
261 // Implementation of SGComparisonCondition.
262 ////////////////////////////////////////////////////////////////////////
265 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
267 using namespace simgear;
268 switch (left->getType()) {
270 bool v1 = left->getBoolValue();
271 bool v2 = right->getBoolValue();
273 return SGComparisonCondition::LESS_THAN;
275 return SGComparisonCondition::GREATER_THAN;
277 return SGComparisonCondition::EQUALS;
281 int v1 = left->getIntValue();
282 int v2 = right->getIntValue();
284 return SGComparisonCondition::LESS_THAN;
286 return SGComparisonCondition::GREATER_THAN;
288 return SGComparisonCondition::EQUALS;
292 long v1 = left->getLongValue();
293 long v2 = right->getLongValue();
295 return SGComparisonCondition::LESS_THAN;
297 return SGComparisonCondition::GREATER_THAN;
299 return SGComparisonCondition::EQUALS;
303 float v1 = left->getFloatValue();
304 float v2 = right->getFloatValue();
306 return SGComparisonCondition::LESS_THAN;
308 return SGComparisonCondition::GREATER_THAN;
310 return SGComparisonCondition::EQUALS;
313 case props::DOUBLE: {
314 double v1 = left->getDoubleValue();
315 double v2 = right->getDoubleValue();
317 return SGComparisonCondition::LESS_THAN;
319 return SGComparisonCondition::GREATER_THAN;
321 return SGComparisonCondition::EQUALS;
326 case props::UNSPECIFIED: {
327 string v1 = left->getStringValue();
328 string v2 = right->getStringValue();
330 return SGComparisonCondition::LESS_THAN;
332 return SGComparisonCondition::GREATER_THAN;
334 return SGComparisonCondition::EQUALS;
338 throw sg_exception("condition: unrecognized node type in comparison");
345 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
351 SGComparisonCondition::~SGComparisonCondition ()
356 SGComparisonCondition::test () const
358 // Always fail if incompletely specified
359 if (!_left_property || !_right_property)
362 // Get LESS_THAN, EQUALS, or GREATER_THAN
364 _left_property->setDoubleValue(_left_dexp->getValue(NULL));
368 _right_property->setDoubleValue(_right_dexp->getValue(NULL));
371 int cmp = doComparison(_left_property, _right_property);
373 return (cmp == _type);
375 return (cmp != _type);
379 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
380 const char * propname )
382 _left_property = prop_root->getNode(propname, true);
386 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
387 const char * propname )
389 _right_property = prop_root->getNode(propname, true);
393 SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
395 _left_property = new SGPropertyNode(*node);
400 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
402 _right_property = new SGPropertyNode(*node);
406 SGComparisonCondition::setLeftDExpression(SGExpressiond* dexp)
408 _left_property = new SGPropertyNode();
413 SGComparisonCondition::setRightDExpression(SGExpressiond* dexp)
415 _right_property = new SGPropertyNode();
418 ////////////////////////////////////////////////////////////////////////
419 // Read a condition and use it if necessary.
420 ////////////////////////////////////////////////////////////////////////
422 // Forward declaration
423 static SGCondition * readCondition( SGPropertyNode *prop_root,
424 const SGPropertyNode *node );
427 readPropertyCondition( SGPropertyNode *prop_root,
428 const SGPropertyNode *node )
430 return new SGPropertyCondition( prop_root, node->getStringValue() );
434 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
436 int nChildren = node->nChildren();
437 for (int i = 0; i < nChildren; i++) {
438 const SGPropertyNode * child = node->getChild(i);
439 SGCondition * condition = readCondition(prop_root, child);
441 return new SGNotCondition(condition);
443 SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
448 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
450 SGAndCondition * andCondition = new SGAndCondition;
451 int nChildren = node->nChildren();
452 for (int i = 0; i < nChildren; i++) {
453 const SGPropertyNode * child = node->getChild(i);
454 SGCondition * condition = readCondition(prop_root, child);
456 andCondition->addCondition(condition);
462 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
464 SGOrCondition * orCondition = new SGOrCondition;
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 orCondition->addCondition(condition);
476 readComparison( SGPropertyNode *prop_root,
477 const SGPropertyNode *node,
478 SGComparisonCondition::Type type,
481 SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
482 if (node->nChildren() != 2) {
483 throw sg_exception("condition: comparison without two children");
486 const SGPropertyNode* left = node->getChild(0),
487 *right = node->getChild(1);
488 string leftName(left->getName());
489 if (leftName == "property") {
490 condition->setLeftProperty(prop_root, left->getStringValue());
491 } else if (leftName == "value") {
492 condition->setLeftValue(left);
493 } else if (leftName == "expression") {
494 SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
495 condition->setLeftDExpression(exp);
497 throw sg_exception("Unknown condition comparison left child:" + leftName);
500 string rightName(right->getName());
501 if (rightName == "property") {
502 condition->setRightProperty(prop_root, right->getStringValue());
503 } else if (rightName == "value") {
504 condition->setRightValue(right);
505 } else if (rightName == "expression") {
506 SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
507 condition->setRightDExpression(exp);
509 throw sg_exception("Unknown condition comparison right child:" + rightName);
516 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
518 const string &name = node->getName();
519 if (name == "property")
520 return readPropertyCondition(prop_root, node);
521 else if (name == "not")
522 return readNotCondition(prop_root, node);
523 else if (name == "and")
524 return readAndConditions(prop_root, node);
525 else if (name == "or")
526 return readOrConditions(prop_root, node);
527 else if (name == "less-than")
528 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
530 else if (name == "less-than-equals")
531 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
533 else if (name == "greater-than")
534 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
536 else if (name == "greater-than-equals")
537 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
539 else if (name == "equals")
540 return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
542 else if (name == "not-equals")
543 return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
544 else if (name == "false")
545 return new SGConstantCondition(false);
546 else if (name == "true")
547 return new SGConstantCondition(true);
554 ////////////////////////////////////////////////////////////////////////
555 // Implementation of SGConditional.
556 ////////////////////////////////////////////////////////////////////////
558 SGConditional::SGConditional ()
563 SGConditional::~SGConditional ()
568 SGConditional::setCondition (SGCondition * condition)
570 _condition = condition;
574 SGConditional::test () const
576 return ((_condition == 0) || _condition->test());
581 // The top-level is always an implicit 'and' group
583 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
585 return readAndConditions(prop_root, node);
589 // end of condition.cxx