00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifdef HAVE_CONFIG_H
00011 # include <simgear_config.h>
00012 #endif
00013
00014
00015
00016 #include <simgear/structure/exception.hxx>
00017
00018 #include "props.hxx"
00019 #include "condition.hxx"
00020
00021 #include <simgear/math/SGMath.hxx>
00022
00023 using std::istream;
00024 using std::ostream;
00025
00026
00027
00028
00030
00032
00033 SGCondition::SGCondition ()
00034 {
00035 }
00036
00037 SGCondition::~SGCondition ()
00038 {
00039 }
00040
00041
00042
00044
00046
00047 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
00048 const char *propname )
00049 : _node( prop_root->getNode(propname, true) )
00050 {
00051 }
00052
00053 SGPropertyCondition::~SGPropertyCondition ()
00054 {
00055 }
00056
00057
00058
00060
00062
00063 SGNotCondition::SGNotCondition (SGCondition * condition)
00064 : _condition(condition)
00065 {
00066 }
00067
00068 SGNotCondition::~SGNotCondition ()
00069 {
00070 }
00071
00072 bool
00073 SGNotCondition::test () const
00074 {
00075 return !(_condition->test());
00076 }
00077
00078
00079
00081
00083
00084 SGAndCondition::SGAndCondition ()
00085 {
00086 }
00087
00088 SGAndCondition::~SGAndCondition ()
00089 {
00090 }
00091
00092 bool
00093 SGAndCondition::test () const
00094 {
00095 int nConditions = _conditions.size();
00096 for (int i = 0; i < nConditions; i++) {
00097 if (!_conditions[i]->test())
00098 return false;
00099 }
00100 return true;
00101 }
00102
00103 void
00104 SGAndCondition::addCondition (SGCondition * condition)
00105 {
00106 _conditions.push_back(condition);
00107 }
00108
00109
00110
00112
00114
00115 SGOrCondition::SGOrCondition ()
00116 {
00117 }
00118
00119 SGOrCondition::~SGOrCondition ()
00120 {
00121 }
00122
00123 bool
00124 SGOrCondition::test () const
00125 {
00126 int nConditions = _conditions.size();
00127 for (int i = 0; i < nConditions; i++) {
00128 if (_conditions[i]->test())
00129 return true;
00130 }
00131 return false;
00132 }
00133
00134 void
00135 SGOrCondition::addCondition (SGCondition * condition)
00136 {
00137 _conditions.push_back(condition);
00138 }
00139
00140
00141
00143
00145
00146 static int
00147 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
00148 {
00149 using namespace simgear;
00150 switch (left->getType()) {
00151 case props::BOOL: {
00152 bool v1 = left->getBoolValue();
00153 bool v2 = right->getBoolValue();
00154 if (v1 < v2)
00155 return SGComparisonCondition::LESS_THAN;
00156 else if (v1 > v2)
00157 return SGComparisonCondition::GREATER_THAN;
00158 else
00159 return SGComparisonCondition::EQUALS;
00160 break;
00161 }
00162 case props::INT: {
00163 int v1 = left->getIntValue();
00164 int v2 = right->getIntValue();
00165 if (v1 < v2)
00166 return SGComparisonCondition::LESS_THAN;
00167 else if (v1 > v2)
00168 return SGComparisonCondition::GREATER_THAN;
00169 else
00170 return SGComparisonCondition::EQUALS;
00171 break;
00172 }
00173 case props::LONG: {
00174 long v1 = left->getLongValue();
00175 long v2 = right->getLongValue();
00176 if (v1 < v2)
00177 return SGComparisonCondition::LESS_THAN;
00178 else if (v1 > v2)
00179 return SGComparisonCondition::GREATER_THAN;
00180 else
00181 return SGComparisonCondition::EQUALS;
00182 break;
00183 }
00184 case props::FLOAT: {
00185 float v1 = left->getFloatValue();
00186 float v2 = right->getFloatValue();
00187 if (v1 < v2)
00188 return SGComparisonCondition::LESS_THAN;
00189 else if (v1 > v2)
00190 return SGComparisonCondition::GREATER_THAN;
00191 else
00192 return SGComparisonCondition::EQUALS;
00193 break;
00194 }
00195 case props::DOUBLE: {
00196 double v1 = left->getDoubleValue();
00197 double v2 = right->getDoubleValue();
00198 if (v1 < v2)
00199 return SGComparisonCondition::LESS_THAN;
00200 else if (v1 > v2)
00201 return SGComparisonCondition::GREATER_THAN;
00202 else
00203 return SGComparisonCondition::EQUALS;
00204 break;
00205 }
00206 case props::STRING:
00207 case props::NONE:
00208 case props::UNSPECIFIED: {
00209 string v1 = left->getStringValue();
00210 string v2 = right->getStringValue();
00211 if (v1 < v2)
00212 return SGComparisonCondition::LESS_THAN;
00213 else if (v1 > v2)
00214 return SGComparisonCondition::GREATER_THAN;
00215 else
00216 return SGComparisonCondition::EQUALS;
00217 break;
00218 }
00219 default:
00220 throw sg_exception("condition: unrecognized node type in comparison");
00221 }
00222
00223 return 0;
00224 }
00225
00226
00227 SGComparisonCondition::SGComparisonCondition (Type type, bool reverse)
00228 : _type(type),
00229 _reverse(reverse),
00230 _left_property(0),
00231 _right_property(0),
00232 _right_value(0)
00233 {
00234 }
00235
00236 SGComparisonCondition::~SGComparisonCondition ()
00237 {
00238 }
00239
00240 bool
00241 SGComparisonCondition::test () const
00242 {
00243
00244 if (_left_property == 0 ||
00245 (_right_property == 0 && _right_value == 0))
00246 return false;
00247
00248
00249 int cmp =
00250 doComparison(_left_property,
00251 (_right_property != 0 ? _right_property : _right_value));
00252 if (!_reverse)
00253 return (cmp == _type);
00254 else
00255 return (cmp != _type);
00256 }
00257
00258 void
00259 SGComparisonCondition::setLeftProperty( SGPropertyNode *prop_root,
00260 const char * propname )
00261 {
00262 _left_property = prop_root->getNode(propname, true);
00263 }
00264
00265 void
00266 SGComparisonCondition::setRightProperty( SGPropertyNode *prop_root,
00267 const char * propname )
00268 {
00269 _right_value = 0;
00270 _right_property = prop_root->getNode(propname, true);
00271 }
00272
00273 void
00274 SGComparisonCondition::setRightValue (const SGPropertyNode *node)
00275 {
00276 _right_property = 0;
00277 _right_value = new SGPropertyNode(*node);
00278 }
00279
00280
00281
00283
00285
00286
00287 static SGCondition * readCondition( SGPropertyNode *prop_root,
00288 const SGPropertyNode *node );
00289
00290 static SGCondition *
00291 readPropertyCondition( SGPropertyNode *prop_root,
00292 const SGPropertyNode *node )
00293 {
00294 return new SGPropertyCondition( prop_root, node->getStringValue() );
00295 }
00296
00297 static SGCondition *
00298 readNotCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
00299 {
00300 int nChildren = node->nChildren();
00301 for (int i = 0; i < nChildren; i++) {
00302 const SGPropertyNode * child = node->getChild(i);
00303 SGCondition * condition = readCondition(prop_root, child);
00304 if (condition != 0)
00305 return new SGNotCondition(condition);
00306 }
00307 SG_LOG(SG_COCKPIT, SG_ALERT, "empty 'not' condition");
00308 return 0;
00309 }
00310
00311 static SGCondition *
00312 readAndConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
00313 {
00314 SGAndCondition * andCondition = new SGAndCondition;
00315 int nChildren = node->nChildren();
00316 for (int i = 0; i < nChildren; i++) {
00317 const SGPropertyNode * child = node->getChild(i);
00318 SGCondition * condition = readCondition(prop_root, child);
00319 if (condition != 0)
00320 andCondition->addCondition(condition);
00321 }
00322 return andCondition;
00323 }
00324
00325 static SGCondition *
00326 readOrConditions( SGPropertyNode *prop_root, const SGPropertyNode *node )
00327 {
00328 SGOrCondition * orCondition = new SGOrCondition;
00329 int nChildren = node->nChildren();
00330 for (int i = 0; i < nChildren; i++) {
00331 const SGPropertyNode * child = node->getChild(i);
00332 SGCondition * condition = readCondition(prop_root, child);
00333 if (condition != 0)
00334 orCondition->addCondition(condition);
00335 }
00336 return orCondition;
00337 }
00338
00339 static SGCondition *
00340 readComparison( SGPropertyNode *prop_root,
00341 const SGPropertyNode *node,
00342 SGComparisonCondition::Type type,
00343 bool reverse)
00344 {
00345 SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
00346 condition->setLeftProperty(prop_root, node->getStringValue("property[0]"));
00347 if (node->hasValue("property[1]"))
00348 condition->setRightProperty(prop_root, node->getStringValue("property[1]"));
00349 else if (node->hasValue("value"))
00350 condition->setRightValue(node->getChild("value", 0));
00351 else
00352 throw sg_exception("condition: comparison without property[1] or value");
00353
00354 return condition;
00355 }
00356
00357 static SGCondition *
00358 readCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
00359 {
00360 const string &name = node->getName();
00361 if (name == "property")
00362 return readPropertyCondition(prop_root, node);
00363 else if (name == "not")
00364 return readNotCondition(prop_root, node);
00365 else if (name == "and")
00366 return readAndConditions(prop_root, node);
00367 else if (name == "or")
00368 return readOrConditions(prop_root, node);
00369 else if (name == "less-than")
00370 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
00371 false);
00372 else if (name == "less-than-equals")
00373 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
00374 true);
00375 else if (name == "greater-than")
00376 return readComparison(prop_root, node, SGComparisonCondition::GREATER_THAN,
00377 false);
00378 else if (name == "greater-than-equals")
00379 return readComparison(prop_root, node, SGComparisonCondition::LESS_THAN,
00380 true);
00381 else if (name == "equals")
00382 return readComparison(prop_root, node, SGComparisonCondition::EQUALS,
00383 false);
00384 else if (name == "not-equals")
00385 return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
00386 else
00387 return 0;
00388 }
00389
00390
00391
00393
00395
00396 SGConditional::SGConditional ()
00397 : _condition (0)
00398 {
00399 }
00400
00401 SGConditional::~SGConditional ()
00402 {
00403 }
00404
00405 void
00406 SGConditional::setCondition (SGCondition * condition)
00407 {
00408 _condition = condition;
00409 }
00410
00411 bool
00412 SGConditional::test () const
00413 {
00414 return ((_condition == 0) || _condition->test());
00415 }
00416
00417
00418
00419
00420 SGCondition *
00421 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
00422 {
00423 return readAndConditions(prop_root, node);
00424 }
00425
00426
00427