%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
#include "FGSwitch.h"
+#include <iostream>
+#include <cstdlib>
+
+using namespace std;
namespace JSBSim {
-static const char *IdSrc = "$Id$";
+static const char *IdSrc = "$Id: FGSwitch.cpp,v 1.22 2011/06/17 12:12:19 jberndt Exp $";
static const char *IdHdr = ID_SWITCH;
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
struct test *current_test;
Element *test_element, *condition_element;
+ FGFCSComponent::bind(); // Bind() this component here in case it is used
+ // in its own definition for a sample-and-hold
+
test_element = element->GetElement();
while (test_element) {
if (test_element->GetName() == "default") {
- tests.push_back(test());
- current_test = &tests.back();
+ current_test = new struct test;
current_test->Logic = eDefault;
+ tests.push_back(current_test);
} else if (test_element->GetName() == "test") { // here's a test
- tests.push_back(test());
- current_test = &tests.back();
+ current_test = new struct test;
logic = test_element->GetAttributeValue("logic");
if (logic == "OR") current_test->Logic = eOR;
else if (logic == "AND") current_test->Logic = eAND;
else { // error
cerr << "Unrecognized LOGIC token " << logic << " in switch component: " << Name << endl;
}
- for (unsigned int i=0; i<test_element->GetNumDataLines(); i++)
- current_test->conditions.push_back(FGCondition(test_element->GetDataLine(i), PropertyManager));
+ for (unsigned int i=0; i<test_element->GetNumDataLines(); i++) {
+ string input_data = test_element->GetDataLine(i);
+ if (input_data.size() <= 1) {
+ // Make sure there are no bad data lines that consist solely of whitespace
+ cerr << fgred << " Bad data line in switch component: " << Name << reset << endl;
+ continue;
+ }
+ current_test->conditions.push_back(new FGCondition(input_data, PropertyManager));
+ }
condition_element = test_element->GetElement(); // retrieve condition groups
while (condition_element) {
- current_test->conditions.push_back(FGCondition(condition_element, PropertyManager));
+ current_test->conditions.push_back(new FGCondition(condition_element, PropertyManager));
condition_element = test_element->GetNextElement();
}
+ tests.push_back(current_test);
}
- if (test_element->GetName() != "output") { // this is not an output element
+ string el_name = test_element->GetName();
+ if ( el_name != "output"
+ && el_name != "description"
+ && el_name != "delay" )
+ {
value = test_element->GetAttributeValue("value");
if (value.empty()) {
cerr << "No VALUE supplied for switch component: " << Name << endl;
} else {
- if (value.find_first_not_of("-.0123456789eE") == string::npos) {
- // if true (and execution falls into this block), "value" is a number.
+ if (is_number(value)) {
current_test->OutputVal = atof(value.c_str());
} else {
// "value" must be a property if execution passes to here.
} else {
current_test->sign = 1.0;
}
- current_test->OutputProp = PropertyManager->GetNode(value);
+ FGPropertyManager *node = PropertyManager->GetNode(value, false);
+ if (node) {
+ current_test->OutputProp = new FGPropertyValue(node);
+ } else {
+ current_test->OutputProp = new FGPropertyValue(value,
+ PropertyManager);
+ }
}
}
}
-
test_element = element->GetNextElement();
}
- FGFCSComponent::bind();
-
Debug(0);
}
FGSwitch::~FGSwitch()
{
+ for (unsigned int i=0; i<tests.size(); i++) {
+ for (unsigned int j=0; j<tests[i]->conditions.size(); j++) delete tests[i]->conditions[j];
+ delete tests[i]->OutputProp;
+ delete tests[i];
+ }
+
Debug(1);
}
bool FGSwitch::Run(void )
{
- vector <test>::iterator iTests = tests.begin();
- vector <FGCondition>::iterator iConditions;
bool pass = false;
+ double default_output=0.0;
- while (iTests < tests.end()) {
- iConditions = iTests->conditions.begin();
-
- if (iTests->Logic == eDefault) {
- Output = iTests->GetValue();
- } else if (iTests->Logic == eAND) {
+ for (unsigned int i=0; i<tests.size(); i++) {
+ if (tests[i]->Logic == eDefault) {
+ default_output = tests[i]->GetValue();
+ } else if (tests[i]->Logic == eAND) {
pass = true;
- while (iConditions < iTests->conditions.end()) {
- if (!iConditions->Evaluate()) pass = false;
- *iConditions++;
+ for (unsigned int j=0; j<tests[i]->conditions.size(); j++) {
+ if (!tests[i]->conditions[j]->Evaluate()) pass = false;
}
- } else if (iTests->Logic == eOR) {
+ } else if (tests[i]->Logic == eOR) {
pass = false;
- while (iConditions < iTests->conditions.end()) {
- if (iConditions->Evaluate()) pass = true;
- *iConditions++;
+ for (unsigned int j=0; j<tests[i]->conditions.size(); j++) {
+ if (tests[i]->conditions[j]->Evaluate()) pass = true;
}
} else {
cerr << "Invalid logic test" << endl;
}
if (pass) {
- Output = iTests->GetValue();
+ Output = tests[i]->GetValue();
break;
}
- *iTests++;
}
+
+ if (!pass) Output = default_output;
+ if (delay != 0) Delay();
Clip();
if (IsOutput) SetOutput();
void FGSwitch::Debug(int from)
{
- vector <test>::iterator iTests = tests.begin();
- vector <FGCondition>::iterator iConditions;
string comp, scratch;
string indent = " ";
bool first = false;
if (debug_lvl & 1) { // Standard console startup message output
if (from == 0) { // Constructor
- while (iTests < tests.end()) {
+ for (unsigned int i=0; i<tests.size(); i++) {
scratch = " if ";
- switch(iTests->Logic) {
+ switch(tests[i]->Logic) {
case (elUndef):
comp = " UNSET ";
cerr << "Unset logic for test condition" << endl;
cerr << "Unknown logic for test condition" << endl;
}
- if (iTests->OutputProp != 0L)
- if (iTests->sign < 0)
- cout << indent << "Switch VALUE is - " << iTests->OutputProp->GetName() << scratch << endl;
+ if (tests[i]->OutputProp != 0L)
+ if (tests[i]->sign < 0)
+ cout << indent << "Switch VALUE is - " << tests[i]->OutputProp->GetName() << scratch << endl;
else
- cout << indent << "Switch VALUE is " << iTests->OutputProp->GetName() << scratch << endl;
+ cout << indent << "Switch VALUE is " << tests[i]->OutputProp->GetName() << scratch << endl;
else
- cout << indent << "Switch VALUE is " << iTests->OutputVal << scratch << endl;
+ cout << indent << "Switch VALUE is " << tests[i]->OutputVal << scratch << endl;
- iConditions = iTests->conditions.begin();
first = true;
- while (iConditions < iTests->conditions.end()) {
+ for (unsigned int j=0; j<tests[i]->conditions.size(); j++) {
if (!first) cout << indent << comp << " ";
else cout << indent << " ";
first = false;
- iConditions->PrintCondition();
+ tests[i]->conditions[j]->PrintCondition();
cout << endl;
- *iConditions++;
}
cout << endl;
- *iTests++;
}
- if (IsOutput) cout << " OUTPUT: " << OutputNode->getName() << endl;
+ if (IsOutput) {
+ for (unsigned int i=0; i<OutputNodes.size(); i++)
+ cout << " OUTPUT: " << OutputNodes[i]->getName() << endl;
+ }
}
}
if (debug_lvl & 2 ) { // Instantiation/Destruction notification