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