condition.cxx

00001 // condition.cxx - Declarations and inline methods for property conditions.
00002 //
00003 // Written by David Megginson, started 2000.
00004 // CLO May 2003 - Split out condition specific code.
00005 //
00006 // This file is in the Public Domain, and comes with no warranty.
00007 //
00008 // $Id: condition_8cxx-source.html,v 1.11 2007-12-17 15:37:01 curt Exp $
00009 
00010 #ifdef HAVE_CONFIG_H
00011 #  include <simgear/compiler.h>
00012 #endif
00013 
00014 // #include STL_IOSTREAM
00015 
00016 #include <simgear/structure/exception.hxx>
00017 
00018 #include "props.hxx"
00019 #include "condition.hxx"
00020 
00021 SG_USING_STD(istream);
00022 SG_USING_STD(ostream);
00023 
00024 
00025 
00026 
00028 // Implementation of SGCondition.
00030 
00031 SGCondition::SGCondition ()
00032 {
00033 }
00034 
00035 SGCondition::~SGCondition ()
00036 {
00037 }
00038 
00039 
00040 
00042 // Implementation of SGPropertyCondition.
00044 
00045 SGPropertyCondition::SGPropertyCondition ( SGPropertyNode *prop_root,
00046                                            const char *propname )
00047     : _node( prop_root->getNode(propname, true) )
00048 {
00049 }
00050 
00051 SGPropertyCondition::~SGPropertyCondition ()
00052 {
00053 }
00054 
00055 
00056 
00058 // Implementation of SGNotCondition.
00060 
00061 SGNotCondition::SGNotCondition (SGCondition * condition)
00062   : _condition(condition)
00063 {
00064 }
00065 
00066 SGNotCondition::~SGNotCondition ()
00067 {
00068   delete _condition;
00069 }
00070 
00071 bool
00072 SGNotCondition::test () const
00073 {
00074   return !(_condition->test());
00075 }
00076 
00077 
00078 
00080 // Implementation of SGAndCondition.
00082 
00083 SGAndCondition::SGAndCondition ()
00084 {
00085 }
00086 
00087 SGAndCondition::~SGAndCondition ()
00088 {
00089   for (unsigned int i = 0; i < _conditions.size(); i++)
00090     delete _conditions[i];
00091 }
00092 
00093 bool
00094 SGAndCondition::test () const
00095 {
00096   int nConditions = _conditions.size();
00097   for (int i = 0; i < nConditions; i++) {
00098     if (!_conditions[i]->test())
00099       return false;
00100   }
00101   return true;
00102 }
00103 
00104 void
00105 SGAndCondition::addCondition (SGCondition * condition)
00106 {
00107   _conditions.push_back(condition);
00108 }
00109 
00110 
00111 
00113 // Implementation of SGOrCondition.
00115 
00116 SGOrCondition::SGOrCondition ()
00117 {
00118 }
00119 
00120 SGOrCondition::~SGOrCondition ()
00121 {
00122   for (unsigned int i = 0; i < _conditions.size(); i++)
00123     delete _conditions[i];
00124 }
00125 
00126 bool
00127 SGOrCondition::test () const
00128 {
00129   int nConditions = _conditions.size();
00130   for (int i = 0; i < nConditions; i++) {
00131     if (_conditions[i]->test())
00132       return true;
00133   }
00134   return false;
00135 }
00136 
00137 void
00138 SGOrCondition::addCondition (SGCondition * condition)
00139 {
00140   _conditions.push_back(condition);
00141 }
00142 
00143 
00144 
00146 // Implementation of SGComparisonCondition.
00148 
00149 static int
00150 doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
00151 {
00152   switch (left->getType()) {
00153   case SGPropertyNode::BOOL: {
00154     bool v1 = left->getBoolValue();
00155     bool v2 = right->getBoolValue();
00156     if (v1 < v2)
00157       return SGComparisonCondition::LESS_THAN;
00158     else if (v1 > v2)
00159       return SGComparisonCondition::GREATER_THAN;
00160     else
00161       return SGComparisonCondition::EQUALS;
00162     break;
00163   }
00164   case SGPropertyNode::INT: {
00165     int v1 = left->getIntValue();
00166     int v2 = right->getIntValue();
00167     if (v1 < v2)
00168       return SGComparisonCondition::LESS_THAN;
00169     else if (v1 > v2)
00170       return SGComparisonCondition::GREATER_THAN;
00171     else
00172       return SGComparisonCondition::EQUALS;
00173     break;
00174   }
00175   case SGPropertyNode::LONG: {
00176     long v1 = left->getLongValue();
00177     long v2 = right->getLongValue();
00178     if (v1 < v2)
00179       return SGComparisonCondition::LESS_THAN;
00180     else if (v1 > v2)
00181       return SGComparisonCondition::GREATER_THAN;
00182     else
00183       return SGComparisonCondition::EQUALS;
00184     break;
00185   }
00186   case SGPropertyNode::FLOAT: {
00187     float v1 = left->getFloatValue();
00188     float v2 = right->getFloatValue();
00189     if (v1 < v2)
00190       return SGComparisonCondition::LESS_THAN;
00191     else if (v1 > v2)
00192       return SGComparisonCondition::GREATER_THAN;
00193     else
00194       return SGComparisonCondition::EQUALS;
00195     break;
00196   }
00197   case SGPropertyNode::DOUBLE: {
00198     double v1 = left->getDoubleValue();
00199     double v2 = right->getDoubleValue();
00200     if (v1 < v2)
00201       return SGComparisonCondition::LESS_THAN;
00202     else if (v1 > v2)
00203       return SGComparisonCondition::GREATER_THAN;
00204     else
00205       return SGComparisonCondition::EQUALS;
00206     break;
00207   }
00208   case SGPropertyNode::STRING: 
00209   case SGPropertyNode::NONE:
00210   case SGPropertyNode::UNSPECIFIED: {
00211     string v1 = left->getStringValue();
00212     string v2 = right->getStringValue();
00213     if (v1 < v2)
00214       return SGComparisonCondition::LESS_THAN;
00215     else if (v1 > v2)
00216       return SGComparisonCondition::GREATER_THAN;
00217     else
00218       return SGComparisonCondition::EQUALS;
00219     break;
00220   }
00221   }
00222   throw sg_exception("condition: unrecognized node type in comparison");
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                                 // Always fail if incompletely specified
00244   if (_left_property == 0 ||
00245       (_right_property == 0 && _right_value == 0))
00246     return false;
00247 
00248                                 // Get LESS_THAN, EQUALS, or GREATER_THAN
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 // Read a condition and use it if necessary.
00285 
00286                                 // Forward declaration
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 // Implementation of SGConditional.
00395 
00396 SGConditional::SGConditional ()
00397   : _condition (0)
00398 {
00399 }
00400 
00401 SGConditional::~SGConditional ()
00402 {
00403   delete _condition;
00404 }
00405 
00406 void
00407 SGConditional::setCondition (SGCondition * condition)
00408 {
00409   delete _condition;
00410   _condition = condition;
00411 }
00412 
00413 bool
00414 SGConditional::test () const
00415 {
00416   return ((_condition == 0) || _condition->test());
00417 }
00418 
00419 
00420 
00421 // The top-level is always an implicit 'and' group
00422 SGCondition *
00423 sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )
00424 {
00425   return readAndConditions(prop_root, node);
00426 }
00427 
00428 
00429 // end of condition.cxx

Generated on Mon Dec 17 09:30:54 2007 for SimGear by  doxygen 1.5.1