]> git.mxchange.org Git - simgear.git/blob - simgear/props/condition.cxx
Removed some extraneous debugging output. Hey, this one was subtle. Due
[simgear.git] / simgear / props / condition.cxx
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.
4 //
5 // This file is in the Public Domain, and comes with no warranty.
6 //
7 // $Id$
8
9 #ifdef HAVE_CONFIG_H
10 #  include <simgear/compiler.h>
11 #endif
12
13 // #include STL_IOSTREAM
14
15 #include <simgear/misc/exception.hxx>
16
17 #include "props.hxx"
18
19 #include "condition.hxx"
20
21 SG_USING_STD(istream);
22 SG_USING_STD(ostream);
23
24
25
26 \f
27 ////////////////////////////////////////////////////////////////////////
28 // Implementation of FGCondition.
29 ////////////////////////////////////////////////////////////////////////
30
31 FGCondition::FGCondition ()
32 {
33 }
34
35 FGCondition::~FGCondition ()
36 {
37 }
38
39
40 \f
41 ////////////////////////////////////////////////////////////////////////
42 // Implementation of FGPropertyCondition.
43 ////////////////////////////////////////////////////////////////////////
44
45 FGPropertyCondition::FGPropertyCondition ( SGPropertyNode *prop_root,
46                                            const char *propname )
47     : _node( prop_root->getNode(propname, true) )
48 {
49 }
50
51 FGPropertyCondition::~FGPropertyCondition ()
52 {
53 }
54
55
56 \f
57 ////////////////////////////////////////////////////////////////////////
58 // Implementation of FGNotCondition.
59 ////////////////////////////////////////////////////////////////////////
60
61 FGNotCondition::FGNotCondition (FGCondition * condition)
62   : _condition(condition)
63 {
64 }
65
66 FGNotCondition::~FGNotCondition ()
67 {
68   delete _condition;
69 }
70
71 bool
72 FGNotCondition::test () const
73 {
74   return !(_condition->test());
75 }
76
77
78 \f
79 ////////////////////////////////////////////////////////////////////////
80 // Implementation of FGAndCondition.
81 ////////////////////////////////////////////////////////////////////////
82
83 FGAndCondition::FGAndCondition ()
84 {
85 }
86
87 FGAndCondition::~FGAndCondition ()
88 {
89   for (unsigned int i = 0; i < _conditions.size(); i++)
90     delete _conditions[i];
91 }
92
93 bool
94 FGAndCondition::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 FGAndCondition::addCondition (FGCondition * condition)
106 {
107   _conditions.push_back(condition);
108 }
109
110
111 \f
112 ////////////////////////////////////////////////////////////////////////
113 // Implementation of FGOrCondition.
114 ////////////////////////////////////////////////////////////////////////
115
116 FGOrCondition::FGOrCondition ()
117 {
118 }
119
120 FGOrCondition::~FGOrCondition ()
121 {
122   for (unsigned int i = 0; i < _conditions.size(); i++)
123     delete _conditions[i];
124 }
125
126 bool
127 FGOrCondition::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 FGOrCondition::addCondition (FGCondition * condition)
139 {
140   _conditions.push_back(condition);
141 }
142
143
144 \f
145 ////////////////////////////////////////////////////////////////////////
146 // Implementation of FGComparisonCondition.
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 FGComparisonCondition::LESS_THAN;
158     else if (v1 > v2)
159       return FGComparisonCondition::GREATER_THAN;
160     else
161       return FGComparisonCondition::EQUALS;
162     break;
163   }
164   case SGPropertyNode::INT: {
165     int v1 = left->getIntValue();
166     int v2 = right->getIntValue();
167     if (v1 < v2)
168       return FGComparisonCondition::LESS_THAN;
169     else if (v1 > v2)
170       return FGComparisonCondition::GREATER_THAN;
171     else
172       return FGComparisonCondition::EQUALS;
173     break;
174   }
175   case SGPropertyNode::LONG: {
176     long v1 = left->getLongValue();
177     long v2 = right->getLongValue();
178     if (v1 < v2)
179       return FGComparisonCondition::LESS_THAN;
180     else if (v1 > v2)
181       return FGComparisonCondition::GREATER_THAN;
182     else
183       return FGComparisonCondition::EQUALS;
184     break;
185   }
186   case SGPropertyNode::FLOAT: {
187     float v1 = left->getFloatValue();
188     float v2 = right->getFloatValue();
189     if (v1 < v2)
190       return FGComparisonCondition::LESS_THAN;
191     else if (v1 > v2)
192       return FGComparisonCondition::GREATER_THAN;
193     else
194       return FGComparisonCondition::EQUALS;
195     break;
196   }
197   case SGPropertyNode::DOUBLE: {
198     double v1 = left->getDoubleValue();
199     double v2 = right->getDoubleValue();
200     if (v1 < v2)
201       return FGComparisonCondition::LESS_THAN;
202     else if (v1 > v2)
203       return FGComparisonCondition::GREATER_THAN;
204     else
205       return FGComparisonCondition::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 FGComparisonCondition::LESS_THAN;
215     else if (v1 > v2)
216       return FGComparisonCondition::GREATER_THAN;
217     else
218       return FGComparisonCondition::EQUALS;
219     break;
220   }
221   }
222   throw sg_exception("Unrecognized node type");
223   return 0;
224 }
225
226
227 FGComparisonCondition::FGComparisonCondition (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 FGComparisonCondition::~FGComparisonCondition ()
237 {
238   delete _right_value;
239 }
240
241 bool
242 FGComparisonCondition::test () const
243 {
244                                 // Always fail if incompletely specified
245   if (_left_property == 0 ||
246       (_right_property == 0 && _right_value == 0))
247     return false;
248
249                                 // Get LESS_THAN, EQUALS, or GREATER_THAN
250   int cmp =
251     doComparison(_left_property,
252                  (_right_property != 0 ? _right_property : _right_value));
253   if (!_reverse)
254     return (cmp == _type);
255   else
256     return (cmp != _type);
257 }
258
259 void
260 FGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
261                                         const char * propname )
262 {
263   _left_property = prop_root->getNode(propname, true);
264 }
265
266 void
267 FGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
268                                          const char * propname )
269 {
270   delete _right_value;
271   _right_value = 0;
272   _right_property = prop_root->getNode(propname, true);
273 }
274
275 void
276 FGComparisonCondition::setRightValue (const SGPropertyNode *node)
277 {
278   _right_property = 0;
279   delete _right_value;
280   _right_value = new SGPropertyNode(*node);
281 }
282
283
284 \f
285 ////////////////////////////////////////////////////////////////////////
286 // Read a condition and use it if necessary.
287 ////////////////////////////////////////////////////////////////////////
288
289                                 // Forward declaration
290 static FGCondition * readCondition( SGPropertyNode *prop_root,
291                                     const SGPropertyNode *node );
292
293 static FGCondition *
294 readPropertyCondition( SGPropertyNode *prop_root,
295                        const SGPropertyNode *node )
296 {
297   return new FGPropertyCondition( prop_root, node->getStringValue() );
298 }
299
300 static FGCondition *
301 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
302 {
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);
307     if (condition != 0)
308       return new FGNotCondition(condition);
309   }
310   SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
311   return 0;
312 }
313
314 static FGCondition *
315 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
316 {
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);
322     if (condition != 0)
323       andCondition->addCondition(condition);
324   }
325   return andCondition;
326 }
327
328 static FGCondition *
329 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
330 {
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);
336     if (condition != 0)
337       orCondition->addCondition(condition);
338   }
339   return orCondition;
340 }
341
342 static FGCondition *
343 readComparison( SGPropertyNode *prop_root,
344                 const SGPropertyNode *node,
345                 FGComparisonCondition::Type type,
346                 bool reverse)
347 {
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]"));
352   else
353     condition->setRightValue(node->getChild("value", 0));
354
355   return condition;
356 }
357
358 static FGCondition *
359 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
360 {
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,
372                           false);
373   else if (name == "less-than-equals")
374     return readComparison(prop_root, node, FGComparisonCondition::GREATER_THAN,
375                           true);
376   else if (name == "greater-than")
377     return readComparison(prop_root, node, FGComparisonCondition::GREATER_THAN,
378                           false);
379   else if (name == "greater-than-equals")
380     return readComparison(prop_root, node, FGComparisonCondition::LESS_THAN,
381                           true);
382   else if (name == "equals")
383     return readComparison(prop_root, node, FGComparisonCondition::EQUALS,
384                           false);
385   else if (name == "not-equals")
386     return readComparison(prop_root, node, FGComparisonCondition::EQUALS, true);
387   else
388     return 0;
389 }
390
391
392 \f
393 ////////////////////////////////////////////////////////////////////////
394 // Implementation of FGConditional.
395 ////////////////////////////////////////////////////////////////////////
396
397 FGConditional::FGConditional ()
398   : _condition (0)
399 {
400 }
401
402 FGConditional::~FGConditional ()
403 {
404   delete _condition;
405 }
406
407 void
408 FGConditional::setCondition (FGCondition * condition)
409 {
410   delete _condition;
411   _condition = condition;
412 }
413
414 bool
415 FGConditional::test () const
416 {
417   return ((_condition == 0) || _condition->test());
418 }
419
420
421 \f
422 // The top-level is always an implicit 'and' group
423 FGCondition *
424 fgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
425 {
426   return readAndConditions(prop_root, node);
427 }
428
429
430 // end of fg_props.cxx