1 // condition.hxx - Declarations and inline methods for property conditions.
2 // Written by David Megginson, started 2000.
3 // CLO May 2003 - Split out condition specific code.
5 // This file is in the Public Domain, and comes with no warranty.
10 # include <simgear/compiler.h>
13 // #include STL_IOSTREAM
15 #include <simgear/misc/exception.hxx>
19 #include "condition.hxx"
21 SG_USING_STD(istream);
22 SG_USING_STD(ostream);
27 ////////////////////////////////////////////////////////////////////////
28 // Implementation of FGCondition.
29 ////////////////////////////////////////////////////////////////////////
31 FGCondition::FGCondition ()
35 FGCondition::~FGCondition ()
41 ////////////////////////////////////////////////////////////////////////
42 // Implementation of FGPropertyCondition.
43 ////////////////////////////////////////////////////////////////////////
45 FGPropertyCondition::FGPropertyCondition ( SGPropertyNode *prop_root,
46 const char *propname )
47 : _node( prop_root->getNode(propname, true) )
49 cout << "FGPropertyCondition::FGPropertyCondition()" << endl;
50 cout << " prop_root = " << prop_root << endl;
51 cout << " propname = " << propname << endl;
52 _node = prop_root->getNode(propname, true);
53 cout << " _node = " << _node << endl;
56 FGPropertyCondition::~FGPropertyCondition ()
62 ////////////////////////////////////////////////////////////////////////
63 // Implementation of FGNotCondition.
64 ////////////////////////////////////////////////////////////////////////
66 FGNotCondition::FGNotCondition (FGCondition * condition)
67 : _condition(condition)
71 FGNotCondition::~FGNotCondition ()
77 FGNotCondition::test () const
79 return !(_condition->test());
84 ////////////////////////////////////////////////////////////////////////
85 // Implementation of FGAndCondition.
86 ////////////////////////////////////////////////////////////////////////
88 FGAndCondition::FGAndCondition ()
92 FGAndCondition::~FGAndCondition ()
94 for (unsigned int i = 0; i < _conditions.size(); i++)
95 delete _conditions[i];
99 FGAndCondition::test () const
101 int nConditions = _conditions.size();
102 for (int i = 0; i < nConditions; i++) {
103 if (!_conditions[i]->test())
110 FGAndCondition::addCondition (FGCondition * condition)
112 _conditions.push_back(condition);
117 ////////////////////////////////////////////////////////////////////////
118 // Implementation of FGOrCondition.
119 ////////////////////////////////////////////////////////////////////////
121 FGOrCondition::FGOrCondition ()
125 FGOrCondition::~FGOrCondition ()
127 for (unsigned int i = 0; i < _conditions.size(); i++)
128 delete _conditions[i];
132 FGOrCondition::test () const
134 int nConditions = _conditions.size();
135 for (int i = 0; i < nConditions; i++) {
136 if (_conditions[i]->test())
143 FGOrCondition::addCondition (FGCondition * condition)
145 _conditions.push_back(condition);
150 ////////////////////////////////////////////////////////////////////////
151 // Implementation of FGComparisonCondition.
152 ////////////////////////////////////////////////////////////////////////
155 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
157 switch (left->getType()) {
158 case SGPropertyNode::BOOL: {
159 bool v1 = left->getBoolValue();
160 bool v2 = right->getBoolValue();
162 return FGComparisonCondition::LESS_THAN;
164 return FGComparisonCondition::GREATER_THAN;
166 return FGComparisonCondition::EQUALS;
169 case SGPropertyNode::INT: {
170 int v1 = left->getIntValue();
171 int v2 = right->getIntValue();
173 return FGComparisonCondition::LESS_THAN;
175 return FGComparisonCondition::GREATER_THAN;
177 return FGComparisonCondition::EQUALS;
180 case SGPropertyNode::LONG: {
181 long v1 = left->getLongValue();
182 long v2 = right->getLongValue();
184 return FGComparisonCondition::LESS_THAN;
186 return FGComparisonCondition::GREATER_THAN;
188 return FGComparisonCondition::EQUALS;
191 case SGPropertyNode::FLOAT: {
192 float v1 = left->getFloatValue();
193 float v2 = right->getFloatValue();
195 return FGComparisonCondition::LESS_THAN;
197 return FGComparisonCondition::GREATER_THAN;
199 return FGComparisonCondition::EQUALS;
202 case SGPropertyNode::DOUBLE: {
203 double v1 = left->getDoubleValue();
204 double v2 = right->getDoubleValue();
206 return FGComparisonCondition::LESS_THAN;
208 return FGComparisonCondition::GREATER_THAN;
210 return FGComparisonCondition::EQUALS;
213 case SGPropertyNode::STRING:
214 case SGPropertyNode::NONE:
215 case SGPropertyNode::UNSPECIFIED: {
216 string v1 = left->getStringValue();
217 string v2 = right->getStringValue();
219 return FGComparisonCondition::LESS_THAN;
221 return FGComparisonCondition::GREATER_THAN;
223 return FGComparisonCondition::EQUALS;
227 throw sg_exception("Unrecognized node type");
232 FGComparisonCondition::FGComparisonCondition (Type type, bool reverse)
241 FGComparisonCondition::~FGComparisonCondition ()
247 FGComparisonCondition::test () const
249 // Always fail if incompletely specified
250 if (_left_property == 0 ||
251 (_right_property == 0 && _right_value == 0))
254 // Get LESS_THAN, EQUALS, or GREATER_THAN
256 doComparison(_left_property,
257 (_right_property != 0 ? _right_property : _right_value));
259 return (cmp == _type);
261 return (cmp != _type);
265 FGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
266 const char * propname )
268 _left_property = prop_root->getNode(propname, true);
272 FGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
273 const char * propname )
277 _right_property = prop_root->getNode(propname, true);
281 FGComparisonCondition::setRightValue (const SGPropertyNode *node)
285 _right_value = new SGPropertyNode(*node);
290 ////////////////////////////////////////////////////////////////////////
291 // Read a condition and use it if necessary.
292 ////////////////////////////////////////////////////////////////////////
294 // Forward declaration
295 static FGCondition * readCondition( SGPropertyNode *prop_root,
296 const SGPropertyNode *node );
299 readPropertyCondition( SGPropertyNode *prop_root,
300 const SGPropertyNode *node )
302 return new FGPropertyCondition( prop_root, node->getStringValue() );
306 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
308 int nChildren = node->nChildren();
309 for (int i = 0; i < nChildren; i++) {
310 const SGPropertyNode * child = node->getChild(i);
311 FGCondition * condition = readCondition(prop_root, child);
313 return new FGNotCondition(condition);
315 SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
320 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
322 FGAndCondition * andCondition = new FGAndCondition;
323 int nChildren = node->nChildren();
324 for (int i = 0; i < nChildren; i++) {
325 const SGPropertyNode * child = node->getChild(i);
326 FGCondition * condition = readCondition(prop_root, child);
328 andCondition->addCondition(condition);
334 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
336 FGOrCondition * orCondition = new FGOrCondition;
337 int nChildren = node->nChildren();
338 for (int i = 0; i < nChildren; i++) {
339 const SGPropertyNode * child = node->getChild(i);
340 FGCondition * condition = readCondition(prop_root, child);
342 orCondition->addCondition(condition);
348 readComparison( SGPropertyNode *prop_root,
349 const SGPropertyNode *node,
350 FGComparisonCondition::Type type,
353 FGComparisonCondition * condition = new FGComparisonCondition(type, reverse);
354 condition->setLeftProperty(prop_root, node->getStringValue("property[0]"));
355 if (node->hasValue("property[1]"))
356 condition->setRightProperty(prop_root, node->getStringValue("property[1]"));
358 condition->setRightValue(node->getChild("value", 0));
364 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
366 const string &name = node->getName();
367 if (name == "property")
368 return readPropertyCondition(prop_root, node);
369 else if (name == "not")
370 return readNotCondition(prop_root, node);
371 else if (name == "and")
372 return readAndConditions(prop_root, node);
373 else if (name == "or")
374 return readOrConditions(prop_root, node);
375 else if (name == "less-than")
376 return readComparison(prop_root, node, FGComparisonCondition::LESS_THAN,
378 else if (name == "less-than-equals")
379 return readComparison(prop_root, node, FGComparisonCondition::GREATER_THAN,
381 else if (name == "greater-than")
382 return readComparison(prop_root, node, FGComparisonCondition::GREATER_THAN,
384 else if (name == "greater-than-equals")
385 return readComparison(prop_root, node, FGComparisonCondition::LESS_THAN,
387 else if (name == "equals")
388 return readComparison(prop_root, node, FGComparisonCondition::EQUALS,
390 else if (name == "not-equals")
391 return readComparison(prop_root, node, FGComparisonCondition::EQUALS, true);
398 ////////////////////////////////////////////////////////////////////////
399 // Implementation of FGConditional.
400 ////////////////////////////////////////////////////////////////////////
402 FGConditional::FGConditional ()
407 FGConditional::~FGConditional ()
413 FGConditional::setCondition (FGCondition * condition)
416 _condition = condition;
420 FGConditional::test () const
422 return ((_condition == 0) || _condition->test());
427 // The top-level is always an implicit 'and' group
429 fgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
431 return readAndConditions(prop_root, node);
435 // end of fg_props.cxx