]> git.mxchange.org Git - simgear.git/blob - simgear/props/condition.cxx
- Moved some property specific code into simgear/props/
[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     cout << "FGPropertyCondition::FGPropertyCondition()" << endl;
50     cout << "  prop_root = " << prop_root << endl;
51     cout << "  propname = " << propname << endl;
52     _node = prop_root->getNode(propname, true);
53     cout << "  _node = " << _node << endl;
54 }
55
56 FGPropertyCondition::~FGPropertyCondition ()
57 {
58 }
59
60
61 \f
62 ////////////////////////////////////////////////////////////////////////
63 // Implementation of FGNotCondition.
64 ////////////////////////////////////////////////////////////////////////
65
66 FGNotCondition::FGNotCondition (FGCondition * condition)
67   : _condition(condition)
68 {
69 }
70
71 FGNotCondition::~FGNotCondition ()
72 {
73   delete _condition;
74 }
75
76 bool
77 FGNotCondition::test () const
78 {
79   return !(_condition->test());
80 }
81
82
83 \f
84 ////////////////////////////////////////////////////////////////////////
85 // Implementation of FGAndCondition.
86 ////////////////////////////////////////////////////////////////////////
87
88 FGAndCondition::FGAndCondition ()
89 {
90 }
91
92 FGAndCondition::~FGAndCondition ()
93 {
94   for (unsigned int i = 0; i < _conditions.size(); i++)
95     delete _conditions[i];
96 }
97
98 bool
99 FGAndCondition::test () const
100 {
101   int nConditions = _conditions.size();
102   for (int i = 0; i < nConditions; i++) {
103     if (!_conditions[i]->test())
104       return false;
105   }
106   return true;
107 }
108
109 void
110 FGAndCondition::addCondition (FGCondition * condition)
111 {
112   _conditions.push_back(condition);
113 }
114
115
116 \f
117 ////////////////////////////////////////////////////////////////////////
118 // Implementation of FGOrCondition.
119 ////////////////////////////////////////////////////////////////////////
120
121 FGOrCondition::FGOrCondition ()
122 {
123 }
124
125 FGOrCondition::~FGOrCondition ()
126 {
127   for (unsigned int i = 0; i < _conditions.size(); i++)
128     delete _conditions[i];
129 }
130
131 bool
132 FGOrCondition::test () const
133 {
134   int nConditions = _conditions.size();
135   for (int i = 0; i < nConditions; i++) {
136     if (_conditions[i]->test())
137       return true;
138   }
139   return false;
140 }
141
142 void
143 FGOrCondition::addCondition (FGCondition * condition)
144 {
145   _conditions.push_back(condition);
146 }
147
148
149 \f
150 ////////////////////////////////////////////////////////////////////////
151 // Implementation of FGComparisonCondition.
152 ////////////////////////////////////////////////////////////////////////
153
154 static int
155 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
156 {
157   switch (left->getType()) {
158   case SGPropertyNode::BOOL: {
159     bool v1 = left->getBoolValue();
160     bool v2 = right->getBoolValue();
161     if (v1 < v2)
162       return FGComparisonCondition::LESS_THAN;
163     else if (v1 > v2)
164       return FGComparisonCondition::GREATER_THAN;
165     else
166       return FGComparisonCondition::EQUALS;
167     break;
168   }
169   case SGPropertyNode::INT: {
170     int v1 = left->getIntValue();
171     int v2 = right->getIntValue();
172     if (v1 < v2)
173       return FGComparisonCondition::LESS_THAN;
174     else if (v1 > v2)
175       return FGComparisonCondition::GREATER_THAN;
176     else
177       return FGComparisonCondition::EQUALS;
178     break;
179   }
180   case SGPropertyNode::LONG: {
181     long v1 = left->getLongValue();
182     long v2 = right->getLongValue();
183     if (v1 < v2)
184       return FGComparisonCondition::LESS_THAN;
185     else if (v1 > v2)
186       return FGComparisonCondition::GREATER_THAN;
187     else
188       return FGComparisonCondition::EQUALS;
189     break;
190   }
191   case SGPropertyNode::FLOAT: {
192     float v1 = left->getFloatValue();
193     float v2 = right->getFloatValue();
194     if (v1 < v2)
195       return FGComparisonCondition::LESS_THAN;
196     else if (v1 > v2)
197       return FGComparisonCondition::GREATER_THAN;
198     else
199       return FGComparisonCondition::EQUALS;
200     break;
201   }
202   case SGPropertyNode::DOUBLE: {
203     double v1 = left->getDoubleValue();
204     double v2 = right->getDoubleValue();
205     if (v1 < v2)
206       return FGComparisonCondition::LESS_THAN;
207     else if (v1 > v2)
208       return FGComparisonCondition::GREATER_THAN;
209     else
210       return FGComparisonCondition::EQUALS;
211     break;
212   }
213   case SGPropertyNode::STRING: 
214   case SGPropertyNode::NONE:
215   case SGPropertyNode::UNSPECIFIED: {
216     string v1 = left->getStringValue();
217     string v2 = right->getStringValue();
218     if (v1 < v2)
219       return FGComparisonCondition::LESS_THAN;
220     else if (v1 > v2)
221       return FGComparisonCondition::GREATER_THAN;
222     else
223       return FGComparisonCondition::EQUALS;
224     break;
225   }
226   }
227   throw sg_exception("Unrecognized node type");
228   return 0;
229 }
230
231
232 FGComparisonCondition::FGComparisonCondition (Type type, bool reverse)
233   : _type(type),
234     _reverse(reverse),
235     _left_property(0),
236     _right_property(0),
237     _right_value(0)
238 {
239 }
240
241 FGComparisonCondition::~FGComparisonCondition ()
242 {
243   delete _right_value;
244 }
245
246 bool
247 FGComparisonCondition::test () const
248 {
249                                 // Always fail if incompletely specified
250   if (_left_property == 0 ||
251       (_right_property == 0 && _right_value == 0))
252     return false;
253
254                                 // Get LESS_THAN, EQUALS, or GREATER_THAN
255   int cmp =
256     doComparison(_left_property,
257                  (_right_property != 0 ? _right_property : _right_value));
258   if (!_reverse)
259     return (cmp == _type);
260   else
261     return (cmp != _type);
262 }
263
264 void
265 FGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
266                                         const char * propname )
267 {
268   _left_property = prop_root->getNode(propname, true);
269 }
270
271 void
272 FGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
273                                          const char * propname )
274 {
275   delete _right_value;
276   _right_value = 0;
277   _right_property = prop_root->getNode(propname, true);
278 }
279
280 void
281 FGComparisonCondition::setRightValue (const SGPropertyNode *node)
282 {
283   _right_property = 0;
284   delete _right_value;
285   _right_value = new SGPropertyNode(*node);
286 }
287
288
289 \f
290 ////////////////////////////////////////////////////////////////////////
291 // Read a condition and use it if necessary.
292 ////////////////////////////////////////////////////////////////////////
293
294                                 // Forward declaration
295 static FGCondition * readCondition( SGPropertyNode *prop_root,
296                                     const SGPropertyNode *node );
297
298 static FGCondition *
299 readPropertyCondition( SGPropertyNode *prop_root,
300                        const SGPropertyNode *node )
301 {
302   return new FGPropertyCondition( prop_root, node->getStringValue() );
303 }
304
305 static FGCondition *
306 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
307 {
308   int nChildren = node->nChildren();
309   for (int i = 0; i < nChildren; i++) {
310     const SGPropertyNode * child = node->getChild(i);
311     FGCondition * condition = readCondition(prop_root, child);
312     if (condition != 0)
313       return new FGNotCondition(condition);
314   }
315   SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
316   return 0;
317 }
318
319 static FGCondition *
320 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
321 {
322   FGAndCondition * andCondition = new FGAndCondition;
323   int nChildren = node->nChildren();
324   for (int i = 0; i < nChildren; i++) {
325     const SGPropertyNode * child = node->getChild(i);
326     FGCondition * condition = readCondition(prop_root, child);
327     if (condition != 0)
328       andCondition->addCondition(condition);
329   }
330   return andCondition;
331 }
332
333 static FGCondition *
334 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
335 {
336   FGOrCondition * orCondition = new FGOrCondition;
337   int nChildren = node->nChildren();
338   for (int i = 0; i < nChildren; i++) {
339     const SGPropertyNode * child = node->getChild(i);
340     FGCondition * condition = readCondition(prop_root, child);
341     if (condition != 0)
342       orCondition->addCondition(condition);
343   }
344   return orCondition;
345 }
346
347 static FGCondition *
348 readComparison( SGPropertyNode *prop_root,
349                 const SGPropertyNode *node,
350                 FGComparisonCondition::Type type,
351                 bool reverse)
352 {
353   FGComparisonCondition * condition = new FGComparisonCondition(type, reverse);
354   condition->setLeftProperty(prop_root, node->getStringValue("property[0]"));
355   if (node->hasValue("property[1]"))
356     condition->setRightProperty(prop_root, node->getStringValue("property[1]"));
357   else
358     condition->setRightValue(node->getChild("value", 0));
359
360   return condition;
361 }
362
363 static FGCondition *
364 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
365 {
366   const string &name = node->getName();
367   if (name == "property")
368     return readPropertyCondition(prop_root, node);
369   else if (name == "not")
370     return readNotCondition(prop_root, node);
371   else if (name == "and")
372     return readAndConditions(prop_root, node);
373   else if (name == "or")
374     return readOrConditions(prop_root, node);
375   else if (name == "less-than")
376     return readComparison(prop_root, node, FGComparisonCondition::LESS_THAN,
377                           false);
378   else if (name == "less-than-equals")
379     return readComparison(prop_root, node, FGComparisonCondition::GREATER_THAN,
380                           true);
381   else if (name == "greater-than")
382     return readComparison(prop_root, node, FGComparisonCondition::GREATER_THAN,
383                           false);
384   else if (name == "greater-than-equals")
385     return readComparison(prop_root, node, FGComparisonCondition::LESS_THAN,
386                           true);
387   else if (name == "equals")
388     return readComparison(prop_root, node, FGComparisonCondition::EQUALS,
389                           false);
390   else if (name == "not-equals")
391     return readComparison(prop_root, node, FGComparisonCondition::EQUALS, true);
392   else
393     return 0;
394 }
395
396
397 \f
398 ////////////////////////////////////////////////////////////////////////
399 // Implementation of FGConditional.
400 ////////////////////////////////////////////////////////////////////////
401
402 FGConditional::FGConditional ()
403   : _condition (0)
404 {
405 }
406
407 FGConditional::~FGConditional ()
408 {
409   delete _condition;
410 }
411
412 void
413 FGConditional::setCondition (FGCondition * condition)
414 {
415   delete _condition;
416   _condition = condition;
417 }
418
419 bool
420 FGConditional::test () const
421 {
422   return ((_condition == 0) || _condition->test());
423 }
424
425
426 \f
427 // The top-level is always an implicit 'and' group
428 FGCondition *
429 fgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
430 {
431   return readAndConditions(prop_root, node);
432 }
433
434
435 // end of fg_props.cxx