]> git.mxchange.org Git - simgear.git/blob - simgear/props/condition.cxx
Compile latest SimGear under MSVC9
[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_config.h>
12 #endif
13
14 // #include <iostream>
15
16 #include <simgear/structure/exception.hxx>
17
18 #include "props.hxx"
19 #include "condition.hxx"
20
21 #include <simgear/Math/SGMath.hxx>
22
23 using std::istream;
24 using std::ostream;
25
26
27
28 \f
29 ////////////////////////////////////////////////////////////////////////
30 // Implementation of SGCondition.
31 ////////////////////////////////////////////////////////////////////////
32
33 SGCondition::SGCondition ()
34 {
35 }
36
37 SGCondition::~SGCondition ()
38 {
39 }
40
41
42 \f
43 ////////////////////////////////////////////////////////////////////////
44 // Implementation of SGPropertyCondition.
45 ////////////////////////////////////////////////////////////////////////
46
47 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
48                                            const char *propname )
49     : _node( prop_root->getNode(propname, true) )
50 {
51 }
52
53 SGPropertyCondition::~SGPropertyCondition ()
54 {
55 }
56
57
58 \f
59 ////////////////////////////////////////////////////////////////////////
60 // Implementation of SGNotCondition.
61 ////////////////////////////////////////////////////////////////////////
62
63 SGNotCondition::SGNotCondition (SGCondition * condition)
64   : _condition(condition)
65 {
66 }
67
68 SGNotCondition::~SGNotCondition ()
69 {
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 }
91
92 bool
93 SGAndCondition::test () const
94 {
95   int nConditions = _conditions.size();
96   for (int i = 0; i < nConditions; i++) {
97     if (!_conditions[i]->test())
98       return false;
99   }
100   return true;
101 }
102
103 void
104 SGAndCondition::addCondition (SGCondition * condition)
105 {
106   _conditions.push_back(condition);
107 }
108
109
110 \f
111 ////////////////////////////////////////////////////////////////////////
112 // Implementation of SGOrCondition.
113 ////////////////////////////////////////////////////////////////////////
114
115 SGOrCondition::SGOrCondition ()
116 {
117 }
118
119 SGOrCondition::~SGOrCondition ()
120 {
121 }
122
123 bool
124 SGOrCondition::test () const
125 {
126   int nConditions = _conditions.size();
127   for (int i = 0; i < nConditions; i++) {
128     if (_conditions[i]->test())
129       return true;
130   }
131   return false;
132 }
133
134 void
135 SGOrCondition::addCondition (SGCondition * condition)
136 {
137   _conditions.push_back(condition);
138 }
139
140
141 \f
142 ////////////////////////////////////////////////////////////////////////
143 // Implementation of SGComparisonCondition.
144 ////////////////////////////////////////////////////////////////////////
145
146 static int
147 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
148 {
149   using namespace simgear;
150   switch (left->getType()) {
151   case props::BOOL: {
152     bool v1 = left->getBoolValue();
153     bool v2 = right->getBoolValue();
154     if (v1 < v2)
155       return SGComparisonCondition::LESS_THAN;
156     else if (v1 > v2)
157       return SGComparisonCondition::GREATER_THAN;
158     else
159       return SGComparisonCondition::EQUALS;
160     break;
161   }
162   case props::INT: {
163     int v1 = left->getIntValue();
164     int v2 = right->getIntValue();
165     if (v1 < v2)
166       return SGComparisonCondition::LESS_THAN;
167     else if (v1 > v2)
168       return SGComparisonCondition::GREATER_THAN;
169     else
170       return SGComparisonCondition::EQUALS;
171     break;
172   }
173   case props::LONG: {
174     long v1 = left->getLongValue();
175     long v2 = right->getLongValue();
176     if (v1 < v2)
177       return SGComparisonCondition::LESS_THAN;
178     else if (v1 > v2)
179       return SGComparisonCondition::GREATER_THAN;
180     else
181       return SGComparisonCondition::EQUALS;
182     break;
183   }
184   case props::FLOAT: {
185     float v1 = left->getFloatValue();
186     float v2 = right->getFloatValue();
187     if (v1 < v2)
188       return SGComparisonCondition::LESS_THAN;
189     else if (v1 > v2)
190       return SGComparisonCondition::GREATER_THAN;
191     else
192       return SGComparisonCondition::EQUALS;
193     break;
194   }
195   case props::DOUBLE: {
196     double v1 = left->getDoubleValue();
197     double v2 = right->getDoubleValue();
198     if (v1 < v2)
199       return SGComparisonCondition::LESS_THAN;
200     else if (v1 > v2)
201       return SGComparisonCondition::GREATER_THAN;
202     else
203       return SGComparisonCondition::EQUALS;
204     break;
205   }
206   case props::STRING:
207   case props::NONE:
208   case props::UNSPECIFIED: {
209     string v1 = left->getStringValue();
210     string v2 = right->getStringValue();
211     if (v1 < v2)
212       return SGComparisonCondition::LESS_THAN;
213     else if (v1 > v2)
214       return SGComparisonCondition::GREATER_THAN;
215     else
216       return SGComparisonCondition::EQUALS;
217     break;
218   }
219   default:
220     throw sg_exception("condition: unrecognized node type in comparison");
221   }
222   
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, "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 if (node->hasValue("value"))
350     condition->setRightValue(node->getChild("value", 0));
351   else
352     throw sg_exception("condition: comparison without property[1] or value");
353
354   return condition;
355 }
356
357 static SGCondition *
358 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
359 {
360   const string &name = node->getName();
361   if (name == "property")
362     return readPropertyCondition(prop_root, node);
363   else if (name == "not")
364     return readNotCondition(prop_root, node);
365   else if (name == "and")
366     return readAndConditions(prop_root, node);
367   else if (name == "or")
368     return readOrConditions(prop_root, node);
369   else if (name == "less-than")
370     return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
371                           false);
372   else if (name == "less-than-equals")
373     return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
374                           true);
375   else if (name == "greater-than")
376     return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
377                           false);
378   else if (name == "greater-than-equals")
379     return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
380                           true);
381   else if (name == "equals")
382     return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
383                           false);
384   else if (name == "not-equals")
385     return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
386   else
387     return 0;
388 }
389
390
391 \f
392 ////////////////////////////////////////////////////////////////////////
393 // Implementation of SGConditional.
394 ////////////////////////////////////////////////////////////////////////
395
396 SGConditional::SGConditional ()
397   : _condition (0)
398 {
399 }
400
401 SGConditional::~SGConditional ()
402 {
403 }
404
405 void
406 SGConditional::setCondition (SGCondition * condition)
407 {
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