]> git.mxchange.org Git - simgear.git/blob - simgear/props/condition.cxx
Fix a warning from GCC - 'ALIAS' was unhandled in the switch stmt.
[simgear.git] / simgear / props / condition.cxx
1 // condition.cxx - Declarations and inline methods for property conditions.
2 //
3 // Written by David Megginson, started 2000.
4 // CLO May 2003 - Split out condition specific code.
5 //
6 // This file is in the Public Domain, and comes with no warranty.
7 //
8 // $Id$
9
10 #ifdef HAVE_CONFIG_H
11 #  include <simgear/compiler.h>
12 #endif
13
14 // #include <iostream>
15
16 #include <simgear/structure/exception.hxx>
17
18 #include "props.hxx"
19 #include "condition.hxx"
20
21 using std::istream;
22 using std::ostream;
23
24
25
26 \f
27 ////////////////////////////////////////////////////////////////////////
28 // Implementation of SGCondition.
29 ////////////////////////////////////////////////////////////////////////
30
31 SGCondition::SGCondition ()
32 {
33 }
34
35 SGCondition::~SGCondition ()
36 {
37 }
38
39
40 \f
41 ////////////////////////////////////////////////////////////////////////
42 // Implementation of SGPropertyCondition.
43 ////////////////////////////////////////////////////////////////////////
44
45 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
46                                            const char *propname )
47     : _node( prop_root->getNode(propname, true) )
48 {
49 }
50
51 SGPropertyCondition::~SGPropertyCondition ()
52 {
53 }
54
55
56 \f
57 ////////////////////////////////////////////////////////////////////////
58 // Implementation of SGNotCondition.
59 ////////////////////////////////////////////////////////////////////////
60
61 SGNotCondition::SGNotCondition (SGCondition * condition)
62   : _condition(condition)
63 {
64 }
65
66 SGNotCondition::~SGNotCondition ()
67 {
68 }
69
70 bool
71 SGNotCondition::test () const
72 {
73   return !(_condition->test());
74 }
75
76
77 \f
78 ////////////////////////////////////////////////////////////////////////
79 // Implementation of SGAndCondition.
80 ////////////////////////////////////////////////////////////////////////
81
82 SGAndCondition::SGAndCondition ()
83 {
84 }
85
86 SGAndCondition::~SGAndCondition ()
87 {
88 }
89
90 bool
91 SGAndCondition::test () const
92 {
93   int nConditions = _conditions.size();
94   for (int i = 0; i < nConditions; i++) {
95     if (!_conditions[i]->test())
96       return false;
97   }
98   return true;
99 }
100
101 void
102 SGAndCondition::addCondition (SGCondition * condition)
103 {
104   _conditions.push_back(condition);
105 }
106
107
108 \f
109 ////////////////////////////////////////////////////////////////////////
110 // Implementation of SGOrCondition.
111 ////////////////////////////////////////////////////////////////////////
112
113 SGOrCondition::SGOrCondition ()
114 {
115 }
116
117 SGOrCondition::~SGOrCondition ()
118 {
119 }
120
121 bool
122 SGOrCondition::test () const
123 {
124   int nConditions = _conditions.size();
125   for (int i = 0; i < nConditions; i++) {
126     if (_conditions[i]->test())
127       return true;
128   }
129   return false;
130 }
131
132 void
133 SGOrCondition::addCondition (SGCondition * condition)
134 {
135   _conditions.push_back(condition);
136 }
137
138
139 \f
140 ////////////////////////////////////////////////////////////////////////
141 // Implementation of SGComparisonCondition.
142 ////////////////////////////////////////////////////////////////////////
143
144 static int
145 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
146 {
147   switch (left->getType()) {
148   case SGPropertyNode::BOOL: {
149     bool v1 = left->getBoolValue();
150     bool v2 = right->getBoolValue();
151     if (v1 < v2)
152       return SGComparisonCondition::LESS_THAN;
153     else if (v1 > v2)
154       return SGComparisonCondition::GREATER_THAN;
155     else
156       return SGComparisonCondition::EQUALS;
157     break;
158   }
159   case SGPropertyNode::INT: {
160     int v1 = left->getIntValue();
161     int v2 = right->getIntValue();
162     if (v1 < v2)
163       return SGComparisonCondition::LESS_THAN;
164     else if (v1 > v2)
165       return SGComparisonCondition::GREATER_THAN;
166     else
167       return SGComparisonCondition::EQUALS;
168     break;
169   }
170   case SGPropertyNode::LONG: {
171     long v1 = left->getLongValue();
172     long v2 = right->getLongValue();
173     if (v1 < v2)
174       return SGComparisonCondition::LESS_THAN;
175     else if (v1 > v2)
176       return SGComparisonCondition::GREATER_THAN;
177     else
178       return SGComparisonCondition::EQUALS;
179     break;
180   }
181   case SGPropertyNode::FLOAT: {
182     float v1 = left->getFloatValue();
183     float v2 = right->getFloatValue();
184     if (v1 < v2)
185       return SGComparisonCondition::LESS_THAN;
186     else if (v1 > v2)
187       return SGComparisonCondition::GREATER_THAN;
188     else
189       return SGComparisonCondition::EQUALS;
190     break;
191   }
192   case SGPropertyNode::DOUBLE: {
193     double v1 = left->getDoubleValue();
194     double v2 = right->getDoubleValue();
195     if (v1 < v2)
196       return SGComparisonCondition::LESS_THAN;
197     else if (v1 > v2)
198       return SGComparisonCondition::GREATER_THAN;
199     else
200       return SGComparisonCondition::EQUALS;
201     break;
202   }
203   case SGPropertyNode::STRING: 
204   case SGPropertyNode::NONE:
205   case SGPropertyNode::UNSPECIFIED: {
206     string v1 = left->getStringValue();
207     string v2 = right->getStringValue();
208     if (v1 < v2)
209       return SGComparisonCondition::LESS_THAN;
210     else if (v1 > v2)
211       return SGComparisonCondition::GREATER_THAN;
212     else
213       return SGComparisonCondition::EQUALS;
214     break;
215   }
216   default:
217     throw sg_exception("condition: unrecognized node type in comparison");
218   }
219   
220   return 0;
221 }
222
223
224 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
225   : _type(type),
226     _reverse(reverse),
227     _left_property(0),
228     _right_property(0),
229     _right_value(0)
230 {
231 }
232
233 SGComparisonCondition::~SGComparisonCondition ()
234 {
235 }
236
237 bool
238 SGComparisonCondition::test () const
239 {
240                                 // Always fail if incompletely specified
241   if (_left_property == 0 ||
242       (_right_property == 0 && _right_value == 0))
243     return false;
244
245                                 // Get LESS_THAN, EQUALS, or GREATER_THAN
246   int cmp =
247     doComparison(_left_property,
248                  (_right_property != 0 ? _right_property : _right_value));
249   if (!_reverse)
250     return (cmp == _type);
251   else
252     return (cmp != _type);
253 }
254
255 void
256 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
257                                         const char * propname )
258 {
259   _left_property = prop_root->getNode(propname, true);
260 }
261
262 void
263 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
264                                          const char * propname )
265 {
266   _right_value = 0;
267   _right_property = prop_root->getNode(propname, true);
268 }
269
270 void
271 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
272 {
273   _right_property = 0;
274   _right_value = new SGPropertyNode(*node);
275 }
276
277
278 \f
279 ////////////////////////////////////////////////////////////////////////
280 // Read a condition and use it if necessary.
281 ////////////////////////////////////////////////////////////////////////
282
283                                 // Forward declaration
284 static SGCondition * readCondition( SGPropertyNode *prop_root,
285                                     const SGPropertyNode *node );
286
287 static SGCondition *
288 readPropertyCondition( SGPropertyNode *prop_root,
289                        const SGPropertyNode *node )
290 {
291   return new SGPropertyCondition( prop_root, node->getStringValue() );
292 }
293
294 static SGCondition *
295 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
296 {
297   int nChildren = node->nChildren();
298   for (int i = 0; i < nChildren; i++) {
299     const SGPropertyNode * child = node->getChild(i);
300     SGCondition * condition = readCondition(prop_root, child);
301     if (condition != 0)
302       return new SGNotCondition(condition);
303   }
304   SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
305   return 0;
306 }
307
308 static SGCondition *
309 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
310 {
311   SGAndCondition * andCondition = new SGAndCondition;
312   int nChildren = node->nChildren();
313   for (int i = 0; i < nChildren; i++) {
314     const SGPropertyNode * child = node->getChild(i);
315     SGCondition * condition = readCondition(prop_root, child);
316     if (condition != 0)
317       andCondition->addCondition(condition);
318   }
319   return andCondition;
320 }
321
322 static SGCondition *
323 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
324 {
325   SGOrCondition * orCondition = new SGOrCondition;
326   int nChildren = node->nChildren();
327   for (int i = 0; i < nChildren; i++) {
328     const SGPropertyNode * child = node->getChild(i);
329     SGCondition * condition = readCondition(prop_root, child);
330     if (condition != 0)
331       orCondition->addCondition(condition);
332   }
333   return orCondition;
334 }
335
336 static SGCondition *
337 readComparison( SGPropertyNode *prop_root,
338                 const SGPropertyNode *node,
339                 SGComparisonCondition::Type type,
340                 bool reverse)
341 {
342   SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
343   condition->setLeftProperty(prop_root, node->getStringValue("property[0]"));
344   if (node->hasValue("property[1]"))
345     condition->setRightProperty(prop_root, node->getStringValue("property[1]"));
346   else if (node->hasValue("value"))
347     condition->setRightValue(node->getChild("value", 0));
348   else
349     throw sg_exception("condition: comparison without property[1] or value");
350
351   return condition;
352 }
353
354 static SGCondition *
355 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
356 {
357   const string &name = node->getName();
358   if (name == "property")
359     return readPropertyCondition(prop_root, node);
360   else if (name == "not")
361     return readNotCondition(prop_root, node);
362   else if (name == "and")
363     return readAndConditions(prop_root, node);
364   else if (name == "or")
365     return readOrConditions(prop_root, node);
366   else if (name == "less-than")
367     return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
368                           false);
369   else if (name == "less-than-equals")
370     return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
371                           true);
372   else if (name == "greater-than")
373     return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
374                           false);
375   else if (name == "greater-than-equals")
376     return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
377                           true);
378   else if (name == "equals")
379     return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
380                           false);
381   else if (name == "not-equals")
382     return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
383   else
384     return 0;
385 }
386
387
388 \f
389 ////////////////////////////////////////////////////////////////////////
390 // Implementation of SGConditional.
391 ////////////////////////////////////////////////////////////////////////
392
393 SGConditional::SGConditional ()
394   : _condition (0)
395 {
396 }
397
398 SGConditional::~SGConditional ()
399 {
400 }
401
402 void
403 SGConditional::setCondition (SGCondition * condition)
404 {
405   _condition = condition;
406 }
407
408 bool
409 SGConditional::test () const
410 {
411   return ((_condition == 0) || _condition->test());
412 }
413
414
415 \f
416 // The top-level is always an implicit 'and' group
417 SGCondition *
418 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
419 {
420   return readAndConditions(prop_root, node);
421 }
422
423
424 // end of condition.cxx