Safer IEEE754 conversion.
The conversion given assumed two things: 1. the pointer was either 32-bit aligned or that unaligned word access was safe. (Not the case on ARM) We avoid this by using memcpy to copy to a buffer that *is* 32-bit-word-aligned. 2. the word was in native-endian format. The original code appeared to assume the given word would be in big-endian format (aka "network" byte order), so we convert it to the host's native format before casting. We re-instate the original implementation, controlled by a compiler switch to allow easy rollback if problems are encountered.
This commit is contained in:
@ -12,6 +12,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include "mbus-protocol.h"
|
#include "mbus-protocol.h"
|
||||||
|
|
||||||
@ -648,8 +649,52 @@ mbus_data_int_encode(unsigned char *int_data, size_t int_data_size, int value)
|
|||||||
float
|
float
|
||||||
mbus_data_float_decode(unsigned char *float_data)
|
mbus_data_float_decode(unsigned char *float_data)
|
||||||
{
|
{
|
||||||
|
#ifdef _HAS_NON_IEEE754_FLOAT
|
||||||
|
float val = 0.0f;
|
||||||
|
long temp = 0, fraction;
|
||||||
|
int sign,exponent;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (float_data)
|
if (float_data)
|
||||||
return *(float *) float_data;
|
{
|
||||||
|
for (i = 4; i > 0; i--)
|
||||||
|
{
|
||||||
|
temp = (temp << 8) + float_data[i-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// first bit = sign bit
|
||||||
|
sign = (temp >> 31) ? -1 : 1;
|
||||||
|
|
||||||
|
// decode 8 bit exponent
|
||||||
|
exponent = ((temp & 0x7F800000) >> 23) - 127;
|
||||||
|
|
||||||
|
// decode explicit 23 bit fraction
|
||||||
|
fraction = temp & 0x007FFFFF;
|
||||||
|
|
||||||
|
if ((exponent != -127) &&
|
||||||
|
(exponent != 128))
|
||||||
|
{
|
||||||
|
// normalized value, add bit 24
|
||||||
|
fraction |= 0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate float value
|
||||||
|
val = (float) sign * fraction * pow(2.0f, -23.0f + exponent);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (float_data)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
uint32_t u32;
|
||||||
|
float f;
|
||||||
|
} data;
|
||||||
|
memcpy(&(data.u32), float_data, sizeof(uint32_t));
|
||||||
|
data.u32 = ntohl(data.u32);
|
||||||
|
return data.f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return -1.0f;
|
return -1.0f;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user