- added FGCondition class and subclasses
- implemented FGConditional abstract base class - added fgReadCondition global function
This commit is contained in:
parent
cd6683bdb5
commit
4de352cbe8
1 changed files with 394 additions and 0 deletions
|
@ -1132,4 +1132,398 @@ fgLoadFlight (istream &input)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation of FGCondition.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FGCondition::FGCondition ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FGCondition::~FGCondition ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation of FGPropertyCondition.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FGPropertyCondition::FGPropertyCondition (const string &propname)
|
||||||
|
: _node(fgGetNode(propname, true))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FGPropertyCondition::~FGPropertyCondition ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation of FGNotCondition.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FGNotCondition::FGNotCondition (FGCondition * condition)
|
||||||
|
: _condition(condition)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FGNotCondition::~FGNotCondition ()
|
||||||
|
{
|
||||||
|
delete _condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FGNotCondition::test () const
|
||||||
|
{
|
||||||
|
return !(_condition->test());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation of FGAndCondition.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FGAndCondition::FGAndCondition ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FGAndCondition::~FGAndCondition ()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _conditions.size(); i++)
|
||||||
|
delete _conditions[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FGAndCondition::test () const
|
||||||
|
{
|
||||||
|
int nConditions = _conditions.size();
|
||||||
|
for (int i = 0; i < nConditions; i++) {
|
||||||
|
if (!_conditions[i]->test())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGAndCondition::addCondition (FGCondition * condition)
|
||||||
|
{
|
||||||
|
_conditions.push_back(condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation of FGOrCondition.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FGOrCondition::FGOrCondition ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FGOrCondition::~FGOrCondition ()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _conditions.size(); i++)
|
||||||
|
delete _conditions[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FGOrCondition::test () const
|
||||||
|
{
|
||||||
|
int nConditions = _conditions.size();
|
||||||
|
for (int i = 0; i < nConditions; i++) {
|
||||||
|
if (_conditions[i]->test())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGOrCondition::addCondition (FGCondition * condition)
|
||||||
|
{
|
||||||
|
_conditions.push_back(condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation of FGComparisonCondition.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static int
|
||||||
|
doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
||||||
|
{
|
||||||
|
switch (left->getType()) {
|
||||||
|
case SGPropertyNode::BOOL: {
|
||||||
|
bool v1 = left->getBoolValue();
|
||||||
|
bool v2 = right->getBoolValue();
|
||||||
|
if (v1 < v2)
|
||||||
|
return FGComparisonCondition::LESS_THAN;
|
||||||
|
else if (v1 > v2)
|
||||||
|
return FGComparisonCondition::GREATER_THAN;
|
||||||
|
else
|
||||||
|
return FGComparisonCondition::EQUALS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SGPropertyNode::INT: {
|
||||||
|
int v1 = left->getIntValue();
|
||||||
|
int v2 = right->getIntValue();
|
||||||
|
if (v1 < v2)
|
||||||
|
return FGComparisonCondition::LESS_THAN;
|
||||||
|
else if (v1 > v2)
|
||||||
|
return FGComparisonCondition::GREATER_THAN;
|
||||||
|
else
|
||||||
|
return FGComparisonCondition::EQUALS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SGPropertyNode::LONG: {
|
||||||
|
long v1 = left->getLongValue();
|
||||||
|
long v2 = right->getLongValue();
|
||||||
|
if (v1 < v2)
|
||||||
|
return FGComparisonCondition::LESS_THAN;
|
||||||
|
else if (v1 > v2)
|
||||||
|
return FGComparisonCondition::GREATER_THAN;
|
||||||
|
else
|
||||||
|
return FGComparisonCondition::EQUALS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SGPropertyNode::FLOAT: {
|
||||||
|
float v1 = left->getFloatValue();
|
||||||
|
float v2 = right->getFloatValue();
|
||||||
|
if (v1 < v2)
|
||||||
|
return FGComparisonCondition::LESS_THAN;
|
||||||
|
else if (v1 > v2)
|
||||||
|
return FGComparisonCondition::GREATER_THAN;
|
||||||
|
else
|
||||||
|
return FGComparisonCondition::EQUALS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SGPropertyNode::DOUBLE: {
|
||||||
|
double v1 = left->getDoubleValue();
|
||||||
|
double v2 = right->getDoubleValue();
|
||||||
|
if (v1 < v2)
|
||||||
|
return FGComparisonCondition::LESS_THAN;
|
||||||
|
else if (v1 > v2)
|
||||||
|
return FGComparisonCondition::GREATER_THAN;
|
||||||
|
else
|
||||||
|
return FGComparisonCondition::EQUALS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SGPropertyNode::STRING:
|
||||||
|
case SGPropertyNode::NONE:
|
||||||
|
case SGPropertyNode::UNSPECIFIED: {
|
||||||
|
string v1 = left->getStringValue();
|
||||||
|
string v2 = right->getStringValue();
|
||||||
|
if (v1 < v2)
|
||||||
|
return FGComparisonCondition::LESS_THAN;
|
||||||
|
else if (v1 > v2)
|
||||||
|
return FGComparisonCondition::GREATER_THAN;
|
||||||
|
else
|
||||||
|
return FGComparisonCondition::EQUALS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw sg_exception("Unrecognized node type");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FGComparisonCondition::FGComparisonCondition (Type type, bool reverse)
|
||||||
|
: _type(type),
|
||||||
|
_reverse(reverse),
|
||||||
|
_left_property(0),
|
||||||
|
_right_property(0),
|
||||||
|
_right_value(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FGComparisonCondition::~FGComparisonCondition ()
|
||||||
|
{
|
||||||
|
delete _right_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FGComparisonCondition::test () const
|
||||||
|
{
|
||||||
|
// Always fail if incompletely specified
|
||||||
|
if (_left_property == 0 ||
|
||||||
|
(_right_property == 0 && _right_value == 0))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Get LESS_THAN, EQUALS, or GREATER_THAN
|
||||||
|
int cmp =
|
||||||
|
doComparison(_left_property,
|
||||||
|
(_right_property != 0 ? _right_property : _right_value));
|
||||||
|
if (!_reverse)
|
||||||
|
return (cmp == _type);
|
||||||
|
else
|
||||||
|
return (cmp != _type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGComparisonCondition::setLeftProperty (const string &propname)
|
||||||
|
{
|
||||||
|
_left_property = fgGetNode(propname, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGComparisonCondition::setRightProperty (const string &propname)
|
||||||
|
{
|
||||||
|
delete _right_value;
|
||||||
|
_right_value = 0;
|
||||||
|
_right_property = fgGetNode(propname, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGComparisonCondition::setRightValue (const SGPropertyNode *node)
|
||||||
|
{
|
||||||
|
_right_property = 0;
|
||||||
|
delete _right_value;
|
||||||
|
_right_value = new SGPropertyNode(*node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Read a condition and use it if necessary.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
|
static FGCondition * readCondition (const SGPropertyNode * node);
|
||||||
|
|
||||||
|
static FGCondition *
|
||||||
|
readPropertyCondition (const SGPropertyNode * node)
|
||||||
|
{
|
||||||
|
return new FGPropertyCondition(node->getStringValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
static FGCondition *
|
||||||
|
readNotCondition (const SGPropertyNode * node)
|
||||||
|
{
|
||||||
|
int nChildren = node->nChildren();
|
||||||
|
for (int i = 0; i < nChildren; i++) {
|
||||||
|
const SGPropertyNode * child = node->getChild(i);
|
||||||
|
FGCondition * condition = readCondition(child);
|
||||||
|
if (condition != 0)
|
||||||
|
return new FGNotCondition(condition);
|
||||||
|
}
|
||||||
|
SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FGCondition *
|
||||||
|
readAndConditions (const SGPropertyNode * node)
|
||||||
|
{
|
||||||
|
FGAndCondition * andCondition = new FGAndCondition;
|
||||||
|
int nChildren = node->nChildren();
|
||||||
|
for (int i = 0; i < nChildren; i++) {
|
||||||
|
const SGPropertyNode * child = node->getChild(i);
|
||||||
|
FGCondition * condition = readCondition(child);
|
||||||
|
if (condition != 0)
|
||||||
|
andCondition->addCondition(condition);
|
||||||
|
}
|
||||||
|
return andCondition;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FGCondition *
|
||||||
|
readOrConditions (const SGPropertyNode * node)
|
||||||
|
{
|
||||||
|
FGOrCondition * orCondition = new FGOrCondition;
|
||||||
|
int nChildren = node->nChildren();
|
||||||
|
for (int i = 0; i < nChildren; i++) {
|
||||||
|
const SGPropertyNode * child = node->getChild(i);
|
||||||
|
FGCondition * condition = readCondition(child);
|
||||||
|
if (condition != 0)
|
||||||
|
orCondition->addCondition(condition);
|
||||||
|
}
|
||||||
|
return orCondition;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FGCondition *
|
||||||
|
readComparison (const SGPropertyNode * node,
|
||||||
|
FGComparisonCondition::Type type,
|
||||||
|
bool reverse)
|
||||||
|
{
|
||||||
|
FGComparisonCondition * condition = new FGComparisonCondition(type, reverse);
|
||||||
|
condition->setLeftProperty(node->getStringValue("property[0]"));
|
||||||
|
if (node->hasValue("property[1]"))
|
||||||
|
condition->setRightProperty(node->getStringValue("property[1]"));
|
||||||
|
else
|
||||||
|
condition->setRightValue(node->getChild("value", 0));
|
||||||
|
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FGCondition *
|
||||||
|
readCondition (const SGPropertyNode * node)
|
||||||
|
{
|
||||||
|
const string &name = node->getName();
|
||||||
|
if (name == "property")
|
||||||
|
return readPropertyCondition(node);
|
||||||
|
else if (name == "not")
|
||||||
|
return readNotCondition(node);
|
||||||
|
else if (name == "and")
|
||||||
|
return readAndConditions(node);
|
||||||
|
else if (name == "or")
|
||||||
|
return readOrConditions(node);
|
||||||
|
else if (name == "less-than")
|
||||||
|
return readComparison(node, FGComparisonCondition::LESS_THAN, false);
|
||||||
|
else if (name == "less-than-equals")
|
||||||
|
return readComparison(node, FGComparisonCondition::GREATER_THAN, true);
|
||||||
|
else if (name == "greater-than")
|
||||||
|
return readComparison(node, FGComparisonCondition::GREATER_THAN, false);
|
||||||
|
else if (name == "greater-than-equals")
|
||||||
|
return readComparison(node, FGComparisonCondition::LESS_THAN, true);
|
||||||
|
else if (name == "equals")
|
||||||
|
return readComparison(node, FGComparisonCondition::EQUALS, false);
|
||||||
|
else if (name == "not-equals")
|
||||||
|
return readComparison(node, FGComparisonCondition::EQUALS, true);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Implementation of FGConditional.
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FGConditional::FGConditional ()
|
||||||
|
: _condition (0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FGConditional::~FGConditional ()
|
||||||
|
{
|
||||||
|
delete _condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FGConditional::setCondition (FGCondition * condition)
|
||||||
|
{
|
||||||
|
delete _condition;
|
||||||
|
_condition = condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FGConditional::test () const
|
||||||
|
{
|
||||||
|
return ((_condition == 0) || _condition->test());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The top-level is always an implicit 'and' group
|
||||||
|
FGCondition *
|
||||||
|
fgReadCondition (const SGPropertyNode * node)
|
||||||
|
{
|
||||||
|
return readAndConditions(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// end of fg_props.cxx
|
// end of fg_props.cxx
|
||||||
|
|
Loading…
Add table
Reference in a new issue