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;
46 * Condition for a 'not' operator.
48 * This condition is true only if the child condition is false.
50 class SGNotCondition : public SGCondition
53 SGNotCondition (SGCondition * condition);
54 virtual ~SGNotCondition ();
55 virtual bool test () const;
57 SGSharedPtr<SGCondition> _condition;
62 * Condition for an 'and' group.
64 * This condition is true only if all of the conditions
65 * in the group are true.
67 class SGAndCondition : public SGCondition
71 virtual ~SGAndCondition ();
72 virtual bool test () const;
73 // transfer pointer ownership
74 virtual void addCondition (SGCondition * condition);
76 std::vector<SGSharedPtr<SGCondition> > _conditions;
81 * Condition for an 'or' group.
83 * This condition is true if at least one of the conditions in the
86 class SGOrCondition : public SGCondition
90 virtual ~SGOrCondition ();
91 virtual bool test () const;
92 // transfer pointer ownership
93 virtual void addCondition (SGCondition * condition);
95 std::vector<SGSharedPtr<SGCondition> > _conditions;
100 * Abstract base class for property comparison conditions.
102 class SGComparisonCondition : public SGCondition
110 SGComparisonCondition (Type type, bool reverse = false);
111 virtual ~SGComparisonCondition ();
112 virtual bool test () const;
113 virtual void setLeftProperty( SGPropertyNode *prop_root,
114 const char * propname );
115 virtual void setRightProperty( SGPropertyNode *prop_root,
116 const char * propname );
117 // will make a local copy
118 virtual void setLeftValue (const SGPropertyNode * value);
119 virtual void setRightValue (const SGPropertyNode * value);
121 void setLeftDExpression(SGExpressiond* dexp);
122 void setRightDExpression(SGExpressiond* dexp);
127 SGPropertyNode_ptr _left_property;
128 SGPropertyNode_ptr _right_property;
130 SGSharedPtr<SGExpressiond> _left_dexp;
131 SGSharedPtr<SGExpressiond> _right_dexp;
135 ////////////////////////////////////////////////////////////////////////
136 // Implementation of SGCondition.
137 ////////////////////////////////////////////////////////////////////////
139 SGCondition::SGCondition ()
143 SGCondition::~SGCondition ()
149 ////////////////////////////////////////////////////////////////////////
150 // Implementation of SGPropertyCondition.
151 ////////////////////////////////////////////////////////////////////////
153 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
154 const char *propname )
155 : _node( prop_root->getNode(propname, true) )
159 SGPropertyCondition::~SGPropertyCondition ()
165 ////////////////////////////////////////////////////////////////////////
166 // Implementation of SGNotCondition.
167 ////////////////////////////////////////////////////////////////////////
169 SGNotCondition::SGNotCondition (SGCondition * condition)
170 : _condition(condition)
174 SGNotCondition::~SGNotCondition ()
179 SGNotCondition::test () const
181 return !(_condition->test());
186 ////////////////////////////////////////////////////////////////////////
187 // Implementation of SGAndCondition.
188 ////////////////////////////////////////////////////////////////////////
190 SGAndCondition::SGAndCondition ()
194 SGAndCondition::~SGAndCondition ()
199 SGAndCondition::test () const
201 int nConditions = _conditions.size();
202 for (int i = 0; i < nConditions; i++) {
203 if (!_conditions[i]->test())
210 SGAndCondition::addCondition (SGCondition * condition)
212 _conditions.push_back(condition);
217 ////////////////////////////////////////////////////////////////////////
218 // Implementation of SGOrCondition.
219 ////////////////////////////////////////////////////////////////////////
221 SGOrCondition::SGOrCondition ()
225 SGOrCondition::~SGOrCondition ()
230 SGOrCondition::test () const
232 int nConditions = _conditions.size();
233 for (int i = 0; i < nConditions; i++) {
234 if (_conditions[i]->test())
241 SGOrCondition::addCondition (SGCondition * condition)
243 _conditions.push_back(condition);
248 ////////////////////////////////////////////////////////////////////////
249 // Implementation of SGComparisonCondition.
250 ////////////////////////////////////////////////////////////////////////
253 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
255 using namespace simgear;
256 switch (left->getType()) {
258 bool v1 = left->getBoolValue();
259 bool v2 = right->getBoolValue();
261 return SGComparisonCondition::LESS_THAN;
263 return SGComparisonCondition::GREATER_THAN;
265 return SGComparisonCondition::EQUALS;
269 int v1 = left->getIntValue();
270 int v2 = right->getIntValue();
272 return SGComparisonCondition::LESS_THAN;
274 return SGComparisonCondition::GREATER_THAN;
276 return SGComparisonCondition::EQUALS;
280 long v1 = left->getLongValue();
281 long v2 = right->getLongValue();
283 return SGComparisonCondition::LESS_THAN;
285 return SGComparisonCondition::GREATER_THAN;
287 return SGComparisonCondition::EQUALS;
291 float v1 = left->getFloatValue();
292 float v2 = right->getFloatValue();
294 return SGComparisonCondition::LESS_THAN;
296 return SGComparisonCondition::GREATER_THAN;
298 return SGComparisonCondition::EQUALS;
301 case props::DOUBLE: {
302 double v1 = left->getDoubleValue();
303 double v2 = right->getDoubleValue();
305 return SGComparisonCondition::LESS_THAN;
307 return SGComparisonCondition::GREATER_THAN;
309 return SGComparisonCondition::EQUALS;
314 case props::UNSPECIFIED: {
315 string v1 = left->getStringValue();
316 string v2 = right->getStringValue();
318 return SGComparisonCondition::LESS_THAN;
320 return SGComparisonCondition::GREATER_THAN;
322 return SGComparisonCondition::EQUALS;
326 throw sg_exception("condition: unrecognized node type in comparison");
333 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
339 SGComparisonCondition::~SGComparisonCondition ()
344 SGComparisonCondition::test () const
346 // Always fail if incompletely specified
347 if (!_left_property || !_right_property)
350 // Get LESS_THAN, EQUALS, or GREATER_THAN
352 _left_property->setDoubleValue(_left_dexp->getValue(NULL));
356 _right_property->setDoubleValue(_right_dexp->getValue(NULL));
359 int cmp = doComparison(_left_property, _right_property);
361 return (cmp == _type);
363 return (cmp != _type);
367 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
368 const char * propname )
370 _left_property = prop_root->getNode(propname, true);
374 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
375 const char * propname )
377 _right_property = prop_root->getNode(propname, true);
381 SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
383 _left_property = new SGPropertyNode(*node);
388 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
390 _right_property = new SGPropertyNode(*node);
394 SGComparisonCondition::setLeftDExpression(SGExpressiond* dexp)
396 _left_property = new SGPropertyNode();
401 SGComparisonCondition::setRightDExpression(SGExpressiond* dexp)
403 _right_property = new SGPropertyNode();
406 ////////////////////////////////////////////////////////////////////////
407 // Read a condition and use it if necessary.
408 ////////////////////////////////////////////////////////////////////////
410 // Forward declaration
411 static SGCondition * readCondition( SGPropertyNode *prop_root,
412 const SGPropertyNode *node );
415 readPropertyCondition( SGPropertyNode *prop_root,
416 const SGPropertyNode *node )
418 return new SGPropertyCondition( prop_root, node->getStringValue() );
422 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
424 int nChildren = node->nChildren();
425 for (int i = 0; i < nChildren; i++) {
426 const SGPropertyNode * child = node->getChild(i);
427 SGCondition * condition = readCondition(prop_root, child);
429 return new SGNotCondition(condition);
431 SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
436 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
438 SGAndCondition * andCondition = new SGAndCondition;
439 int nChildren = node->nChildren();
440 for (int i = 0; i < nChildren; i++) {
441 const SGPropertyNode * child = node->getChild(i);
442 SGCondition * condition = readCondition(prop_root, child);
444 andCondition->addCondition(condition);
450 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
452 SGOrCondition * orCondition = new SGOrCondition;
453 int nChildren = node->nChildren();
454 for (int i = 0; i < nChildren; i++) {
455 const SGPropertyNode * child = node->getChild(i);
456 SGCondition * condition = readCondition(prop_root, child);
458 orCondition->addCondition(condition);
464 readComparison( SGPropertyNode *prop_root,
465 const SGPropertyNode *node,
466 SGComparisonCondition::Type type,
469 SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
470 if (node->nChildren() != 2) {
471 throw sg_exception("condition: comparison without two children");
474 const SGPropertyNode* left = node->getChild(0),
475 *right = node->getChild(1);
476 string leftName(left->getName());
477 if (leftName == "property") {
478 condition->setLeftProperty(prop_root, left->getStringValue());
479 } else if (leftName == "value") {
480 condition->setLeftValue(left);
481 } else if (leftName == "expression") {
482 SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
483 condition->setLeftDExpression(exp);
485 throw sg_exception("Unknown condition comparison left child:" + leftName);
488 string rightName(right->getName());
489 if (rightName == "property") {
490 condition->setRightProperty(prop_root, right->getStringValue());
491 } else if (rightName == "value") {
492 condition->setRightValue(right);
493 } else if (rightName == "expression") {
494 SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
495 condition->setRightDExpression(exp);
497 throw sg_exception("Unknown condition comparison right child:" + rightName);
504 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
506 const string &name = node->getName();
507 if (name == "property")
508 return readPropertyCondition(prop_root, node);
509 else if (name == "not")
510 return readNotCondition(prop_root, node);
511 else if (name == "and")
512 return readAndConditions(prop_root, node);
513 else if (name == "or")
514 return readOrConditions(prop_root, node);
515 else if (name == "less-than")
516 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
518 else if (name == "less-than-equals")
519 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
521 else if (name == "greater-than")
522 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
524 else if (name == "greater-than-equals")
525 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
527 else if (name == "equals")
528 return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
530 else if (name == "not-equals")
531 return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
538 ////////////////////////////////////////////////////////////////////////
539 // Implementation of SGConditional.
540 ////////////////////////////////////////////////////////////////////////
542 SGConditional::SGConditional ()
547 SGConditional::~SGConditional ()
552 SGConditional::setCondition (SGCondition * condition)
554 _condition = condition;
558 SGConditional::test () const
560 return ((_condition == 0) || _condition->test());
565 // The top-level is always an implicit 'and' group
567 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
569 return readAndConditions(prop_root, node);
573 // end of condition.cxx