]> git.mxchange.org Git - simgear.git/blob - simgear/props/condition.cxx
Cleanup of properties
[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   using namespace simgear::props;
148   switch (left->getType()) {
149   case BOOL: {
150     bool v1 = left->getBoolValue();
151     bool v2 = right->getBoolValue();
152     if (v1 < v2)
153       return SGComparisonCondition::LESS_THAN;
154     else if (v1 > v2)
155       return SGComparisonCondition::GREATER_THAN;
156     else
157       return SGComparisonCondition::EQUALS;
158     break;
159   }
160   case INT: {
161     int v1 = left->getIntValue();
162     int v2 = right->getIntValue();
163     if (v1 < v2)
164       return SGComparisonCondition::LESS_THAN;
165     else if (v1 > v2)
166       return SGComparisonCondition::GREATER_THAN;
167     else
168       return SGComparisonCondition::EQUALS;
169     break;
170   }
171   case LONG: {
172     long v1 = left->getLongValue();
173     long v2 = right->getLongValue();
174     if (v1 < v2)
175       return SGComparisonCondition::LESS_THAN;
176     else if (v1 > v2)
177       return SGComparisonCondition::GREATER_THAN;
178     else
179       return SGComparisonCondition::EQUALS;
180     break;
181   }
182   case FLOAT: {
183     float v1 = left->getFloatValue();
184     float v2 = right->getFloatValue();
185     if (v1 < v2)
186       return SGComparisonCondition::LESS_THAN;
187     else if (v1 > v2)
188       return SGComparisonCondition::GREATER_THAN;
189     else
190       return SGComparisonCondition::EQUALS;
191     break;
192   }
193   case DOUBLE: {
194     double v1 = left->getDoubleValue();
195     double v2 = right->getDoubleValue();
196     if (v1 < v2)
197       return SGComparisonCondition::LESS_THAN;
198     else if (v1 > v2)
199       return SGComparisonCondition::GREATER_THAN;
200     else
201       return SGComparisonCondition::EQUALS;
202     break;
203   }
204   case STRING:
205   case NONE:
206   case UNSPECIFIED: {
207     string v1 = left->getStringValue();
208     string v2 = right->getStringValue();
209     if (v1 < v2)
210       return SGComparisonCondition::LESS_THAN;
211     else if (v1 > v2)
212       return SGComparisonCondition::GREATER_THAN;
213     else
214       return SGComparisonCondition::EQUALS;
215     break;
216   }
217   default:
218     throw sg_exception("condition: unrecognized node type in comparison");
219   }
220   
221   return 0;
222 }
223
224
225 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
226   : _type(type),
227     _reverse(reverse),
228     _left_property(0),
229     _right_property(0),
230     _right_value(0)
231 {
232 }
233
234 SGComparisonCondition::~SGComparisonCondition ()
235 {
236 }
237
238 bool
239 SGComparisonCondition::test () const
240 {
241                                 // Always fail if incompletely specified
242   if (_left_property == 0 ||
243       (_right_property == 0 && _right_value == 0))
244     return false;
245
246                                 // Get LESS_THAN, EQUALS, or GREATER_THAN
247   int cmp =
248     doComparison(_left_property,
249                  (_right_property != 0 ? _right_property : _right_value));
250   if (!_reverse)
251     return (cmp == _type);
252   else
253     return (cmp != _type);
254 }
255
256 void
257 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
258                                         const char * propname )
259 {
260   _left_property = prop_root->getNode(propname, true);
261 }
262
263 void
264 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
265                                          const char * propname )
266 {
267   _right_value = 0;
268   _right_property = prop_root->getNode(propname, true);
269 }
270
271 void
272 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
273 {
274   _right_property = 0;
275   _right_value = new SGPropertyNode(*node);
276 }
277
278
279 \f
280 ////////////////////////////////////////////////////////////////////////
281 // Read a condition and use it if necessary.
282 ////////////////////////////////////////////////////////////////////////
283
284                                 // Forward declaration
285 static SGCondition * readCondition( SGPropertyNode *prop_root,
286                                     const SGPropertyNode *node );
287
288 static SGCondition *
289 readPropertyCondition( SGPropertyNode *prop_root,
290                        const SGPropertyNode *node )
291 {
292   return new SGPropertyCondition( prop_root, node->getStringValue() );
293 }
294
295 static SGCondition *
296 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
297 {
298   int nChildren = node->nChildren();
299   for (int i = 0; i < nChildren; i++) {
300     const SGPropertyNode * child = node->getChild(i);
301     SGCondition * condition = readCondition(prop_root, child);
302     if (condition != 0)
303       return new SGNotCondition(condition);
304   }
305   SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
306   return 0;
307 }
308
309 static SGCondition *
310 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
311 {
312   SGAndCondition * andCondition = new SGAndCondition;
313   int nChildren = node->nChildren();
314   for (int i = 0; i < nChildren; i++) {
315     const SGPropertyNode * child = node->getChild(i);
316     SGCondition * condition = readCondition(prop_root, child);
317     if (condition != 0)
318       andCondition->addCondition(condition);
319   }
320   return andCondition;
321 }
322
323 static SGCondition *
324 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
325 {
326   SGOrCondition * orCondition = new SGOrCondition;
327   int nChildren = node->nChildren();
328   for (int i = 0; i < nChildren; i++) {
329     const SGPropertyNode * child = node->getChild(i);
330     SGCondition * condition = readCondition(prop_root, child);
331     if (condition != 0)
332       orCondition->addCondition(condition);
333   }
334   return orCondition;
335 }
336
337 static SGCondition *
338 readComparison( SGPropertyNode *prop_root,
339                 const SGPropertyNode *node,
340                 SGComparisonCondition::Type type,
341                 bool reverse)
342 {
343   SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
344   condition->setLeftProperty(prop_root, node->getStringValue("property[0]"));
345   if (node->hasValue("property[1]"))
346     condition->setRightProperty(prop_root, node->getStringValue("property[1]"));
347   else if (node->hasValue("value"))
348     condition->setRightValue(node->getChild("value", 0));
349   else
350     throw sg_exception("condition: comparison without property[1] or value");
351
352   return condition;
353 }
354
355 static SGCondition *
356 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
357 {
358   const string &name = node->getName();
359   if (name == "property")
360     return readPropertyCondition(prop_root, node);
361   else if (name == "not")
362     return readNotCondition(prop_root, node);
363   else if (name == "and")
364     return readAndConditions(prop_root, node);
365   else if (name == "or")
366     return readOrConditions(prop_root, node);
367   else if (name == "less-than")
368     return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
369                           false);
370   else if (name == "less-than-equals")
371     return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
372                           true);
373   else if (name == "greater-than")
374     return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
375                           false);
376   else if (name == "greater-than-equals")
377     return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
378                           true);
379   else if (name == "equals")
380     return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
381                           false);
382   else if (name == "not-equals")
383     return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
384   else
385     return 0;
386 }
387
388
389 \f
390 ////////////////////////////////////////////////////////////////////////
391 // Implementation of SGConditional.
392 ////////////////////////////////////////////////////////////////////////
393
394 SGConditional::SGConditional ()
395   : _condition (0)
396 {
397 }
398
399 SGConditional::~SGConditional ()
400 {
401 }
402
403 void
404 SGConditional::setCondition (SGCondition * condition)
405 {
406   _condition = condition;
407 }
408
409 bool
410 SGConditional::test () const
411 {
412   return ((_condition == 0) || _condition->test());
413 }
414
415
416 \f
417 // The top-level is always an implicit 'and' group
418 SGCondition *
419 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
420 {
421   return readAndConditions(prop_root, node);
422 }
423
424
425 // end of condition.cxx