From 4de352cbe8c4a86ccf6084fbe03f163f3355add9 Mon Sep 17 00:00:00 2001 From: curt Date: Fri, 3 Aug 2001 00:19:41 +0000 Subject: [PATCH] - added FGCondition class and subclasses - implemented FGConditional abstract base class - added fgReadCondition global function --- src/Main/fg_props.cxx | 394 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) diff --git a/src/Main/fg_props.cxx b/src/Main/fg_props.cxx index e2fd5fc9f..396aa66e2 100644 --- a/src/Main/fg_props.cxx +++ b/src/Main/fg_props.cxx @@ -1132,4 +1132,398 @@ fgLoadFlight (istream &input) 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