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>
29 ////////////////////////////////////////////////////////////////////////
30 // Implementation of SGCondition.
31 ////////////////////////////////////////////////////////////////////////
33 SGCondition::SGCondition ()
37 SGCondition::~SGCondition ()
43 ////////////////////////////////////////////////////////////////////////
44 // Implementation of SGPropertyCondition.
45 ////////////////////////////////////////////////////////////////////////
47 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
48 const char *propname )
49 : _node( prop_root->getNode(propname, true) )
53 SGPropertyCondition::~SGPropertyCondition ()
59 ////////////////////////////////////////////////////////////////////////
60 // Implementation of SGNotCondition.
61 ////////////////////////////////////////////////////////////////////////
63 SGNotCondition::SGNotCondition (SGCondition * condition)
64 : _condition(condition)
68 SGNotCondition::~SGNotCondition ()
73 SGNotCondition::test () const
75 return !(_condition->test());
80 ////////////////////////////////////////////////////////////////////////
81 // Implementation of SGAndCondition.
82 ////////////////////////////////////////////////////////////////////////
84 SGAndCondition::SGAndCondition ()
88 SGAndCondition::~SGAndCondition ()
93 SGAndCondition::test () const
95 int nConditions = _conditions.size();
96 for (int i = 0; i < nConditions; i++) {
97 if (!_conditions[i]->test())
104 SGAndCondition::addCondition (SGCondition * condition)
106 _conditions.push_back(condition);
111 ////////////////////////////////////////////////////////////////////////
112 // Implementation of SGOrCondition.
113 ////////////////////////////////////////////////////////////////////////
115 SGOrCondition::SGOrCondition ()
119 SGOrCondition::~SGOrCondition ()
124 SGOrCondition::test () const
126 int nConditions = _conditions.size();
127 for (int i = 0; i < nConditions; i++) {
128 if (_conditions[i]->test())
135 SGOrCondition::addCondition (SGCondition * condition)
137 _conditions.push_back(condition);
142 ////////////////////////////////////////////////////////////////////////
143 // Implementation of SGComparisonCondition.
144 ////////////////////////////////////////////////////////////////////////
147 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
149 using namespace simgear;
150 switch (left->getType()) {
152 bool v1 = left->getBoolValue();
153 bool v2 = right->getBoolValue();
155 return SGComparisonCondition::LESS_THAN;
157 return SGComparisonCondition::GREATER_THAN;
159 return SGComparisonCondition::EQUALS;
163 int v1 = left->getIntValue();
164 int v2 = right->getIntValue();
166 return SGComparisonCondition::LESS_THAN;
168 return SGComparisonCondition::GREATER_THAN;
170 return SGComparisonCondition::EQUALS;
174 long v1 = left->getLongValue();
175 long v2 = right->getLongValue();
177 return SGComparisonCondition::LESS_THAN;
179 return SGComparisonCondition::GREATER_THAN;
181 return SGComparisonCondition::EQUALS;
185 float v1 = left->getFloatValue();
186 float v2 = right->getFloatValue();
188 return SGComparisonCondition::LESS_THAN;
190 return SGComparisonCondition::GREATER_THAN;
192 return SGComparisonCondition::EQUALS;
195 case props::DOUBLE: {
196 double v1 = left->getDoubleValue();
197 double v2 = right->getDoubleValue();
199 return SGComparisonCondition::LESS_THAN;
201 return SGComparisonCondition::GREATER_THAN;
203 return SGComparisonCondition::EQUALS;
208 case props::UNSPECIFIED: {
209 string v1 = left->getStringValue();
210 string v2 = right->getStringValue();
212 return SGComparisonCondition::LESS_THAN;
214 return SGComparisonCondition::GREATER_THAN;
216 return SGComparisonCondition::EQUALS;
220 throw sg_exception("condition: unrecognized node type in comparison");
227 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
236 SGComparisonCondition::~SGComparisonCondition ()
241 SGComparisonCondition::test () const
243 // Always fail if incompletely specified
244 if (_left_property == 0 ||
245 (_right_property == 0 && _right_value == 0))
248 // Get LESS_THAN, EQUALS, or GREATER_THAN
250 doComparison(_left_property,
251 (_right_property != 0 ? _right_property : _right_value));
253 return (cmp == _type);
255 return (cmp != _type);
259 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
260 const char * propname )
262 _left_property = prop_root->getNode(propname, true);
266 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
267 const char * propname )
270 _right_property = prop_root->getNode(propname, true);
274 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
277 _right_value = new SGPropertyNode(*node);
282 ////////////////////////////////////////////////////////////////////////
283 // Read a condition and use it if necessary.
284 ////////////////////////////////////////////////////////////////////////
286 // Forward declaration
287 static SGCondition * readCondition( SGPropertyNode *prop_root,
288 const SGPropertyNode *node );
291 readPropertyCondition( SGPropertyNode *prop_root,
292 const SGPropertyNode *node )
294 return new SGPropertyCondition( prop_root, node->getStringValue() );
298 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
300 int nChildren = node->nChildren();
301 for (int i = 0; i < nChildren; i++) {
302 const SGPropertyNode * child = node->getChild(i);
303 SGCondition * condition = readCondition(prop_root, child);
305 return new SGNotCondition(condition);
307 SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
312 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
314 SGAndCondition * andCondition = new SGAndCondition;
315 int nChildren = node->nChildren();
316 for (int i = 0; i < nChildren; i++) {
317 const SGPropertyNode * child = node->getChild(i);
318 SGCondition * condition = readCondition(prop_root, child);
320 andCondition->addCondition(condition);
326 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
328 SGOrCondition * orCondition = new SGOrCondition;
329 int nChildren = node->nChildren();
330 for (int i = 0; i < nChildren; i++) {
331 const SGPropertyNode * child = node->getChild(i);
332 SGCondition * condition = readCondition(prop_root, child);
334 orCondition->addCondition(condition);
340 readComparison( SGPropertyNode *prop_root,
341 const SGPropertyNode *node,
342 SGComparisonCondition::Type type,
345 SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
346 condition->setLeftProperty(prop_root, node->getStringValue("property[0]"));
347 if (node->hasValue("property[1]"))
348 condition->setRightProperty(prop_root, node->getStringValue("property[1]"));
349 else if (node->hasValue("value"))
350 condition->setRightValue(node->getChild("value", 0));
352 throw sg_exception("condition: comparison without property[1] or value");
358 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
360 const string &name = node->getName();
361 if (name == "property")
362 return readPropertyCondition(prop_root, node);
363 else if (name == "not")
364 return readNotCondition(prop_root, node);
365 else if (name == "and")
366 return readAndConditions(prop_root, node);
367 else if (name == "or")
368 return readOrConditions(prop_root, node);
369 else if (name == "less-than")
370 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
372 else if (name == "less-than-equals")
373 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
375 else if (name == "greater-than")
376 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
378 else if (name == "greater-than-equals")
379 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
381 else if (name == "equals")
382 return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
384 else if (name == "not-equals")
385 return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
392 ////////////////////////////////////////////////////////////////////////
393 // Implementation of SGConditional.
394 ////////////////////////////////////////////////////////////////////////
396 SGConditional::SGConditional ()
401 SGConditional::~SGConditional ()
406 SGConditional::setCondition (SGCondition * condition)
408 _condition = condition;
412 SGConditional::test () const
414 return ((_condition == 0) || _condition->test());
419 // The top-level is always an implicit 'and' group
421 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
423 return readAndConditions(prop_root, node);
427 // end of condition.cxx