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