#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
+#include <Main/fg_os.hxx>
#include <Main/util.hxx>
-
#include "generic.hxx"
file_name = config+".xml";
direction = tokens[2];
- if (direction != "in" && direction != "out") {
+ if (direction != "in" && direction != "out" && direction != "bi") {
SG_LOG(SG_GENERAL, SG_ALERT, "Unsuported protocol direction: "
<< direction);
}
switch (_out_message[i].type) {
case FG_INT:
+ {
val = _out_message[i].offset +
_out_message[i].prop->getIntValue() * _out_message[i].factor;
-
- if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
- *((int32_t*)&buf[length]) = (int32_t)val;
- } else {
- *((uint32_t*)&buf[length]) = sg_bswap_32((uint32_t)val);
+ int32_t intVal = val;
+ if (binary_byte_order != BYTE_ORDER_MATCHES_NETWORK_ORDER) {
+ intVal = (int32_t) sg_bswap_32((uint32_t)intVal);
}
+ memcpy(&buf[length], &intVal, sizeof(int32_t));
length += sizeof(int32_t);
break;
+ }
case FG_BOOL:
- *((int8_t*)&buf[length])
- = _out_message[i].prop->getBoolValue() ? true : false;
+ buf[length] = (char) (_out_message[i].prop->getBoolValue() ? true : false);
length += 1;
break;
val = _out_message[i].offset +
_out_message[i].prop->getFloatValue() * _out_message[i].factor;
- int fixed = (int)(val * 65536.0f);
- if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
- *((int32_t*)&buf[length]) = (int32_t)fixed;
- } else {
- *((uint32_t*)&buf[length]) = sg_bswap_32((uint32_t)fixed);
+ int32_t fixed = (int)(val * 65536.0f);
+ if (binary_byte_order != BYTE_ORDER_MATCHES_NETWORK_ORDER) {
+ fixed = (int32_t) sg_bswap_32((uint32_t)fixed);
}
+ memcpy(&buf[length], &fixed, sizeof(int32_t));
length += sizeof(int32_t);
break;
}
+
case FG_FLOAT:
+ {
val = _out_message[i].offset +
_out_message[i].prop->getFloatValue() * _out_message[i].factor;
+ u32 tmpun32;
+ tmpun32.floatVal = static_cast<float>(val);
- if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
- *((float*)&buf[length]) = val;
- } else {
- u32 tmpun32;
- tmpun32.floatVal = static_cast<float>(val);
- *((uint32_t*)&buf[length]) = sg_bswap_32(tmpun32.intVal);
+ if (binary_byte_order != BYTE_ORDER_MATCHES_NETWORK_ORDER) {
+ tmpun32.intVal = sg_bswap_32(tmpun32.intVal);
}
+ memcpy(&buf[length], &tmpun32.intVal, sizeof(uint32_t));
length += sizeof(uint32_t);
break;
+ }
case FG_DOUBLE:
+ {
val = _out_message[i].offset +
_out_message[i].prop->getFloatValue() * _out_message[i].factor;
+ u64 tmpun64;
+ tmpun64.doubleVal = val;
- if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
- *((double*)&buf[length]) = val;
- } else {
- u64 tmpun64;
- tmpun64.doubleVal = val;
- *((uint64_t*)&buf[length]) = sg_bswap_64(tmpun64.longVal);
+ if (binary_byte_order != BYTE_ORDER_MATCHES_NETWORK_ORDER) {
+ tmpun64.longVal = sg_bswap_64(tmpun64.longVal);
}
- length += sizeof(int64_t);
+ memcpy(&buf[length], &tmpun64.longVal, sizeof(uint64_t));
+ length += sizeof(uint64_t);
break;
+ }
default: // SG_STRING
const char *strdata = _out_message[i].prop->getStringValue();
- int strlength = strlen(strdata);
+ int32_t strlength = strlen(strdata);
if (binary_byte_order == BYTE_ORDER_NEEDS_CONVERSION) {
SG_LOG( SG_IO, SG_ALERT, "Generic protocol: "
/* Format for strings is
* [length as int, 4 bytes][ASCII data, length bytes]
*/
- if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
- *((int32_t*)&buf[length]) = strlength;
- } else {
- *((int32_t*)&buf[length]) = sg_bswap_32(strlength);
+ if (binary_byte_order != BYTE_ORDER_MATCHES_NETWORK_ORDER) {
+ strlength = sg_bswap_32(strlength);
}
+ memcpy(&buf[length], &strlength, sizeof(int32_t));
length += sizeof(int32_t);
strncpy(&buf[length], strdata, strlength);
length += strlength;
}
if (binary_footer_type != FOOTER_NONE) {
- if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
- *((int32_t*)&buf[length]) = binary_footer_value;
- } else {
- *((int32_t*)&buf[length]) = sg_bswap_32(binary_footer_value);
+ int32_t intValue = binary_footer_value;
+ if (binary_byte_order != BYTE_ORDER_MATCHES_NETWORK_ORDER) {
+ intValue = sg_bswap_32(binary_footer_value);
}
+ memcpy(&buf[length], &intValue, sizeof(int32_t));
length += sizeof(int32_t);
}
}
}
-bool FGGeneric::parse_message_binary() {
+bool FGGeneric::parse_message_binary(int length) {
char *p2, *p1 = buf;
int32_t tmp32;
double val;
int i = -1;
- p2 = p1 + FG_MAX_MSG_SIZE;
+ p2 = p1 + length;
while ((++i < (int)_in_message.size()) && (p1 < p2)) {
switch (_in_message[i].type) {
return true;
}
-bool FGGeneric::parse_message_ascii() {
+bool FGGeneric::parse_message_ascii(int length) {
char *p2, *p1 = buf;
double val;
int i = -1;
+ int chunks = _in_message.size();
+ int line_separator_size = line_separator.size();
+
+ if (length < line_separator_size ||
+ line_separator.compare(buf + length - line_separator_size) != 0) {
- while ((++i < (int)_in_message.size()) &&
- p1 && strcmp(p1, line_separator.c_str())) {
+ SG_LOG(SG_IO, SG_WARN,
+ "Input line does not end with expected line separator." );
+ } else {
+ buf[length - line_separator_size] = 0;
+ }
+ while ((++i < chunks) && p1) {
p2 = strstr(p1, var_separator.c_str());
if (p2) {
*p2 = 0;
return true;
}
-bool FGGeneric::parse_message() {
+bool FGGeneric::parse_message(int length) {
if (binary_mode) {
- return parse_message_binary();
+ return parse_message_binary(length);
} else {
- return parse_message_ascii();
+ return parse_message_ascii(length);
}
}
set_enabled( true );
- if ( get_direction() == SG_IO_OUT && ! preamble.empty() ) {
+ if ( ((get_direction() == SG_IO_OUT )||
+ (get_direction() == SG_IO_BI))
+ && ! preamble.empty() ) {
if ( ! io->write( preamble.c_str(), preamble.size() ) ) {
SG_LOG( SG_IO, SG_WARN, "Error writing preamble." );
return false;
bool FGGeneric::process() {
SGIOChannel *io = get_io_channel();
- if ( get_direction() == SG_IO_OUT ) {
+ if ( (get_direction() == SG_IO_OUT) ||
+ (get_direction() == SG_IO_BI) ) {
gen_message();
if ( ! io->write( buf, length ) ) {
SG_LOG( SG_IO, SG_WARN, "Error writing data." );
goto error_out;
}
- } else if ( get_direction() == SG_IO_IN ) {
+ }
+
+ if (( get_direction() == SG_IO_IN ) ||
+ (get_direction() == SG_IO_BI) ) {
if ( io->get_type() == sgFileType ) {
if (!binary_mode) {
length = io->readline( buf, FG_MAX_MSG_SIZE );
if ( length > 0 ) {
- parse_message();
+ parse_message( length );
} else {
SG_LOG( SG_IO, SG_ALERT, "Error reading data." );
return false;
} else {
length = io->read( buf, binary_record_length );
if ( length == binary_record_length ) {
- parse_message();
+ parse_message( length );
} else {
SG_LOG( SG_IO, SG_ALERT,
"Generic protocol: Received binary "
} else {
if (!binary_mode) {
while ((length = io->readline( buf, FG_MAX_MSG_SIZE )) > 0 ) {
- parse_message();
+ parse_message( length );
}
} else {
while ((length = io->read( buf, binary_record_length ))
== binary_record_length ) {
- parse_message();
+ parse_message( length );
}
if ( length > 0 ) {
return true;
error_out:
if (exitOnError) {
- fgExit(1);
+ fgOSExit(1);
return true; // should not get there, but please the compiler
} else
return false;
bool FGGeneric::close() {
SGIOChannel *io = get_io_channel();
- if ( get_direction() == SG_IO_OUT && ! postamble.empty() ) {
+ if ( ((get_direction() == SG_IO_OUT)||
+ (get_direction() == SG_IO_BI))
+ && ! postamble.empty() ) {
if ( ! io->write( postamble.c_str(), postamble.size() ) ) {
SG_LOG( SG_IO, SG_ALERT, "Error writing postamble." );
return false;
SGPropertyNode root;
try {
readProperties(path.str(), &root);
- } catch (const sg_exception &) {
+ } catch (const sg_exception & ex) {
SG_LOG(SG_GENERAL, SG_ALERT,
- "Unable to load the protocol configuration file");
+ "Unable to load the protocol configuration file: " << ex.getFormattedMessage() );
return;
}
if (input) {
_in_message.clear();
read_config(input, _in_message);
+ if (!binary_mode && (line_separator.size() == 0 ||
+ *line_separator.rbegin() != '\n')) {
+
+ SG_LOG(SG_IO, SG_WARN,
+ "Warning: Appending newline to line separator in generic input.");
+ line_separator.push_back('\n');
+ }
}
}
}