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) )
51 FGPropertyCondition::~FGPropertyCondition ()
57 ////////////////////////////////////////////////////////////////////////
58 // Implementation of FGNotCondition.
59 ////////////////////////////////////////////////////////////////////////
61 FGNotCondition::FGNotCondition (FGCondition * condition)
62 : _condition(condition)
66 FGNotCondition::~FGNotCondition ()
72 FGNotCondition::test () const
74 return !(_condition->test());
79 ////////////////////////////////////////////////////////////////////////
80 // Implementation of FGAndCondition.
81 ////////////////////////////////////////////////////////////////////////
83 FGAndCondition::FGAndCondition ()
87 FGAndCondition::~FGAndCondition ()
89 for (unsigned int i = 0; i < _conditions.size(); i++)
90 delete _conditions[i];
94 FGAndCondition::test () const
96 int nConditions = _conditions.size();
97 for (int i = 0; i < nConditions; i++) {
98 if (!_conditions[i]->test())
105 FGAndCondition::addCondition (FGCondition * condition)
107 _conditions.push_back(condition);
112 ////////////////////////////////////////////////////////////////////////
113 // Implementation of FGOrCondition.
114 ////////////////////////////////////////////////////////////////////////
116 FGOrCondition::FGOrCondition ()
120 FGOrCondition::~FGOrCondition ()
122 for (unsigned int i = 0; i < _conditions.size(); i++)
123 delete _conditions[i];
127 FGOrCondition::test () const
129 int nConditions = _conditions.size();
130 for (int i = 0; i < nConditions; i++) {
131 if (_conditions[i]->test())
138 FGOrCondition::addCondition (FGCondition * condition)
140 _conditions.push_back(condition);
145 ////////////////////////////////////////////////////////////////////////
146 // Implementation of FGComparisonCondition.
147 ////////////////////////////////////////////////////////////////////////
150 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
152 switch (left->getType()) {
153 case SGPropertyNode::BOOL: {
154 bool v1 = left->getBoolValue();
155 bool v2 = right->getBoolValue();
157 return FGComparisonCondition::LESS_THAN;
159 return FGComparisonCondition::GREATER_THAN;
161 return FGComparisonCondition::EQUALS;
164 case SGPropertyNode::INT: {
165 int v1 = left->getIntValue();
166 int v2 = right->getIntValue();
168 return FGComparisonCondition::LESS_THAN;
170 return FGComparisonCondition::GREATER_THAN;
172 return FGComparisonCondition::EQUALS;
175 case SGPropertyNode::LONG: {
176 long v1 = left->getLongValue();
177 long v2 = right->getLongValue();
179 return FGComparisonCondition::LESS_THAN;
181 return FGComparisonCondition::GREATER_THAN;
183 return FGComparisonCondition::EQUALS;
186 case SGPropertyNode::FLOAT: {
187 float v1 = left->getFloatValue();
188 float v2 = right->getFloatValue();
190 return FGComparisonCondition::LESS_THAN;
192 return FGComparisonCondition::GREATER_THAN;
194 return FGComparisonCondition::EQUALS;
197 case SGPropertyNode::DOUBLE: {
198 double v1 = left->getDoubleValue();
199 double v2 = right->getDoubleValue();
201 return FGComparisonCondition::LESS_THAN;
203 return FGComparisonCondition::GREATER_THAN;
205 return FGComparisonCondition::EQUALS;
208 case SGPropertyNode::STRING:
209 case SGPropertyNode::NONE:
210 case SGPropertyNode::UNSPECIFIED: {
211 string v1 = left->getStringValue();
212 string v2 = right->getStringValue();
214 return FGComparisonCondition::LESS_THAN;
216 return FGComparisonCondition::GREATER_THAN;
218 return FGComparisonCondition::EQUALS;
222 throw sg_exception("Unrecognized node type");
227 FGComparisonCondition::FGComparisonCondition (Type type, bool reverse)
236 FGComparisonCondition::~FGComparisonCondition ()
242 FGComparisonCondition::test () const
244 // Always fail if incompletely specified
245 if (_left_property == 0 ||
246 (_right_property == 0 && _right_value == 0))
249 // Get LESS_THAN, EQUALS, or GREATER_THAN
251 doComparison(_left_property,
252 (_right_property != 0 ? _right_property : _right_value));
254 return (cmp == _type);
256 return (cmp != _type);
260 FGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
261 const char * propname )
263 _left_property = prop_root->getNode(propname, true);
267 FGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
268 const char * propname )
272 _right_property = prop_root->getNode(propname, true);
276 FGComparisonCondition::setRightValue (const SGPropertyNode *node)
280 _right_value = new SGPropertyNode(*node);
285 ////////////////////////////////////////////////////////////////////////
286 // Read a condition and use it if necessary.
287 ////////////////////////////////////////////////////////////////////////
289 // Forward declaration
290 static FGCondition * readCondition( SGPropertyNode *prop_root,
291 const SGPropertyNode *node );
294 readPropertyCondition( SGPropertyNode *prop_root,
295 const SGPropertyNode *node )
297 return new FGPropertyCondition( prop_root, node->getStringValue() );
301 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
303 int nChildren = node->nChildren();
304 for (int i = 0; i < nChildren; i++) {
305 const SGPropertyNode * child = node->getChild(i);
306 FGCondition * condition = readCondition(prop_root, child);
308 return new FGNotCondition(condition);
310 SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
315 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
317 FGAndCondition * andCondition = new FGAndCondition;
318 int nChildren = node->nChildren();
319 for (int i = 0; i < nChildren; i++) {
320 const SGPropertyNode * child = node->getChild(i);
321 FGCondition * condition = readCondition(prop_root, child);
323 andCondition->addCondition(condition);
329 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
331 FGOrCondition * orCondition = new FGOrCondition;
332 int nChildren = node->nChildren();
333 for (int i = 0; i < nChildren; i++) {
334 const SGPropertyNode * child = node->getChild(i);
335 FGCondition * condition = readCondition(prop_root, child);
337 orCondition->addCondition(condition);
343 readComparison( SGPropertyNode *prop_root,
344 const SGPropertyNode *node,
345 FGComparisonCondition::Type type,
348 FGComparisonCondition * condition = new FGComparisonCondition(type, reverse);
349 condition->setLeftProperty(prop_root, node->getStringValue("property[0]"));
350 if (node->hasValue("property[1]"))
351 condition->setRightProperty(prop_root, node->getStringValue("property[1]"));
353 condition->setRightValue(node->getChild("value", 0));
359 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
361 const string &name = node->getName();
362 if (name == "property")
363 return readPropertyCondition(prop_root, node);
364 else if (name == "not")
365 return readNotCondition(prop_root, node);
366 else if (name == "and")
367 return readAndConditions(prop_root, node);
368 else if (name == "or")
369 return readOrConditions(prop_root, node);
370 else if (name == "less-than")
371 return readComparison(prop_root, node, FGComparisonCondition::LESS_THAN,
373 else if (name == "less-than-equals")
374 return readComparison(prop_root, node, FGComparisonCondition::GREATER_THAN,
376 else if (name == "greater-than")
377 return readComparison(prop_root, node, FGComparisonCondition::GREATER_THAN,
379 else if (name == "greater-than-equals")
380 return readComparison(prop_root, node, FGComparisonCondition::LESS_THAN,
382 else if (name == "equals")
383 return readComparison(prop_root, node, FGComparisonCondition::EQUALS,
385 else if (name == "not-equals")
386 return readComparison(prop_root, node, FGComparisonCondition::EQUALS, true);
393 ////////////////////////////////////////////////////////////////////////
394 // Implementation of FGConditional.
395 ////////////////////////////////////////////////////////////////////////
397 FGConditional::FGConditional ()
402 FGConditional::~FGConditional ()
408 FGConditional::setCondition (FGCondition * condition)
411 _condition = condition;
415 FGConditional::test () const
417 return ((_condition == 0) || _condition->test());
422 // The top-level is always an implicit 'and' group
424 fgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
426 return readAndConditions(prop_root, node);
430 // end of fg_props.cxx