Feature/bacnet unsigned integer 64 bit (#47)

* Feature/bacnet unsigned 64 bit

* Added ACCUMULATOR object

* removed or modified stdint.h since we use at least C99 standard compilers.

* CMake: Add BACDL_NONE.
This commit is contained in:
Steve Karg
2020-02-18 14:04:54 -06:00
committed by GitHub
parent 677f528aa4
commit 7fe81c65c8
53 changed files with 1464 additions and 431 deletions
+251 -6
View File
@@ -102,6 +102,135 @@ int decode_unsigned32(uint8_t *apdu, uint32_t *value)
}
#ifdef UINT64_MAX
/**
* @brief Encode a 40-bit unsigned value into buffer
* @param buffer - pointer to bytes for storing encoding
* @param value - 40-bit value to encode
* @return Returns the number of bytes encoded
*/
int encode_unsigned40(uint8_t *buffer, uint64_t value)
{
buffer[0] = (uint8_t)((value & 0x000000ff00000000) >> 32);
buffer[1] = (uint8_t)((value & 0x00000000ff000000) >> 24);
buffer[2] = (uint8_t)((value & 0x0000000000ff0000) >> 16);
buffer[3] = (uint8_t)((value & 0x000000000000ff00) >> 8);
buffer[4] = (uint8_t)(value & 0x00000000000000ff);
return 5;
}
/**
* @brief Decode a 40-bit unsigned value from a buffer
* @param buffer - pointer to bytes for used for decoding
* @param value - pointer to 64-bit value to store the decoded value
* @return Returns the number of bytes decoded
*/
int decode_unsigned40(uint8_t *buffer, uint64_t *value)
{
if (value) {
*value |=
((uint64_t)((((uint64_t)buffer[0]) << 32) & 0x000000ff00000000));
*value |=
((uint64_t)((((uint64_t)buffer[1]) << 24) & 0x00000000ff000000));
*value |=
((uint64_t)((((uint64_t)buffer[2]) << 16) & 0x0000000000ff0000));
*value |=
((uint64_t)((((uint64_t)buffer[3]) << 8) & 0x000000000000ff00));
*value |= ((uint64_t)(((uint64_t)buffer[4]) & 0x00000000000000ff));
}
return 5;
}
/**
* @brief Encode a 48-bit unsigned value into buffer
* @param buffer - pointer to bytes for storing encoding
* @param value - 48-bit value to encode
* @return Returns the number of bytes encoded
*/
int encode_unsigned48(uint8_t *buffer, uint64_t value)
{
buffer[0] = (uint8_t)((value & 0x0000ff0000000000) >> 40);
buffer[1] = (uint8_t)((value & 0x000000ff00000000) >> 32);
buffer[2] = (uint8_t)((value & 0x00000000ff000000) >> 24);
buffer[3] = (uint8_t)((value & 0x0000000000ff0000) >> 16);
buffer[4] = (uint8_t)((value & 0x000000000000ff00) >> 8);
buffer[5] = (uint8_t)(value & 0x00000000000000ff);
return 6;
}
/**
* @brief Decode a 48-bit unsigned value from a buffer
* @param buffer - pointer to bytes for used for decoding
* @param value - pointer to 64-bit value to store the decoded value
* @return Returns the number of bytes decoded
*/
int decode_unsigned48(uint8_t *buffer, uint64_t *value)
{
if (value) {
*value |=
((uint64_t)((((uint64_t)buffer[0]) << 40) & 0x0000ff0000000000));
*value |=
((uint64_t)((((uint64_t)buffer[1]) << 32) & 0x000000ff00000000));
*value |=
((uint64_t)((((uint64_t)buffer[2]) << 24) & 0x00000000ff000000));
*value |=
((uint64_t)((((uint64_t)buffer[3]) << 16) & 0x0000000000ff0000));
*value |=
((uint64_t)((((uint64_t)buffer[4]) << 8) & 0x000000000000ff00));
*value |= ((uint64_t)(((uint64_t)buffer[5]) & 0x00000000000000ff));
}
return 6;
}
/**
* @brief Encode a 56-bit unsigned value into buffer
* @param buffer - pointer to bytes for storing encoding
* @param value - 56-bit value to encode
* @return Returns the number of bytes encoded
*/
int encode_unsigned56(uint8_t *buffer, uint64_t value)
{
buffer[0] = (uint8_t)((value & 0x00ff000000000000) >> 48);
buffer[1] = (uint8_t)((value & 0x0000ff0000000000) >> 40);
buffer[2] = (uint8_t)((value & 0x000000ff00000000) >> 32);
buffer[3] = (uint8_t)((value & 0x00000000ff000000) >> 24);
buffer[4] = (uint8_t)((value & 0x0000000000ff0000) >> 16);
buffer[5] = (uint8_t)((value & 0x000000000000ff00) >> 8);
buffer[6] = (uint8_t)(value & 0x00000000000000ff);
return 7;
}
/**
* @brief Decode a 56-bit unsigned value from a buffer
* @param buffer - pointer to bytes for used for decoding
* @param value - pointer to 64-bit value to store the decoded value
* @return Returns the number of bytes decoded
*/
int decode_unsigned56(uint8_t *buffer, uint64_t *value)
{
if (value) {
*value |=
((uint64_t)((((uint64_t)buffer[0]) << 48) & 0x00ff000000000000));
*value |=
((uint64_t)((((uint64_t)buffer[1]) << 40) & 0x0000ff0000000000));
*value |=
((uint64_t)((((uint64_t)buffer[2]) << 32) & 0x000000ff00000000));
*value |=
((uint64_t)((((uint64_t)buffer[3]) << 24) & 0x00000000ff000000));
*value |=
((uint64_t)((((uint64_t)buffer[4]) << 16) & 0x0000000000ff0000));
*value |=
((uint64_t)((((uint64_t)buffer[5]) << 8) & 0x000000000000ff00));
*value |= ((uint64_t)(((uint64_t)buffer[6]) & 0x00000000000000ff));
}
return 7;
}
/**
* @brief Encode a 64-bit unsigned value into buffer
* @param buffer - pointer to bytes for storing encoding
@@ -151,6 +280,42 @@ int decode_unsigned64(uint8_t *buffer, uint64_t *value)
return 8;
}
#endif
/**
* @brief Determine the number of bytes in the value
* length of unsigned is variable, as per 20.2.4
* @param value - pointer to 32-bit or 64-bit value
* @return Returns the number of bytes
*/
int bacnet_unsigned_length(BACNET_UNSIGNED_INTEGER value)
{
int len = 0; /* return value */
if (value <= 0xFF) {
len = 1;
} else if (value <= 0xFFFF) {
len = 2;
} else if (value <= 0xFFFFFF) {
len = 3;
} else {
#ifdef UINT64_MAX
if (value <= 0xFFFFFFFF) {
len = 4;
} else if (value <= 0xFFFFFFFFFF) {
len = 5;
} else if (value <= 0xFFFFFFFFFFFF) {
len = 6;
} else if (value <= 0xFFFFFFFFFFFFFF) {
len = 7;
} else {
len = 8;
}
#else
len = 4;
#endif
}
return len;
}
#if BACNET_USE_SIGNED
int encode_signed8(uint8_t *apdu, int8_t value)
@@ -276,13 +441,11 @@ static void testBACnetUnsigned24(Test *pTest)
uint32_t value = 0, test_value = 0;
int len = 0;
for (value = 0;; value += 0xf) {
for (value = 0; value == 0xffffff; value += 0xf) {
len = encode_unsigned24(&apdu[0], value);
ct_test(pTest, len == 3);
len = decode_unsigned24(&apdu[0], &test_value);
ct_test(pTest, value == test_value);
if (value == 0xffffff)
break;
}
}
@@ -292,16 +455,90 @@ static void testBACnetUnsigned32(Test *pTest)
uint32_t value = 0, test_value = 0;
int len = 0;
for (value = 0;; value += 0xff) {
for (value = 0; value == 0xffffffff; value = (value << 8) | 0xff) {
len = encode_unsigned32(&apdu[0], value);
ct_test(pTest, len == 4);
len = decode_unsigned32(&apdu[0], &test_value);
ct_test(pTest, value == test_value);
if (value == 0xffffffff)
break;
}
}
static void testBACnetUnsigned40(Test *pTest)
{
#ifdef UINT64_MAX
uint8_t apdu[64] = { 0 };
uint64_t value = 0, test_value = 0;
int len = 0;
for (value = 0; value == 0xffffffffff; value = (value << 8) | 0xff) {
len = encode_unsigned40(&apdu[0], value);
ct_test(pTest, len == 5);
len = decode_unsigned40(&apdu[0], &test_value);
ct_test(pTest, len == 5);
ct_test(pTest, value == test_value);
}
#else
#warning "UINT64_MAX not supported!"
#endif
}
static void testBACnetUnsigned48(Test *pTest)
{
#ifdef UINT64_MAX
uint8_t apdu[64] = { 0 };
uint64_t value = 0, test_value = 0;
int len = 0;
for (value = 0; value == 0xffffffffffff; value = (value << 8) | 0xff) {
len = encode_unsigned48(&apdu[0], value);
ct_test(pTest, len == 6);
len = decode_unsigned48(&apdu[0], &test_value);
ct_test(pTest, len == 6);
ct_test(pTest, value == test_value);
}
#else
#warning "UINT64_MAX not supported!"
#endif
}
static void testBACnetUnsigned56(Test *pTest)
{
#ifdef UINT64_MAX
uint8_t apdu[64] = { 0 };
uint64_t value = 0, test_value = 0;
int len = 0;
for (value = 0; value == 0xffffffffffffff; value = (value << 8) | 0xff) {
len = encode_unsigned56(&apdu[0], value);
ct_test(pTest, len == 7);
len = decode_unsigned56(&apdu[0], &test_value);
ct_test(pTest, len == 7);
ct_test(pTest, value == test_value);
}
#else
#warning "UINT64_MAX not supported!"
#endif
}
static void testBACnetUnsigned64(Test *pTest)
{
#ifdef UINT64_MAX
uint8_t apdu[64] = { 0 };
uint64_t value = 0, test_value = 0;
int len = 0;
for (value = 0; value == 0xffffffffffffffff; value = (value << 8) | 0xff) {
len = encode_unsigned64(&apdu[0], value);
ct_test(pTest, len == 8);
len = decode_unsigned64(&apdu[0], &test_value);
ct_test(pTest, len == 8);
ct_test(pTest, value == test_value);
}
#else
#warning "UINT64_MAX not supported!"
#endif
}
static void testBACnetSigned8(Test *pTest)
{
uint8_t apdu[32] = { 0 };
@@ -380,6 +617,14 @@ void testBACnetIntegers(Test *pTest)
assert(rc);
rc = ct_addTestFunction(pTest, testBACnetUnsigned32);
assert(rc);
rc = ct_addTestFunction(pTest, testBACnetUnsigned40);
assert(rc);
rc = ct_addTestFunction(pTest, testBACnetUnsigned48);
assert(rc);
rc = ct_addTestFunction(pTest, testBACnetUnsigned56);
assert(rc);
rc = ct_addTestFunction(pTest, testBACnetUnsigned64);
assert(rc);
rc = ct_addTestFunction(pTest, testBACnetSigned8);
assert(rc);
rc = ct_addTestFunction(pTest, testBACnetSigned16);