]> git.mxchange.org Git - flightgear.git/blobdiff - src/Network/generic.cxx
Switch from bool to int for more deterministic structure packing.
[flightgear.git] / src / Network / generic.cxx
index 14a25619361848dc81020a4aeb8094ec60d9dfd5..38481b08b238e19b2199c41924dd7c139a478450 100644 (file)
@@ -2,7 +2,7 @@
 //
 // Written by Curtis Olson, started November 1999.
 //
-// Copyright (C) 1999  Curtis L. Olson - curt@flightgear.org
+// Copyright (C) 1999  Curtis L. Olson - http://www.flightgear.org/~curt
 //
 // This program is free software; you can redistribute it and/or
 // modify it under the terms of the GNU General Public License as
@@ -21,6 +21,9 @@
 // $Id$
 
 
+#include <string.h>            // strstr()
+#include <stdlib.h>            // strtod(), atoi()
+
 #include <simgear/debug/logstream.hxx>
 #include <simgear/io/iochannel.hxx>
 #include <simgear/structure/exception.hxx>
@@ -34,6 +37,7 @@
 #include "generic.hxx"
 
 
+
 FGGeneric::FGGeneric(string& config) {
 
     string file = config+".xml";
@@ -53,77 +57,20 @@ FGGeneric::FGGeneric(string& config) {
          return;
     }
 
+    _out_message.clear();
     SGPropertyNode *output = root.getNode("generic/output");
+    if (output)
+        read_config(output, _out_message);
 
-        /* These variables specified in the fgfsbase/Properties/xxxx.xml file for each format
-         * var_sep_string = the string/charachter to place between variables
-         * line_sep_string = the string/charachter to place at the end of each lot of variables
-         */
-    var_sep_string = output->getStringValue("var_separator");
-    line_sep_string = output->getStringValue("line_separator");
-
-        if ( var_sep_string == "newline" )
-                var_separator = '\n';
-        else if ( var_sep_string == "tab" )
-                var_separator = '\t';
-        else if ( var_sep_string == "space" )
-                var_separator = ' ';
-        else if ( var_sep_string == "formfeed" )
-                var_separator = '\f';
-        else if ( var_sep_string == "carriagereturn" )
-                var_sep_string = '\r';
-        else if ( var_sep_string == "verticaltab" )
-                var_separator = '\v';
-        else
-                var_separator = var_sep_string;
-
-        if ( line_sep_string == "newline" )
-                line_separator = '\n';
-        if ( line_sep_string == "tab" )
-                line_separator = '\t';
-        if ( line_sep_string == "space" )
-                line_separator = ' ';
-        else if ( line_sep_string == "formfeed" )
-                line_separator = '\f';
-        else if ( line_sep_string == "carriagereturn" )
-                line_separator = '\r';
-        else if ( line_sep_string == "verticaltab" )
-                line_separator = '\v';
-        else
-                line_separator = line_sep_string;
-
-
-    vector<SGPropertyNode_ptr> chunks = output->getChildren("chunk");
-    for (unsigned int i = 0; i < chunks.size(); i++) {
-
-        _serial_prot chunk;
-
-     // chunk.name = chunks[i]->getStringValue("name");
-        chunk.format = chunks[i]->getStringValue("format", "%d");
-        chunk.offset = chunks[i]->getDoubleValue("offset");
-        chunk.factor = chunks[i]->getDoubleValue("offset", 1.0);
-
-        string node = chunks[i]->getStringValue("node");
-        chunk.prop = fgGetNode(node.c_str(), true);
-
-        string type = chunks[i]->getStringValue("type");
-        if (type == "bool")
-            chunk.type = FG_BOOL;
-        else if (type == "float")
-            chunk.type = FG_DOUBLE;
-        else if (type == "string")
-            chunk.type = FG_STRING;
-        else
-            chunk.type = FG_INT;
-
-        _message.push_back(chunk);
-        
-    }
-
+    _in_message.clear();
+    SGPropertyNode *input = root.getNode("generic/input");
+    if (input)
+        read_config(input, _in_message);
 }
 
 FGGeneric::~FGGeneric() {
-    _message.clear();
+    _out_message.clear();
+    _in_message.clear();
 }
 
 
@@ -135,38 +82,40 @@ bool FGGeneric::gen_message() {
 
     double val;
 
-    for (unsigned int i = 0; i < _message.size(); i++) {
+    for (unsigned int i = 0; i < _out_message.size(); i++) {
 
         if (i > 0)
            generic_sentence += var_separator;
 
-        switch (_message[i].type) {
+        switch (_out_message[i].type) {
         case FG_INT:
-            val = _message[i].offset +
-                    _message[i].prop->getIntValue() * _message[i].factor;
-            snprintf(tmp, 255, _message[i].format.c_str(), (int)val);
+            val = _out_message[i].offset +
+                  _out_message[i].prop->getIntValue() * _out_message[i].factor;
+            snprintf(tmp, 255, _out_message[i].format.c_str(), (int)val);
             break;
 
         case FG_BOOL:
-            snprintf(tmp, 255, _message[i].format.c_str(),
-                               _message[i].prop->getBoolValue());
+            snprintf(tmp, 255, _out_message[i].format.c_str(),
+                               _out_message[i].prop->getBoolValue());
             break;
 
         case FG_DOUBLE:
-            val = _message[i].offset +
-                       _message[i].prop->getDoubleValue() * _message[i].factor;
-            snprintf(tmp, 255, _message[i].format.c_str(), val);
+            val = _out_message[i].offset +
+                _out_message[i].prop->getFloatValue() * _out_message[i].factor;
+            snprintf(tmp, 255, _out_message[i].format.c_str(), (float)val);
             break;
 
         default: // SG_STRING
-             snprintf(tmp, 255, _message[i].format.c_str(),
-                               _message[i].prop->getStringValue());
+             snprintf(tmp, 255, _out_message[i].format.c_str(),
+                                _out_message[i].prop->getStringValue());
         }
 
         generic_sentence += tmp;
     }
 
-    /* After each lot of variables has been added, put the line separator char/string */
+    /* After each lot of variables has been added, put the line separator
+     * char/string
+     */
     generic_sentence += line_separator;
  
             
@@ -177,7 +126,42 @@ bool FGGeneric::gen_message() {
 }
 
 bool FGGeneric::parse_message() {
-        return true;
+    char *p2, *p1 = buf;
+    double val;
+    int i = -1;
+
+    while ((++i < _in_message.size()) &&
+           p1 && strcmp(p1, line_separator.c_str())) {
+
+        p2 = strstr(p1, var_separator.c_str());
+        if (p2) {
+            *p2 = 0;
+            p2 += var_separator.length();
+        }
+
+        switch (_in_message[i].type) {
+        case FG_INT:
+            val = _in_message[i].offset + atoi(p1) * _in_message[i].factor;
+            _in_message[i].prop->setIntValue((int)val);
+            break;
+
+        case FG_BOOL:
+            _in_message[i].prop->setBoolValue( atof(p1) != 0.0 );
+            break;
+
+        case FG_DOUBLE:
+            val = _in_message[i].offset + strtod(p1, 0) * _in_message[i].factor;
+            _in_message[i].prop->setFloatValue((float)val);
+            break;
+
+        default: // SG_STRING
+             _in_message[i].prop->setStringValue(p1);
+        }
+
+        p1 = p2;
+    }
+    
+    return true;
 }
 
 
@@ -214,13 +198,12 @@ bool FGGeneric::process() {
             return false;
         }
     } else if ( get_direction() == SG_IO_IN ) {
-        // Temporarliy disable this as output only!
-        //if ( (length = io->readline( buf, FG_MAX_MSG_SIZE )) > 0 ) {
-        //    parse_message();
-        //} else {
-        //    SG_LOG( SG_IO, SG_ALERT, "Error reading data." );
-        //    return false;
-        //}
+        if ( (length = io->readline( buf, FG_MAX_MSG_SIZE )) > 0 ) {
+            parse_message();
+        } else {
+            SG_LOG( SG_IO, SG_ALERT, "Error reading data." );
+            return false;
+        }
     }
 
     return true;
@@ -239,3 +222,78 @@ bool FGGeneric::close() {
 
     return true;
 }
+
+
+void
+FGGeneric::read_config(SGPropertyNode *root, vector<_serial_prot> &msg)
+{
+        /* These variables specified in the $FG_ROOT/data/Protocol/xxx.xml
+         * file for each format
+         *
+         * var_sep_string  = the string/charachter to place between variables
+         * line_sep_string = the string/charachter to place at the end of each
+         *                   lot of variables
+         */
+    var_sep_string = root->getStringValue("var_separator");
+    line_sep_string = root->getStringValue("line_separator");
+
+        if ( var_sep_string == "newline" )
+                var_separator = '\n';
+        else if ( var_sep_string == "tab" )
+                var_separator = '\t';
+        else if ( var_sep_string == "space" )
+                var_separator = ' ';
+        else if ( var_sep_string == "formfeed" )
+                var_separator = '\f';
+        else if ( var_sep_string == "carriagereturn" )
+                var_sep_string = '\r';
+        else if ( var_sep_string == "verticaltab" )
+                var_separator = '\v';
+        else
+                var_separator = var_sep_string;
+
+        if ( line_sep_string == "newline" )
+                line_separator = '\n';
+        else if ( line_sep_string == "tab" )
+                line_separator = '\t';
+        else if ( line_sep_string == "space" )
+                line_separator = ' ';
+        else if ( line_sep_string == "formfeed" )
+                line_separator = '\f';
+        else if ( line_sep_string == "carriagereturn" )
+                line_separator = '\r';
+        else if ( line_sep_string == "verticaltab" )
+                line_separator = '\v';
+        else
+                line_separator = line_sep_string;
+
+
+    vector<SGPropertyNode_ptr> chunks = root->getChildren("chunk");
+    for (unsigned int i = 0; i < chunks.size(); i++) {
+
+        _serial_prot chunk;
+
+     // chunk.name = chunks[i]->getStringValue("name");
+        chunk.format = chunks[i]->getStringValue("format", "%d");
+        chunk.offset = chunks[i]->getDoubleValue("offset");
+        chunk.factor = chunks[i]->getDoubleValue("factor", 1.0);
+
+        string node = chunks[i]->getStringValue("node");
+        chunk.prop = fgGetNode(node.c_str(), true);
+
+        string type = chunks[i]->getStringValue("type");
+        if (type == "bool")
+            chunk.type = FG_BOOL;
+        else if (type == "float")
+            chunk.type = FG_DOUBLE;
+        else if (type == "string")
+            chunk.type = FG_STRING;
+        else
+            chunk.type = FG_INT;
+
+        msg.push_back(chunk);
+
+    }
+
+}
+