]> git.mxchange.org Git - simgear.git/blob - simgear/props/condition.cxx
Harald JOHNSEN:
[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   delete _right_value;
239 }
240
241 bool
242 SGComparisonCondition::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 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
261                                         const char * propname )
262 {
263   _left_property = prop_root->getNode(propname, true);
264 }
265
266 void
267 SGComparisonCondition::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 SGComparisonCondition::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 SGCondition * readCondition( SGPropertyNode *prop_root,
291                                     const SGPropertyNode *node );
292
293 static SGCondition *
294 readPropertyCondition( SGPropertyNode *prop_root,
295                        const SGPropertyNode *node )
296 {
297   return new SGPropertyCondition( prop_root, node->getStringValue() );
298 }
299
300 static SGCondition *
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     SGCondition * condition = readCondition(prop_root, child);
307     if (condition != 0)
308       return new SGNotCondition(condition);
309   }
310   SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
311   return 0;
312 }
313
314 static SGCondition *
315 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
316 {
317   SGAndCondition * andCondition = new SGAndCondition;
318   int nChildren = node->nChildren();
319   for (int i = 0; i < nChildren; i++) {
320     const SGPropertyNode * child = node->getChild(i);
321     SGCondition * condition = readCondition(prop_root, child);
322     if (condition != 0)
323       andCondition->addCondition(condition);
324   }
325   return andCondition;
326 }
327
328 static SGCondition *
329 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
330 {
331   SGOrCondition * orCondition = new SGOrCondition;
332   int nChildren = node->nChildren();
333   for (int i = 0; i < nChildren; i++) {
334     const SGPropertyNode * child = node->getChild(i);
335     SGCondition * condition = readCondition(prop_root, child);
336     if (condition != 0)
337       orCondition->addCondition(condition);
338   }
339   return orCondition;
340 }
341
342 static SGCondition *
343 readComparison( SGPropertyNode *prop_root,
344                 const SGPropertyNode *node,
345                 SGComparisonCondition::Type type,
346                 bool reverse)
347 {
348   SGComparisonCondition * condition = new SGComparisonCondition(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 SGCondition *
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, SGComparisonCondition::LESS_THAN,
372                           false);
373   else if (name == "less-than-equals")
374     return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
375                           true);
376   else if (name == "greater-than")
377     return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
378                           false);
379   else if (name == "greater-than-equals")
380     return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
381                           true);
382   else if (name == "equals")
383     return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
384                           false);
385   else if (name == "not-equals")
386     return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
387   else
388     return 0;
389 }
390
391
392 \f
393 ////////////////////////////////////////////////////////////////////////
394 // Implementation of SGConditional.
395 ////////////////////////////////////////////////////////////////////////
396
397 SGConditional::SGConditional ()
398   : _condition (0)
399 {
400 }
401
402 SGConditional::~SGConditional ()
403 {
404   delete _condition;
405 }
406
407 void
408 SGConditional::setCondition (SGCondition * condition)
409 {
410   delete _condition;
411   _condition = condition;
412 }
413
414 bool
415 SGConditional::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 SGCondition *
424 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
425 {
426   return readAndConditions(prop_root, node);
427 }
428
429
430 // end of condition.cxx