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(); }
39 SGConstPropertyNode_ptr _node;
43 * Condition with constant value
46 class SGConstantCondition : public SGCondition
49 SGConstantCondition (bool v) : _value(v) { ; }
50 virtual bool test () const { return _value; }
56 * Condition for a 'not' operator.
58 * This condition is true only if the child condition is false.
60 class SGNotCondition : public SGCondition
63 SGNotCondition (SGCondition * condition);
64 virtual ~SGNotCondition ();
65 virtual bool test () const;
67 SGSharedPtr<SGCondition> _condition;
72 * Condition for an 'and' group.
74 * This condition is true only if all of the conditions
75 * in the group are true.
77 class SGAndCondition : public SGCondition
81 virtual ~SGAndCondition ();
82 virtual bool test () const;
83 // transfer pointer ownership
84 virtual void addCondition (SGCondition * condition);
86 std::vector<SGSharedPtr<SGCondition> > _conditions;
91 * Condition for an 'or' group.
93 * This condition is true if at least one of the conditions in the
96 class SGOrCondition : public SGCondition
100 virtual ~SGOrCondition ();
101 virtual bool test () const;
102 // transfer pointer ownership
103 virtual void addCondition (SGCondition * condition);
105 std::vector<SGSharedPtr<SGCondition> > _conditions;
110 * Abstract base class for property comparison conditions.
112 class SGComparisonCondition : public SGCondition
120 SGComparisonCondition (Type type, bool reverse = false);
121 virtual ~SGComparisonCondition ();
122 virtual bool test () const;
123 virtual void setLeftProperty( SGPropertyNode *prop_root,
124 const char * propname );
125 virtual void setRightProperty( SGPropertyNode *prop_root,
126 const char * propname );
127 virtual void setPrecisionProperty( 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);
132 virtual void setPrecisionValue (const SGPropertyNode * value);
134 void setLeftDExpression(SGExpressiond* dexp);
135 void setRightDExpression(SGExpressiond* dexp);
136 void setPrecisionDExpression(SGExpressiond* dexp);
141 SGPropertyNode_ptr _left_property;
142 SGPropertyNode_ptr _right_property;
143 SGPropertyNode_ptr _precision_property;
145 SGSharedPtr<SGExpressiond> _left_dexp;
146 SGSharedPtr<SGExpressiond> _right_dexp;
147 SGSharedPtr<SGExpressiond> _precision_dexp;
151 ////////////////////////////////////////////////////////////////////////
152 // Implementation of SGCondition.
153 ////////////////////////////////////////////////////////////////////////
155 SGCondition::SGCondition ()
159 SGCondition::~SGCondition ()
164 ////////////////////////////////////////////////////////////////////////
165 // Implementation of SGPropertyCondition.
166 ////////////////////////////////////////////////////////////////////////
168 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
169 const char *propname )
170 : _node( prop_root->getNode(propname, true) )
174 SGPropertyCondition::~SGPropertyCondition ()
179 ////////////////////////////////////////////////////////////////////////
180 // Implementation of SGNotCondition.
181 ////////////////////////////////////////////////////////////////////////
183 SGNotCondition::SGNotCondition (SGCondition * condition)
184 : _condition(condition)
188 SGNotCondition::~SGNotCondition ()
193 SGNotCondition::test () const
195 return !(_condition->test());
199 ////////////////////////////////////////////////////////////////////////
200 // Implementation of SGAndCondition.
201 ////////////////////////////////////////////////////////////////////////
203 SGAndCondition::SGAndCondition ()
207 SGAndCondition::~SGAndCondition ()
212 SGAndCondition::test () const
214 for( size_t i = 0; i < _conditions.size(); i++ )
216 if (!_conditions[i]->test())
223 SGAndCondition::addCondition (SGCondition * condition)
225 _conditions.push_back(condition);
229 ////////////////////////////////////////////////////////////////////////
230 // Implementation of SGOrCondition.
231 ////////////////////////////////////////////////////////////////////////
233 SGOrCondition::SGOrCondition ()
237 SGOrCondition::~SGOrCondition ()
242 SGOrCondition::test () const
244 for( size_t i = 0; i < _conditions.size(); i++ )
246 if (_conditions[i]->test())
253 SGOrCondition::addCondition (SGCondition * condition)
255 _conditions.push_back(condition);
259 ////////////////////////////////////////////////////////////////////////
260 // Implementation of SGComparisonCondition.
261 ////////////////////////////////////////////////////////////////////////
264 static int doComp( T v1, T v2, T e )
268 return SGComparisonCondition::LESS_THAN;
270 return SGComparisonCondition::GREATER_THAN;
272 return SGComparisonCondition::EQUALS;
276 doComparison (const SGPropertyNode * left, const SGPropertyNode * right, const SGPropertyNode * precision )
278 using namespace simgear;
279 switch (left->getType()) {
281 bool v1 = left->getBoolValue();
282 bool v2 = right->getBoolValue();
284 return SGComparisonCondition::LESS_THAN;
286 return SGComparisonCondition::GREATER_THAN;
288 return SGComparisonCondition::EQUALS;
292 return doComp<int>(left->getIntValue(), right->getIntValue(),
293 precision ? std::abs(precision->getIntValue()/2) : 0 );
296 return doComp<long>(left->getLongValue(), right->getLongValue(),
297 precision ? std::abs(precision->getLongValue()/2L) : 0L );
300 return doComp<float>(left->getFloatValue(), right->getFloatValue(),
301 precision ? std::fabs(precision->getFloatValue()/2.0f) : 0.0f );
304 return doComp<double>(left->getDoubleValue(), right->getDoubleValue(),
305 precision ? std::fabs(precision->getDoubleValue()/2.0) : 0.0 );
309 case props::UNSPECIFIED: {
310 size_t l = precision ? precision->getLongValue() : string::npos;
311 string v1 = string(left->getStringValue()).substr(0,l);
312 string v2 = string(right->getStringValue()).substr(0,l);
314 return SGComparisonCondition::LESS_THAN;
316 return SGComparisonCondition::GREATER_THAN;
318 return SGComparisonCondition::EQUALS;
322 throw sg_exception("condition: unrecognized node type in comparison");
329 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
335 SGComparisonCondition::~SGComparisonCondition ()
340 SGComparisonCondition::test () const
342 // Always fail if incompletely specified
343 if (!_left_property || !_right_property)
346 // Get LESS_THAN, EQUALS, or GREATER_THAN
348 _left_property->setDoubleValue(_left_dexp->getValue(NULL));
352 _right_property->setDoubleValue(_right_dexp->getValue(NULL));
355 if (_precision_dexp) {
356 _precision_property->setDoubleValue(_precision_dexp->getValue(NULL));
359 int cmp = doComparison(_left_property, _right_property, _precision_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::setPrecisionProperty( SGPropertyNode *prop_root,
382 const char * propname )
384 _precision_property = prop_root->getNode(propname, true);
388 SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
390 _left_property = new SGPropertyNode(*node);
394 SGComparisonCondition::setPrecisionValue (const SGPropertyNode *node)
396 _precision_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();
420 SGComparisonCondition::setPrecisionDExpression(SGExpressiond* dexp)
422 _precision_property = new SGPropertyNode();
423 _precision_dexp = dexp;
424 }////////////////////////////////////////////////////////////////////////
425 // Read a condition and use it if necessary.
426 ////////////////////////////////////////////////////////////////////////
428 // Forward declaration
429 static SGCondition * readCondition( SGPropertyNode *prop_root,
430 const SGPropertyNode *node );
433 readPropertyCondition( SGPropertyNode *prop_root,
434 const SGPropertyNode *node )
436 return new SGPropertyCondition( prop_root, node->getStringValue() );
440 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
442 int nChildren = node->nChildren();
443 for (int i = 0; i < nChildren; i++) {
444 const SGPropertyNode * child = node->getChild(i);
445 SGCondition * condition = readCondition(prop_root, child);
447 return new SGNotCondition(condition);
449 SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
454 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
456 SGAndCondition * andCondition = new SGAndCondition;
457 int nChildren = node->nChildren();
458 for (int i = 0; i < nChildren; i++) {
459 const SGPropertyNode * child = node->getChild(i);
460 SGCondition * condition = readCondition(prop_root, child);
462 andCondition->addCondition(condition);
468 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
470 SGOrCondition * orCondition = new SGOrCondition;
471 int nChildren = node->nChildren();
472 for (int i = 0; i < nChildren; i++) {
473 const SGPropertyNode * child = node->getChild(i);
474 SGCondition * condition = readCondition(prop_root, child);
476 orCondition->addCondition(condition);
482 readComparison( SGPropertyNode *prop_root,
483 const SGPropertyNode *node,
484 SGComparisonCondition::Type type,
487 SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
488 if (node->nChildren() < 2 || node->nChildren() > 3 ) {
489 throw sg_exception("condition: comparison without two or three children");
492 const SGPropertyNode* left = node->getChild(0),
493 *right = node->getChild(1);
496 string leftName(left->getName());
497 if (leftName == "property") {
498 condition->setLeftProperty(prop_root, left->getStringValue());
499 } else if (leftName == "value") {
500 condition->setLeftValue(left);
501 } else if (leftName == "expression") {
502 SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
503 condition->setLeftDExpression(exp);
505 throw sg_exception("Unknown condition comparison left child:" + leftName);
510 string rightName(right->getName());
511 if (rightName == "property") {
512 condition->setRightProperty(prop_root, right->getStringValue());
513 } else if (rightName == "value") {
514 condition->setRightValue(right);
515 } else if (rightName == "expression") {
516 SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
517 condition->setRightDExpression(exp);
519 throw sg_exception("Unknown condition comparison right child:" + rightName);
523 if( node->nChildren() == 3 ) {
524 const SGPropertyNode *n = node->getChild(2);
525 string name(n->getName());
526 if (name == "precision-property") {
527 condition->setPrecisionProperty(prop_root, n->getStringValue());
528 } else if (name == "precision-value") {
529 condition->setPrecisionValue(n);
530 } else if (name == "precision-expression") {
531 SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
532 condition->setPrecisionDExpression(exp);
534 throw sg_exception("Unknown condition comparison precision child:" + name );
542 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
544 const string &name = node->getName();
545 if (name == "property")
546 return readPropertyCondition(prop_root, node);
547 else if (name == "not")
548 return readNotCondition(prop_root, node);
549 else if (name == "and")
550 return readAndConditions(prop_root, node);
551 else if (name == "or")
552 return readOrConditions(prop_root, node);
553 else if (name == "less-than")
554 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
556 else if (name == "less-than-equals")
557 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
559 else if (name == "greater-than")
560 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
562 else if (name == "greater-than-equals")
563 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
565 else if (name == "equals")
566 return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
568 else if (name == "not-equals")
569 return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
570 else if (name == "false")
571 return new SGConstantCondition(false);
572 else if (name == "true")
573 return new SGConstantCondition(true);
579 ////////////////////////////////////////////////////////////////////////
580 // Implementation of SGConditional.
581 ////////////////////////////////////////////////////////////////////////
583 SGConditional::SGConditional ()
588 SGConditional::~SGConditional ()
593 SGConditional::setCondition (SGCondition * condition)
595 _condition = condition;
599 SGConditional::test () const
601 return ((_condition == 0) || _condition->test());
605 // The top-level is always an implicit 'and' group
607 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
609 return readAndConditions(prop_root, node);
613 // end of condition.cxx