]> git.mxchange.org Git - simgear.git/blob - simgear/props/condition.cxx
whoops, sorry (Yes, it *was* tested, but then I made another "trivial"
[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 STL_IOSTREAM
15
16 #include <simgear/structure/exception.hxx>
17
18 #include "props.hxx"
19 #include "condition.hxx"
20
21 SG_USING_STD(istream);
22 SG_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   delete _condition;
69 }
70
71 bool
72 SGNotCondition::test () const
73 {
74   return !(_condition->test());
75 }
76
77
78 \f
79 ////////////////////////////////////////////////////////////////////////
80 // Implementation of SGAndCondition.
81 ////////////////////////////////////////////////////////////////////////
82
83 SGAndCondition::SGAndCondition ()
84 {
85 }
86
87 SGAndCondition::~SGAndCondition ()
88 {
89   for (unsigned int i = 0; i < _conditions.size(); i++)
90     delete _conditions[i];
91 }
92
93 bool
94 SGAndCondition::test () const
95 {
96   int nConditions = _conditions.size();
97   for (int i = 0; i < nConditions; i++) {
98     if (!_conditions[i]->test())
99       return false;
100   }
101   return true;
102 }
103
104 void
105 SGAndCondition::addCondition (SGCondition * condition)
106 {
107   _conditions.push_back(condition);
108 }
109
110
111 \f
112 ////////////////////////////////////////////////////////////////////////
113 // Implementation of SGOrCondition.
114 ////////////////////////////////////////////////////////////////////////
115
116 SGOrCondition::SGOrCondition ()
117 {
118 }
119
120 SGOrCondition::~SGOrCondition ()
121 {
122   for (unsigned int i = 0; i < _conditions.size(); i++)
123     delete _conditions[i];
124 }
125
126 bool
127 SGOrCondition::test () const
128 {
129   int nConditions = _conditions.size();
130   for (int i = 0; i < nConditions; i++) {
131     if (_conditions[i]->test())
132       return true;
133   }
134   return false;
135 }
136
137 void
138 SGOrCondition::addCondition (SGCondition * condition)
139 {
140   _conditions.push_back(condition);
141 }
142
143
144 \f
145 ////////////////////////////////////////////////////////////////////////
146 // Implementation of SGComparisonCondition.
147 ////////////////////////////////////////////////////////////////////////
148
149 static int
150 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
151 {
152   switch (left->getType()) {
153   case SGPropertyNode::BOOL: {
154     bool v1 = left->getBoolValue();
155     bool v2 = right->getBoolValue();
156     if (v1 < v2)
157       return SGComparisonCondition::LESS_THAN;
158     else if (v1 > v2)
159       return SGComparisonCondition::GREATER_THAN;
160     else
161       return SGComparisonCondition::EQUALS;
162     break;
163   }
164   case SGPropertyNode::INT: {
165     int v1 = left->getIntValue();
166     int v2 = right->getIntValue();
167     if (v1 < v2)
168       return SGComparisonCondition::LESS_THAN;
169     else if (v1 > v2)
170       return SGComparisonCondition::GREATER_THAN;
171     else
172       return SGComparisonCondition::EQUALS;
173     break;
174   }
175   case SGPropertyNode::LONG: {
176     long v1 = left->getLongValue();
177     long v2 = right->getLongValue();
178     if (v1 < v2)
179       return SGComparisonCondition::LESS_THAN;
180     else if (v1 > v2)
181       return SGComparisonCondition::GREATER_THAN;
182     else
183       return SGComparisonCondition::EQUALS;
184     break;
185   }
186   case SGPropertyNode::FLOAT: {
187     float v1 = left->getFloatValue();
188     float v2 = right->getFloatValue();
189     if (v1 < v2)
190       return SGComparisonCondition::LESS_THAN;
191     else if (v1 > v2)
192       return SGComparisonCondition::GREATER_THAN;
193     else
194       return SGComparisonCondition::EQUALS;
195     break;
196   }
197   case SGPropertyNode::DOUBLE: {
198     double v1 = left->getDoubleValue();
199     double v2 = right->getDoubleValue();
200     if (v1 < v2)
201       return SGComparisonCondition::LESS_THAN;
202     else if (v1 > v2)
203       return SGComparisonCondition::GREATER_THAN;
204     else
205       return SGComparisonCondition::EQUALS;
206     break;
207   }
208   case SGPropertyNode::STRING: 
209   case SGPropertyNode::NONE:
210   case SGPropertyNode::UNSPECIFIED: {
211     string v1 = left->getStringValue();
212     string v2 = right->getStringValue();
213     if (v1 < v2)
214       return SGComparisonCondition::LESS_THAN;
215     else if (v1 > v2)
216       return SGComparisonCondition::GREATER_THAN;
217     else
218       return SGComparisonCondition::EQUALS;
219     break;
220   }
221   }
222   throw sg_exception("Unrecognized node type");
223   return 0;
224 }
225
226
227 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
228   : _type(type),
229     _reverse(reverse),
230     _left_property(0),
231     _right_property(0),
232     _right_value(0)
233 {
234 }
235
236 SGComparisonCondition::~SGComparisonCondition ()
237 {
238 }
239
240 bool
241 SGComparisonCondition::test () const
242 {
243                                 // Always fail if incompletely specified
244   if (_left_property == 0 ||
245       (_right_property == 0 && _right_value == 0))
246     return false;
247
248                                 // Get LESS_THAN, EQUALS, or GREATER_THAN
249   int cmp =
250     doComparison(_left_property,
251                  (_right_property != 0 ? _right_property : _right_value));
252   if (!_reverse)
253     return (cmp == _type);
254   else
255     return (cmp != _type);
256 }
257
258 void
259 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
260                                         const char * propname )
261 {
262   _left_property = prop_root->getNode(propname, true);
263 }
264
265 void
266 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
267                                          const char * propname )
268 {
269   _right_value = 0;
270   _right_property = prop_root->getNode(propname, true);
271 }
272
273 void
274 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
275 {
276   _right_property = 0;
277   _right_value = new SGPropertyNode(*node);
278 }
279
280
281 \f
282 ////////////////////////////////////////////////////////////////////////
283 // Read a condition and use it if necessary.
284 ////////////////////////////////////////////////////////////////////////
285
286                                 // Forward declaration
287 static SGCondition * readCondition( SGPropertyNode *prop_root,
288                                     const SGPropertyNode *node );
289
290 static SGCondition *
291 readPropertyCondition( SGPropertyNode *prop_root,
292                        const SGPropertyNode *node )
293 {
294   return new SGPropertyCondition( prop_root, node->getStringValue() );
295 }
296
297 static SGCondition *
298 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
299 {
300   int nChildren = node->nChildren();
301   for (int i = 0; i < nChildren; i++) {
302     const SGPropertyNode * child = node->getChild(i);
303     SGCondition * condition = readCondition(prop_root, child);
304     if (condition != 0)
305       return new SGNotCondition(condition);
306   }
307   SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
308   return 0;
309 }
310
311 static SGCondition *
312 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
313 {
314   SGAndCondition * andCondition = new SGAndCondition;
315   int nChildren = node->nChildren();
316   for (int i = 0; i < nChildren; i++) {
317     const SGPropertyNode * child = node->getChild(i);
318     SGCondition * condition = readCondition(prop_root, child);
319     if (condition != 0)
320       andCondition->addCondition(condition);
321   }
322   return andCondition;
323 }
324
325 static SGCondition *
326 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
327 {
328   SGOrCondition * orCondition = new SGOrCondition;
329   int nChildren = node->nChildren();
330   for (int i = 0; i < nChildren; i++) {
331     const SGPropertyNode * child = node->getChild(i);
332     SGCondition * condition = readCondition(prop_root, child);
333     if (condition != 0)
334       orCondition->addCondition(condition);
335   }
336   return orCondition;
337 }
338
339 static SGCondition *
340 readComparison( SGPropertyNode *prop_root,
341                 const SGPropertyNode *node,
342                 SGComparisonCondition::Type type,
343                 bool reverse)
344 {
345   SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
346   condition->setLeftProperty(prop_root, node->getStringValue("property[0]"));
347   if (node->hasValue("property[1]"))
348     condition->setRightProperty(prop_root, node->getStringValue("property[1]"));
349   else
350     condition->setRightValue(node->getChild("value", 0));
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   delete _condition;
402 }
403
404 void
405 SGConditional::setCondition (SGCondition * condition)
406 {
407   delete _condition;
408   _condition = condition;
409 }
410
411 bool
412 SGConditional::test () const
413 {
414   return ((_condition == 0) || _condition->test());
415 }
416
417
418 \f
419 // The top-level is always an implicit 'and' group
420 SGCondition *
421 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
422 {
423   return readAndConditions(prop_root, node);
424 }
425
426
427 // end of condition.cxx