* Add proper support for float and double values
* properly honour network byte order on little-endian and big-endian systems * various cleanups and bug-fixes
This commit is contained in:
parent
30e925bb38
commit
36f8519973
2 changed files with 114 additions and 52 deletions
|
@ -43,9 +43,18 @@
|
|||
|
||||
|
||||
|
||||
FGGeneric::FGGeneric(string& config) : exitOnError(false)
|
||||
FGGeneric::FGGeneric(vector<string> tokens) : exitOnError(false)
|
||||
{
|
||||
int configToken;
|
||||
if (tokens[1] == "socket") {
|
||||
configToken = 7;
|
||||
} else if (tokens[1] == "file") {
|
||||
configToken = 5;
|
||||
} else {
|
||||
configToken = 6;
|
||||
}
|
||||
|
||||
string config = tokens[ configToken ];
|
||||
string file = config+".xml";
|
||||
|
||||
SGPath path( globals->get_fg_root() );
|
||||
|
@ -57,19 +66,26 @@ FGGeneric::FGGeneric(string& config) : exitOnError(false)
|
|||
SGPropertyNode root;
|
||||
try {
|
||||
readProperties(path.str(), &root);
|
||||
} catch (const sg_exception &e) {
|
||||
} catch (const sg_exception &e) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
"Unable to load the protocol configuration file");
|
||||
return;
|
||||
}
|
||||
|
||||
SGPropertyNode *output = root.getNode("generic/output");
|
||||
if (output)
|
||||
read_config(output, _out_message);
|
||||
|
||||
SGPropertyNode *input = root.getNode("generic/input");
|
||||
if (input)
|
||||
read_config(input, _in_message);
|
||||
if (tokens[2] == "out") {
|
||||
SGPropertyNode *output = root.getNode("generic/output");
|
||||
if (output) {
|
||||
read_config(output, _out_message);
|
||||
}
|
||||
} else if (tokens[2] == "in") {
|
||||
SGPropertyNode *input = root.getNode("generic/input");
|
||||
if (input) {
|
||||
read_config(input, _in_message);
|
||||
}
|
||||
} else {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Unsuported protocol direction: "
|
||||
<< tokens[2]);
|
||||
}
|
||||
}
|
||||
|
||||
FGGeneric::~FGGeneric() {
|
||||
|
@ -83,7 +99,6 @@ bool FGGeneric::gen_message() {
|
|||
length = 0;
|
||||
|
||||
double val;
|
||||
|
||||
for (unsigned int i = 0; i < _out_message.size(); i++) {
|
||||
|
||||
if (i > 0 && !binary_mode)
|
||||
|
@ -94,13 +109,10 @@ bool FGGeneric::gen_message() {
|
|||
val = _out_message[i].offset +
|
||||
_out_message[i].prop->getIntValue() * _out_message[i].factor;
|
||||
if (binary_mode) {
|
||||
if (binary_byte_order == HOST_BYTE_ORDER) {
|
||||
if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
|
||||
*((int32_t*)&buf[length]) = (int32_t)val;
|
||||
} else {
|
||||
buf[length + 0] = (int8_t)((int32_t)val >> 24);
|
||||
buf[length + 1] = (int8_t)((int32_t)val >> 16);
|
||||
buf[length + 2] = (int8_t)((int32_t)val >> 8);
|
||||
buf[length + 3] = (int8_t)val;
|
||||
*((uint32_t*)&buf[length]) = sg_bswap_32((uint32_t)val);
|
||||
}
|
||||
length += sizeof(int32_t);
|
||||
} else {
|
||||
|
@ -112,7 +124,7 @@ bool FGGeneric::gen_message() {
|
|||
if (binary_mode) {
|
||||
*((int8_t*)&buf[length])
|
||||
= _out_message[i].prop->getBoolValue() ? true : false;
|
||||
length += sizeof(int8_t);
|
||||
length += 1;
|
||||
} else {
|
||||
snprintf(tmp, 255, _out_message[i].format.c_str(),
|
||||
_out_message[i].prop->getBoolValue());
|
||||
|
@ -124,13 +136,10 @@ bool FGGeneric::gen_message() {
|
|||
_out_message[i].prop->getFloatValue() * _out_message[i].factor;
|
||||
if (binary_mode) {
|
||||
int fixed = (int)(val * 65536.0f);
|
||||
if (binary_byte_order == HOST_BYTE_ORDER) {
|
||||
if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
|
||||
*((int32_t*)&buf[length]) = (int32_t)fixed;
|
||||
} else {
|
||||
buf[length + 0] = (int8_t)(fixed >> 24);
|
||||
buf[length + 1] = (int8_t)(fixed >> 16);
|
||||
buf[length + 2] = (int8_t)(fixed >> 8);
|
||||
buf[length + 3] = (int8_t)fixed;
|
||||
*((uint32_t*)&buf[length]) = sg_bswap_32((uint32_t)val);
|
||||
}
|
||||
length += sizeof(int32_t);
|
||||
} else {
|
||||
|
@ -138,18 +147,31 @@ bool FGGeneric::gen_message() {
|
|||
}
|
||||
break;
|
||||
|
||||
case FG_FLOAT:
|
||||
val = _out_message[i].offset +
|
||||
_out_message[i].prop->getFloatValue() * _out_message[i].factor;
|
||||
if (binary_mode) {
|
||||
if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
|
||||
*((float*)&buf[length]) = val;
|
||||
} else {
|
||||
*((float*)&buf[length]) = sg_bswap_32(*(uint32_t*)&val);
|
||||
}
|
||||
length += sizeof(int32_t);
|
||||
} else {
|
||||
snprintf(tmp, 255, _out_message[i].format.c_str(), (float)val);
|
||||
}
|
||||
break;
|
||||
|
||||
case FG_DOUBLE:
|
||||
val = _out_message[i].offset +
|
||||
_out_message[i].prop->getFloatValue() * _out_message[i].factor;
|
||||
if (binary_mode) {
|
||||
if (binary_byte_order == HOST_BYTE_ORDER) {
|
||||
if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
|
||||
*((double*)&buf[length]) = val;
|
||||
} else {
|
||||
SG_LOG( SG_IO, SG_ALERT, "Generic protocol: "
|
||||
"FG_DOUBLE will be written in host byte order.");
|
||||
*((double*)&buf[length]) = val;
|
||||
*((double*)&buf[length]) = sg_bswap_64(*(uint64_t*)&val);
|
||||
}
|
||||
length += sizeof(double);
|
||||
length += sizeof(int64_t);
|
||||
} else {
|
||||
snprintf(tmp, 255, _out_message[i].format.c_str(), (float)val);
|
||||
}
|
||||
|
@ -160,14 +182,18 @@ bool FGGeneric::gen_message() {
|
|||
const char *strdata = _out_message[i].prop->getStringValue();
|
||||
int strlength = strlen(strdata);
|
||||
|
||||
if (binary_byte_order == NETWORK_BYTE_ORDER) {
|
||||
if (binary_byte_order == BYTE_ORDER_NEEDS_CONVERSION) {
|
||||
SG_LOG( SG_IO, SG_ALERT, "Generic protocol: "
|
||||
"FG_STRING will be written in host byte order.");
|
||||
}
|
||||
/* Format for strings is
|
||||
* [length as int, 4 bytes][ASCII data, length bytes]
|
||||
*/
|
||||
*((int32_t*)&buf[length]) = strlength;
|
||||
if (binary_byte_order == BYTE_ORDER_MATCHES_NETWORK_ORDER) {
|
||||
*((int32_t*)&buf[length]) = strlength;
|
||||
} else {
|
||||
*((int32_t*)&buf[length]) = sg_bswap_32(strlength);
|
||||
}
|
||||
length += sizeof(int32_t);
|
||||
strncpy(&buf[length], strdata, strlength);
|
||||
length += strlength;
|
||||
|
@ -204,7 +230,11 @@ bool FGGeneric::gen_message() {
|
|||
break;
|
||||
}
|
||||
if (binary_footer_type != FOOTER_NONE) {
|
||||
*((int32_t*)&buf[length]) = binary_footer_value;
|
||||
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);
|
||||
}
|
||||
length += sizeof(int32_t);
|
||||
}
|
||||
}
|
||||
|
@ -216,7 +246,6 @@ bool FGGeneric::parse_message() {
|
|||
char *p2, *p1 = buf;
|
||||
double val;
|
||||
int i = -1;
|
||||
int tmp;
|
||||
|
||||
if (!binary_mode) {
|
||||
while ((++i < (int)_in_message.size()) &&
|
||||
|
@ -252,17 +281,15 @@ bool FGGeneric::parse_message() {
|
|||
}
|
||||
} else {
|
||||
/* Binary mode */
|
||||
int64_t tmp;
|
||||
|
||||
while ((++i < (int)_in_message.size()) &&
|
||||
(p1 - buf < FG_MAX_MSG_SIZE)) {
|
||||
|
||||
switch (_in_message[i].type) {
|
||||
case FG_INT:
|
||||
if (binary_byte_order == NETWORK_BYTE_ORDER) {
|
||||
tmp =
|
||||
(((p1[0]) & 0xff) << 24) |
|
||||
(((p1[1]) & 0xff) << 16) |
|
||||
(((p1[2]) & 0xff) << 8) |
|
||||
((p1[3]) & 0xff);
|
||||
if (binary_byte_order == BYTE_ORDER_NEEDS_CONVERSION) {
|
||||
tmp = sg_bswap_32(*(int32_t *)p1);
|
||||
} else {
|
||||
tmp = *(int32_t *)p1;
|
||||
}
|
||||
|
@ -274,17 +301,13 @@ bool FGGeneric::parse_message() {
|
|||
break;
|
||||
|
||||
case FG_BOOL:
|
||||
_in_message[i].prop->setBoolValue( p1[0] != 0.0 );
|
||||
_in_message[i].prop->setBoolValue( p1[0] != 0 );
|
||||
p1 += 1;
|
||||
break;
|
||||
|
||||
case FG_FIXED:
|
||||
if (binary_byte_order == NETWORK_BYTE_ORDER) {
|
||||
tmp =
|
||||
(((p1[0]) & 0xff) << 24) |
|
||||
(((p1[1]) & 0xff) << 16) |
|
||||
(((p1[2]) & 0xff) << 8) |
|
||||
((p1[3]) & 0xff);
|
||||
if (binary_byte_order == BYTE_ORDER_NEEDS_CONVERSION) {
|
||||
tmp = sg_bswap_32(*(int32_t *)p1);
|
||||
} else {
|
||||
tmp = *(int32_t *)p1;
|
||||
}
|
||||
|
@ -294,7 +317,30 @@ bool FGGeneric::parse_message() {
|
|||
p1 += sizeof(int32_t);
|
||||
break;
|
||||
|
||||
case FG_FLOAT:
|
||||
if (binary_byte_order == BYTE_ORDER_NEEDS_CONVERSION) {
|
||||
tmp = sg_bswap_32(*(int32_t *)p1);
|
||||
} else {
|
||||
tmp = *(int32_t *)p1;
|
||||
}
|
||||
val = _in_message[i].offset +
|
||||
*(float *)&tmp * _in_message[i].factor;
|
||||
_in_message[i].prop->setFloatValue(val);
|
||||
p1 += sizeof(int32_t);
|
||||
break;
|
||||
|
||||
case FG_DOUBLE:
|
||||
if (binary_byte_order == BYTE_ORDER_NEEDS_CONVERSION) {
|
||||
tmp = sg_bswap_64(*(int64_t *)p1);
|
||||
} else {
|
||||
tmp = *(int64_t *)p1;
|
||||
}
|
||||
val = _in_message[i].offset +
|
||||
*(double *)&tmp * _in_message[i].factor;
|
||||
_in_message[i].prop->setDoubleValue(val);
|
||||
p1 += sizeof(int64_t);
|
||||
break;
|
||||
|
||||
default: // SG_STRING
|
||||
SG_LOG( SG_IO, SG_ALERT, "Generic protocol: "
|
||||
"Ignoring unsupported binary input chunk type.");
|
||||
|
@ -358,7 +404,9 @@ bool FGGeneric::process() {
|
|||
if (length != binary_record_length) {
|
||||
SG_LOG( SG_IO, SG_ALERT,
|
||||
"Generic protocol: Received binary "
|
||||
"record of unexpected size." );
|
||||
"record of unexpected size, expected: "
|
||||
<< binary_record_length << "received: "
|
||||
<< length);
|
||||
} else {
|
||||
SG_LOG( SG_IO, SG_DEBUG,
|
||||
"Generic protocol: received record of " << length <<
|
||||
|
@ -452,7 +500,14 @@ FGGeneric::read_config(SGPropertyNode *root, vector<_serial_prot> &msg)
|
|||
} else {
|
||||
binary_footer_type = FOOTER_NONE; // default choice
|
||||
binary_record_length = -1; // default choice = sizeof(representation)
|
||||
binary_byte_order = HOST_BYTE_ORDER; // default choice
|
||||
|
||||
// default choice is network byte order (big endian)
|
||||
if (sgIsLittleEndian()) {
|
||||
binary_byte_order = BYTE_ORDER_NEEDS_CONVERSION;
|
||||
} else {
|
||||
binary_byte_order = BYTE_ORDER_MATCHES_NETWORK_ORDER;
|
||||
}
|
||||
|
||||
if ( root->hasValue("binary_footer") ) {
|
||||
string footer_type = root->getStringValue("binary_footer");
|
||||
if ( footer_type == "length" )
|
||||
|
@ -471,10 +526,14 @@ FGGeneric::read_config(SGPropertyNode *root, vector<_serial_prot> &msg)
|
|||
}
|
||||
if ( root->hasValue("byte_order") ) {
|
||||
string byte_order = root->getStringValue("byte_order");
|
||||
if ( byte_order == "network" ) {
|
||||
binary_byte_order = NETWORK_BYTE_ORDER;
|
||||
if (byte_order == "network" ) {
|
||||
if ( sgIsLittleEndian() ) {
|
||||
binary_byte_order = BYTE_ORDER_NEEDS_CONVERSION;
|
||||
} else {
|
||||
binary_byte_order = BYTE_ORDER_MATCHES_NETWORK_ORDER;
|
||||
}
|
||||
} else if ( byte_order == "host" ) {
|
||||
binary_byte_order = HOST_BYTE_ORDER;
|
||||
binary_byte_order = BYTE_ORDER_MATCHES_NETWORK_ORDER;
|
||||
} else {
|
||||
SG_LOG(SG_IO, SG_ALERT,
|
||||
"generic protocol: Undefined generic binary protocol"
|
||||
|
@ -502,8 +561,11 @@ FGGeneric::read_config(SGPropertyNode *root, vector<_serial_prot> &msg)
|
|||
chunk.type = FG_BOOL;
|
||||
record_length += 1;
|
||||
} else if (type == "float") {
|
||||
chunk.type = FG_FLOAT;
|
||||
record_length += sizeof(int32_t);
|
||||
} else if (type == "double") {
|
||||
chunk.type = FG_DOUBLE;
|
||||
record_length += sizeof(double);
|
||||
record_length += sizeof(int64_t);
|
||||
} else if (type == "fixed") {
|
||||
chunk.type = FG_FIXED;
|
||||
record_length += sizeof(int32_t);
|
||||
|
|
|
@ -38,7 +38,7 @@ class FGGeneric : public FGProtocol {
|
|||
|
||||
public:
|
||||
|
||||
FGGeneric(string&);
|
||||
FGGeneric(vector<string>);
|
||||
~FGGeneric();
|
||||
|
||||
bool gen_message();
|
||||
|
@ -57,7 +57,7 @@ public:
|
|||
bool getExitOnError() { return exitOnError; }
|
||||
protected:
|
||||
|
||||
enum e_type { FG_BOOL=0, FG_INT, FG_DOUBLE, FG_STRING, FG_FIXED };
|
||||
enum e_type { FG_BOOL=0, FG_INT, FG_FLOAT, FG_DOUBLE, FG_STRING, FG_FIXED };
|
||||
|
||||
typedef struct {
|
||||
// string name;
|
||||
|
@ -86,7 +86,7 @@ private:
|
|||
enum {FOOTER_NONE, FOOTER_LENGTH, FOOTER_MAGIC} binary_footer_type;
|
||||
int binary_footer_value;
|
||||
int binary_record_length;
|
||||
enum {NETWORK_BYTE_ORDER, HOST_BYTE_ORDER} binary_byte_order;
|
||||
enum {BYTE_ORDER_NEEDS_CONVERSION, BYTE_ORDER_MATCHES_NETWORK_ORDER} binary_byte_order;
|
||||
|
||||
void read_config(SGPropertyNode *root, vector<_serial_prot> &msg);
|
||||
bool exitOnError;
|
||||
|
|
Loading…
Reference in a new issue