Moved encoding and decoding of integers out of bacdcode.c, and now relying on bacint.c. This should also help Feature Request 1532291 for reducing code size.
This commit is contained in:
+1
-446
@@ -39,6 +39,7 @@
|
|||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bits.h"
|
#include "bits.h"
|
||||||
#include "bacstr.h"
|
#include "bacstr.h"
|
||||||
|
#include "bacint.h"
|
||||||
|
|
||||||
/* NOTE: byte order plays a role in decoding multibyte values */
|
/* NOTE: byte order plays a role in decoding multibyte values */
|
||||||
/* http://www.unixpapa.com/incnote/byteorder.html */
|
/* http://www.unixpapa.com/incnote/byteorder.html */
|
||||||
@@ -188,347 +189,6 @@ int decode_max_apdu(uint8_t octet)
|
|||||||
return max_apdu;
|
return max_apdu;
|
||||||
}
|
}
|
||||||
|
|
||||||
int encode_unsigned16(uint8_t * apdu, uint16_t value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[2];
|
|
||||||
uint16_t value;
|
|
||||||
} short_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
short_data.value = value;
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
apdu[0] = short_data.byte[0];
|
|
||||||
apdu[1] = short_data.byte[1];
|
|
||||||
#else
|
|
||||||
apdu[0] = short_data.byte[1];
|
|
||||||
apdu[1] = short_data.byte[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int decode_unsigned16(uint8_t * apdu, uint16_t * value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[2];
|
|
||||||
uint16_t value;
|
|
||||||
} short_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
short_data.byte[0] = apdu[0];
|
|
||||||
short_data.byte[1] = apdu[1];
|
|
||||||
#else
|
|
||||||
short_data.byte[1] = apdu[0];
|
|
||||||
short_data.byte[0] = apdu[1];
|
|
||||||
#endif
|
|
||||||
if (value)
|
|
||||||
*value = short_data.value;
|
|
||||||
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int encode_unsigned24(uint8_t * apdu, uint32_t value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
uint32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
long_data.value = value;
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
apdu[0] = long_data.byte[1];
|
|
||||||
apdu[1] = long_data.byte[2];
|
|
||||||
apdu[2] = long_data.byte[3];
|
|
||||||
#else
|
|
||||||
apdu[0] = long_data.byte[2];
|
|
||||||
apdu[1] = long_data.byte[1];
|
|
||||||
apdu[2] = long_data.byte[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
int decode_unsigned24(uint8_t * apdu, uint32_t * value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
uint32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
long_data.byte[1] = apdu[0];
|
|
||||||
long_data.byte[2] = apdu[1];
|
|
||||||
long_data.byte[3] = apdu[2];
|
|
||||||
#else
|
|
||||||
long_data.byte[2] = apdu[0];
|
|
||||||
long_data.byte[1] = apdu[1];
|
|
||||||
long_data.byte[0] = apdu[2];
|
|
||||||
#endif
|
|
||||||
if (value)
|
|
||||||
*value = long_data.value;
|
|
||||||
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
int encode_unsigned32(uint8_t * apdu, uint32_t value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
uint32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
long_data.value = value;
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
apdu[0] = long_data.byte[0];
|
|
||||||
apdu[1] = long_data.byte[1];
|
|
||||||
apdu[2] = long_data.byte[2];
|
|
||||||
apdu[3] = long_data.byte[3];
|
|
||||||
#else
|
|
||||||
apdu[0] = long_data.byte[3];
|
|
||||||
apdu[1] = long_data.byte[2];
|
|
||||||
apdu[2] = long_data.byte[1];
|
|
||||||
apdu[3] = long_data.byte[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
int decode_unsigned32(uint8_t * apdu, uint32_t * value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
uint32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
long_data.byte[0] = apdu[0];
|
|
||||||
long_data.byte[1] = apdu[1];
|
|
||||||
long_data.byte[2] = apdu[2];
|
|
||||||
long_data.byte[3] = apdu[3];
|
|
||||||
#else
|
|
||||||
long_data.byte[3] = apdu[0];
|
|
||||||
long_data.byte[2] = apdu[1];
|
|
||||||
long_data.byte[1] = apdu[2];
|
|
||||||
long_data.byte[0] = apdu[3];
|
|
||||||
#endif
|
|
||||||
if (value)
|
|
||||||
*value = long_data.value;
|
|
||||||
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* returns the number of APDU octets used */
|
|
||||||
int encode_signed8(uint8_t * apdu, int8_t value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte;
|
|
||||||
int8_t value;
|
|
||||||
} byte_data = {
|
|
||||||
0};
|
|
||||||
|
|
||||||
byte_data.value = value;
|
|
||||||
apdu[0] = byte_data.byte;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* returns the number of APDU octets consumed */
|
|
||||||
int decode_signed8(uint8_t * apdu, int32_t * value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
int32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
/* negative - bit 7 is set */
|
|
||||||
if (apdu[0] & 0x80) {
|
|
||||||
long_data.byte[0] = 0xFF;
|
|
||||||
long_data.byte[1] = 0xFF;
|
|
||||||
long_data.byte[2] = 0xFF;
|
|
||||||
}
|
|
||||||
/* fill in the rest */
|
|
||||||
long_data.byte[3] = apdu[0];
|
|
||||||
#else
|
|
||||||
/* negative - bit 7 is set */
|
|
||||||
if (apdu[0] & 0x80) {
|
|
||||||
long_data.byte[3] = 0xFF;
|
|
||||||
long_data.byte[2] = 0xFF;
|
|
||||||
long_data.byte[1] = 0xFF;
|
|
||||||
}
|
|
||||||
/* fill in the rest */
|
|
||||||
long_data.byte[0] = apdu[0];
|
|
||||||
#endif
|
|
||||||
if (value)
|
|
||||||
*value = long_data.value;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* returns the number of APDU octets used */
|
|
||||||
int encode_signed16(uint8_t * apdu, int16_t value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[2];
|
|
||||||
int16_t value;
|
|
||||||
} short_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
short_data.value = value;
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
apdu[0] = short_data.byte[0];
|
|
||||||
apdu[1] = short_data.byte[1];
|
|
||||||
#else
|
|
||||||
apdu[0] = short_data.byte[1];
|
|
||||||
apdu[1] = short_data.byte[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* returns the number of APDU octets consumed */
|
|
||||||
int decode_signed16(uint8_t * apdu, int32_t * value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
int32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
/* negative - bit 7 is set */
|
|
||||||
if (apdu[0] & 0x80) {
|
|
||||||
long_data.byte[0] = 0xFF;
|
|
||||||
long_data.byte[1] = 0xFF;
|
|
||||||
}
|
|
||||||
/* fill in the rest */
|
|
||||||
long_data.byte[2] = apdu[0];
|
|
||||||
long_data.byte[3] = apdu[1];
|
|
||||||
#else
|
|
||||||
/* negative - bit 7 is set */
|
|
||||||
if (apdu[0] & 0x80) {
|
|
||||||
long_data.byte[3] = 0xFF;
|
|
||||||
long_data.byte[2] = 0xFF;
|
|
||||||
}
|
|
||||||
/* fill in the rest */
|
|
||||||
long_data.byte[1] = apdu[0];
|
|
||||||
long_data.byte[0] = apdu[1];
|
|
||||||
#endif
|
|
||||||
if (value)
|
|
||||||
*value = long_data.value;
|
|
||||||
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int encode_signed24(uint8_t * apdu, int32_t value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
int32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
long_data.value = value;
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
apdu[0] = long_data.byte[1];
|
|
||||||
apdu[1] = long_data.byte[2];
|
|
||||||
apdu[2] = long_data.byte[3];
|
|
||||||
#else
|
|
||||||
apdu[0] = long_data.byte[2];
|
|
||||||
apdu[1] = long_data.byte[1];
|
|
||||||
apdu[2] = long_data.byte[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
int decode_signed24(uint8_t * apdu, int32_t * value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
int32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
/* negative - bit 7 is set */
|
|
||||||
if (apdu[0] & 0x80)
|
|
||||||
long_data.byte[0] = 0xFF;
|
|
||||||
/* fill in the rest */
|
|
||||||
long_data.byte[1] = apdu[0];
|
|
||||||
long_data.byte[2] = apdu[1];
|
|
||||||
long_data.byte[3] = apdu[2];
|
|
||||||
#else
|
|
||||||
/* negative - bit 7 is set */
|
|
||||||
if (apdu[0] & 0x80)
|
|
||||||
long_data.byte[3] = 0xFF;
|
|
||||||
/* fill in the rest */
|
|
||||||
long_data.byte[2] = apdu[0];
|
|
||||||
long_data.byte[1] = apdu[1];
|
|
||||||
long_data.byte[0] = apdu[2];
|
|
||||||
#endif
|
|
||||||
if (value)
|
|
||||||
*value = long_data.value;
|
|
||||||
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
int encode_signed32(uint8_t * apdu, int32_t value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
int32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
long_data.value = value;
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
apdu[0] = long_data.byte[0];
|
|
||||||
apdu[1] = long_data.byte[1];
|
|
||||||
apdu[2] = long_data.byte[2];
|
|
||||||
apdu[3] = long_data.byte[3];
|
|
||||||
#else
|
|
||||||
apdu[0] = long_data.byte[3];
|
|
||||||
apdu[1] = long_data.byte[2];
|
|
||||||
apdu[2] = long_data.byte[1];
|
|
||||||
apdu[3] = long_data.byte[0];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
int decode_signed32(uint8_t * apdu, int32_t * value)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
uint8_t byte[4];
|
|
||||||
int32_t value;
|
|
||||||
} long_data = { {
|
|
||||||
0}};
|
|
||||||
|
|
||||||
#if BIG_ENDIAN
|
|
||||||
long_data.byte[0] = apdu[0];
|
|
||||||
long_data.byte[1] = apdu[1];
|
|
||||||
long_data.byte[2] = apdu[2];
|
|
||||||
long_data.byte[3] = apdu[3];
|
|
||||||
#else
|
|
||||||
long_data.byte[3] = apdu[0];
|
|
||||||
long_data.byte[2] = apdu[1];
|
|
||||||
long_data.byte[1] = apdu[2];
|
|
||||||
long_data.byte[0] = apdu[3];
|
|
||||||
#endif
|
|
||||||
if (value)
|
|
||||||
*value = long_data.value;
|
|
||||||
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* from clause 20.2.1 General Rules for Encoding BACnet Tags */
|
/* from clause 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_tag(uint8_t * apdu, uint8_t tag_number, bool context_specific,
|
int encode_tag(uint8_t * apdu, uint8_t tag_number, bool context_specific,
|
||||||
@@ -1227,27 +887,6 @@ int decode_character_string(uint8_t * apdu, uint32_t len_value,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
|
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
|
||||||
/* returns the number of apdu bytes consumed */
|
|
||||||
int encode_bacnet_unsigned(uint8_t * apdu, uint32_t value)
|
|
||||||
{
|
|
||||||
int len = 0; /* return value */
|
|
||||||
|
|
||||||
if (value < 0x100) {
|
|
||||||
apdu[0] = (uint8_t) value;
|
|
||||||
len = 1;
|
|
||||||
} else if (value < 0x10000) {
|
|
||||||
len = encode_unsigned16(&apdu[0], (uint16_t) value);
|
|
||||||
} else if (value < 0x1000000) {
|
|
||||||
len = encode_unsigned24(&apdu[0], value);
|
|
||||||
} else {
|
|
||||||
len = encode_unsigned32(&apdu[0], value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
|
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
@@ -1279,37 +918,6 @@ int encode_tagged_unsigned(uint8_t * apdu, uint32_t value)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
|
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
|
||||||
/* returns the number of apdu bytes consumed */
|
|
||||||
int decode_unsigned(uint8_t * apdu, uint32_t len_value, uint32_t * value)
|
|
||||||
{
|
|
||||||
uint16_t unsigned16_value = 0;
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
switch (len_value) {
|
|
||||||
case 1:
|
|
||||||
*value = apdu[0];
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
decode_unsigned16(&apdu[0], &unsigned16_value);
|
|
||||||
*value = unsigned16_value;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
decode_unsigned24(&apdu[0], value);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
decode_unsigned32(&apdu[0], value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*value = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return len_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* from clause 20.2.11 Encoding of an Enumerated Value */
|
/* from clause 20.2.11 Encoding of an Enumerated Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
@@ -1366,59 +974,6 @@ int encode_context_enumerated(uint8_t * apdu, int tag_number, int value)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* from clause 20.2.5 Encoding of a Signed Integer Value */
|
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
|
||||||
/* returns the number of apdu bytes consumed */
|
|
||||||
int decode_signed(uint8_t * apdu, uint32_t len_value, int32_t * value)
|
|
||||||
{
|
|
||||||
if (value) {
|
|
||||||
switch (len_value) {
|
|
||||||
case 1:
|
|
||||||
decode_signed8(&apdu[0], value);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
decode_signed16(&apdu[0], value);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
decode_signed24(&apdu[0], value);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
decode_signed32(&apdu[0], value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*value = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return len_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* from clause 20.2.5 Encoding of a Signed Integer Value */
|
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
|
||||||
/* returns the number of apdu bytes consumed */
|
|
||||||
int encode_bacnet_signed(uint8_t * apdu, int32_t value)
|
|
||||||
{
|
|
||||||
int len = 0; /* return value */
|
|
||||||
|
|
||||||
/* don't encode the leading X'FF' or X'00' of the two's compliment.
|
|
||||||
That is, the first octet of any multi-octet encoded value shall
|
|
||||||
not be X'00' if the most significant bit (bit 7) of the second
|
|
||||||
octet is 0, and the first octet shall not be X'FF' if the most
|
|
||||||
significant bit of the second octet is 1. */
|
|
||||||
if ((value >= -128) && (value < 128)) {
|
|
||||||
len = encode_signed8(&apdu[0], (int8_t) value);
|
|
||||||
} else if ((value >= -32768) && (value < 32768)) {
|
|
||||||
len = encode_signed16(&apdu[0], (int16_t) value);
|
|
||||||
} else if ((value > -8388608) && (value < 8388608)) {
|
|
||||||
len = encode_signed24(&apdu[0], value);
|
|
||||||
} else {
|
|
||||||
len = encode_signed32(&apdu[0], value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* from clause 20.2.5 Encoding of a Signed Integer Value */
|
/* from clause 20.2.5 Encoding of a Signed Integer Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
|
|||||||
@@ -541,7 +541,6 @@ void testBACnetUnsigned(Test * pTest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST_BACINT
|
#ifdef TEST_BACINT
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
@@ -576,5 +575,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_DECODE */
|
#endif /* TEST_BACINT */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|||||||
Reference in New Issue
Block a user