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/compiler.h>
14 // #include STL_IOSTREAM
16 #include <simgear/structure/exception.hxx>
19 #include "condition.hxx"
21 SG_USING_STD(istream);
22 SG_USING_STD(ostream);
27 ////////////////////////////////////////////////////////////////////////
28 // Implementation of SGCondition.
29 ////////////////////////////////////////////////////////////////////////
31 SGCondition::SGCondition ()
35 SGCondition::~SGCondition ()
41 ////////////////////////////////////////////////////////////////////////
42 // Implementation of SGPropertyCondition.
43 ////////////////////////////////////////////////////////////////////////
45 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
46 const char *propname )
47 : _node( prop_root->getNode(propname, true) )
51 SGPropertyCondition::~SGPropertyCondition ()
57 ////////////////////////////////////////////////////////////////////////
58 // Implementation of SGNotCondition.
59 ////////////////////////////////////////////////////////////////////////
61 SGNotCondition::SGNotCondition (SGCondition * condition)
62 : _condition(condition)
66 SGNotCondition::~SGNotCondition ()
71 SGNotCondition::test () const
73 return !(_condition->test());
78 ////////////////////////////////////////////////////////////////////////
79 // Implementation of SGAndCondition.
80 ////////////////////////////////////////////////////////////////////////
82 SGAndCondition::SGAndCondition ()
86 SGAndCondition::~SGAndCondition ()
91 SGAndCondition::test () const
93 int nConditions = _conditions.size();
94 for (int i = 0; i < nConditions; i++) {
95 if (!_conditions[i]->test())
102 SGAndCondition::addCondition (SGCondition * condition)
104 _conditions.push_back(condition);
109 ////////////////////////////////////////////////////////////////////////
110 // Implementation of SGOrCondition.
111 ////////////////////////////////////////////////////////////////////////
113 SGOrCondition::SGOrCondition ()
117 SGOrCondition::~SGOrCondition ()
122 SGOrCondition::test () const
124 int nConditions = _conditions.size();
125 for (int i = 0; i < nConditions; i++) {
126 if (_conditions[i]->test())
133 SGOrCondition::addCondition (SGCondition * condition)
135 _conditions.push_back(condition);
140 ////////////////////////////////////////////////////////////////////////
141 // Implementation of SGComparisonCondition.
142 ////////////////////////////////////////////////////////////////////////
145 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
147 switch (left->getType()) {
148 case SGPropertyNode::BOOL: {
149 bool v1 = left->getBoolValue();
150 bool v2 = right->getBoolValue();
152 return SGComparisonCondition::LESS_THAN;
154 return SGComparisonCondition::GREATER_THAN;
156 return SGComparisonCondition::EQUALS;
159 case SGPropertyNode::INT: {
160 int v1 = left->getIntValue();
161 int v2 = right->getIntValue();
163 return SGComparisonCondition::LESS_THAN;
165 return SGComparisonCondition::GREATER_THAN;
167 return SGComparisonCondition::EQUALS;
170 case SGPropertyNode::LONG: {
171 long v1 = left->getLongValue();
172 long v2 = right->getLongValue();
174 return SGComparisonCondition::LESS_THAN;
176 return SGComparisonCondition::GREATER_THAN;
178 return SGComparisonCondition::EQUALS;
181 case SGPropertyNode::FLOAT: {
182 float v1 = left->getFloatValue();
183 float v2 = right->getFloatValue();
185 return SGComparisonCondition::LESS_THAN;
187 return SGComparisonCondition::GREATER_THAN;
189 return SGComparisonCondition::EQUALS;
192 case SGPropertyNode::DOUBLE: {
193 double v1 = left->getDoubleValue();
194 double v2 = right->getDoubleValue();
196 return SGComparisonCondition::LESS_THAN;
198 return SGComparisonCondition::GREATER_THAN;
200 return SGComparisonCondition::EQUALS;
203 case SGPropertyNode::STRING:
204 case SGPropertyNode::NONE:
205 case SGPropertyNode::UNSPECIFIED: {
206 string v1 = left->getStringValue();
207 string v2 = right->getStringValue();
209 return SGComparisonCondition::LESS_THAN;
211 return SGComparisonCondition::GREATER_THAN;
213 return SGComparisonCondition::EQUALS;
217 throw sg_exception("Unrecognized node type");
222 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
231 SGComparisonCondition::~SGComparisonCondition ()
236 SGComparisonCondition::test () const
238 // Always fail if incompletely specified
239 if (_left_property == 0 ||
240 (_right_property == 0 && _right_value == 0))
243 // Get LESS_THAN, EQUALS, or GREATER_THAN
245 doComparison(_left_property,
246 (_right_property != 0 ? _right_property : _right_value));
248 return (cmp == _type);
250 return (cmp != _type);
254 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
255 const char * propname )
257 _left_property = prop_root->getNode(propname, true);
261 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
262 const char * propname )
265 _right_property = prop_root->getNode(propname, true);
269 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
272 _right_value = new SGPropertyNode(*node);
277 ////////////////////////////////////////////////////////////////////////
278 // Read a condition and use it if necessary.
279 ////////////////////////////////////////////////////////////////////////
281 // Forward declaration
282 static SGCondition * readCondition( SGPropertyNode *prop_root,
283 const SGPropertyNode *node );
286 readPropertyCondition( SGPropertyNode *prop_root,
287 const SGPropertyNode *node )
289 return new SGPropertyCondition( prop_root, node->getStringValue() );
293 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
295 int nChildren = node->nChildren();
296 for (int i = 0; i < nChildren; i++) {
297 const SGPropertyNode * child = node->getChild(i);
298 SGCondition * condition = readCondition(prop_root, child);
300 return new SGNotCondition(condition);
302 SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
307 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
309 SGAndCondition * andCondition = new SGAndCondition;
310 int nChildren = node->nChildren();
311 for (int i = 0; i < nChildren; i++) {
312 const SGPropertyNode * child = node->getChild(i);
313 SGCondition * condition = readCondition(prop_root, child);
315 andCondition->addCondition(condition);
321 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
323 SGOrCondition * orCondition = new SGOrCondition;
324 int nChildren = node->nChildren();
325 for (int i = 0; i < nChildren; i++) {
326 const SGPropertyNode * child = node->getChild(i);
327 SGCondition * condition = readCondition(prop_root, child);
329 orCondition->addCondition(condition);
335 readComparison( SGPropertyNode *prop_root,
336 const SGPropertyNode *node,
337 SGComparisonCondition::Type type,
340 SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
341 condition->setLeftProperty(prop_root, node->getStringValue("property[0]"));
342 if (node->hasValue("property[1]"))
343 condition->setRightProperty(prop_root, node->getStringValue("property[1]"));
345 condition->setRightValue(node->getChild("value", 0));
351 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
353 const string &name = node->getName();
354 if (name == "property")
355 return readPropertyCondition(prop_root, node);
356 else if (name == "not")
357 return readNotCondition(prop_root, node);
358 else if (name == "and")
359 return readAndConditions(prop_root, node);
360 else if (name == "or")
361 return readOrConditions(prop_root, node);
362 else if (name == "less-than")
363 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
365 else if (name == "less-than-equals")
366 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
368 else if (name == "greater-than")
369 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
371 else if (name == "greater-than-equals")
372 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
374 else if (name == "equals")
375 return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
377 else if (name == "not-equals")
378 return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
385 ////////////////////////////////////////////////////////////////////////
386 // Implementation of SGConditional.
387 ////////////////////////////////////////////////////////////////////////
389 SGConditional::SGConditional ()
394 SGConditional::~SGConditional ()
399 SGConditional::setCondition (SGCondition * condition)
401 _condition = condition;
405 SGConditional::test () const
407 return ((_condition == 0) || _condition->test());
412 // The top-level is always an implicit 'and' group
414 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
416 return readAndConditions(prop_root, node);
420 // end of condition.cxx