Files
bacnet_stack/src/bacnet/bacint.c
T
Kari Argillander f806c5829b Run clang-format and enable CI check for it (#755)
* pre-commit: Update and enable clang-format check

There is newer version from clang-format so use that. We do not yet want
18 as that is little bit too new.

* Format some thing by hand which clang-format "breaks"

Clang-format will format some things little bit off in some cases.
Format some things by hand so we get cleaner end result.

* Run clang-format with

```
pre-commit run --all-files clang-format
```

We have already in previously checked places where clang-format does not
make good format and ignored those (hopefully most of the things).

---------

Co-authored-by: Kari Argillander <kari.argillander@fidelix.com>
2024-08-30 11:20:58 -05:00

413 lines
10 KiB
C

/**
* @file
* @brief BACnet integer encode and decode helper functions
* @author Steve Karg <skarg@users.sourceforge.net>
* @date 2004
* @copyright SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
*/
#include <stdint.h>
#include <stdbool.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/bacint.h"
int encode_unsigned16(uint8_t *apdu, uint16_t value)
{
if (apdu) {
apdu[0] = (uint8_t)((value >> 8) & 0xFF);
apdu[1] = (uint8_t)((value >> 0) & 0xFF);
}
return 2;
}
int decode_unsigned16(const uint8_t *apdu, uint16_t *value)
{
if (apdu && value) {
*value = (uint16_t)apdu[0] << 8;
*value |= (uint16_t)apdu[1];
}
return 2;
}
int encode_unsigned24(uint8_t *apdu, uint32_t value)
{
if (apdu) {
apdu[0] = (uint8_t)((value >> 16) & 0xFF);
apdu[1] = (uint8_t)((value >> 8) & 0xFF);
apdu[2] = (uint8_t)((value >> 0) & 0xFF);
}
return 3;
}
int decode_unsigned24(const uint8_t *apdu, uint32_t *value)
{
if (apdu && value) {
*value = (uint32_t)apdu[0] << 16;
*value |= (uint32_t)apdu[1] << 8;
*value |= (uint32_t)apdu[2];
}
return 3;
}
int encode_unsigned32(uint8_t *apdu, uint32_t value)
{
if (apdu) {
apdu[0] = (uint8_t)((value >> 24) & 0xFF);
apdu[1] = (uint8_t)((value >> 16) & 0xFF);
apdu[2] = (uint8_t)((value >> 8) & 0xFF);
apdu[3] = (uint8_t)((value >> 0) & 0xFF);
}
return 4;
}
int decode_unsigned32(const uint8_t *apdu, uint32_t *value)
{
if (apdu && value) {
*value = (uint32_t)apdu[0] << 24;
*value |= (uint32_t)apdu[1] << 16;
*value |= (uint32_t)apdu[2] << 8;
*value |= (uint32_t)apdu[3];
}
return 4;
}
#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)
{
if (buffer) {
buffer[0] = (uint8_t)((value >> 32) & 0xFF);
buffer[1] = (uint8_t)((value >> 24) & 0xFF);
buffer[2] = (uint8_t)((value >> 16) & 0xFF);
buffer[3] = (uint8_t)((value >> 8) & 0xFF);
buffer[4] = (uint8_t)((value >> 0) & 0xFF);
}
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(const uint8_t *buffer, uint64_t *value)
{
if (buffer && value) {
*value = (uint64_t)buffer[0] << 32;
*value |= (uint64_t)buffer[1] << 24;
*value |= (uint64_t)buffer[2] << 16;
*value |= (uint64_t)buffer[3] << 8;
*value |= (uint64_t)buffer[4];
}
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)
{
if (buffer) {
buffer[0] = (uint8_t)((value >> 40) & 0xFF);
buffer[1] = (uint8_t)((value >> 32) & 0xFF);
buffer[2] = (uint8_t)((value >> 24) & 0xFF);
buffer[3] = (uint8_t)((value >> 16) & 0xFF);
buffer[4] = (uint8_t)((value >> 8) & 0xFF);
buffer[5] = (uint8_t)((value >> 0) & 0xFF);
}
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(const uint8_t *buffer, uint64_t *value)
{
if (buffer && value) {
*value = (uint64_t)buffer[0] << 40;
*value |= (uint64_t)buffer[1] << 32;
*value |= (uint64_t)buffer[2] << 24;
*value |= (uint64_t)buffer[3] << 16;
*value |= (uint64_t)buffer[4] << 8;
*value |= (uint64_t)buffer[5];
}
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)
{
if (buffer) {
buffer[0] = (uint8_t)((value >> 48) & 0xFF);
buffer[1] = (uint8_t)((value >> 40) & 0xFF);
buffer[2] = (uint8_t)((value >> 32) & 0xFF);
buffer[3] = (uint8_t)((value >> 24) & 0xFF);
buffer[4] = (uint8_t)((value >> 16) & 0xFF);
buffer[5] = (uint8_t)((value >> 8) & 0xFF);
buffer[6] = (uint8_t)((value >> 0) & 0xFF);
}
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(const uint8_t *buffer, uint64_t *value)
{
if (buffer && value) {
*value = (uint64_t)buffer[0] << 48;
*value |= (uint64_t)buffer[1] << 40;
*value |= (uint64_t)buffer[2] << 32;
*value |= (uint64_t)buffer[3] << 24;
*value |= (uint64_t)buffer[4] << 16;
*value |= (uint64_t)buffer[5] << 8;
*value |= (uint64_t)buffer[6];
}
return 7;
}
/**
* @brief Encode a 64-bit unsigned value into buffer
* @param buffer - pointer to bytes for storing encoding
* @param value - 16-bit value to encode
* @return Returns the number of bytes encoded
*/
int encode_unsigned64(uint8_t *buffer, uint64_t value)
{
if (buffer) {
buffer[0] = (uint8_t)((value >> 56) & 0xFF);
buffer[1] = (uint8_t)((value >> 48) & 0xFF);
buffer[2] = (uint8_t)((value >> 40) & 0xFF);
buffer[3] = (uint8_t)((value >> 32) & 0xFF);
buffer[4] = (uint8_t)((value >> 24) & 0xFF);
buffer[5] = (uint8_t)((value >> 16) & 0xFF);
buffer[6] = (uint8_t)((value >> 8) & 0xFF);
buffer[7] = (uint8_t)((value >> 0) & 0xFF);
}
return 8;
}
/**
* @brief Decode a 64-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_unsigned64(const uint8_t *buffer, uint64_t *value)
{
if (buffer && value) {
*value = (uint64_t)buffer[0] << 56;
*value |= (uint64_t)buffer[1] << 48;
*value |= (uint64_t)buffer[2] << 40;
*value |= (uint64_t)buffer[3] << 32;
*value |= (uint64_t)buffer[4] << 24;
*value |= (uint64_t)buffer[5] << 16;
*value |= (uint64_t)buffer[6] << 8;
*value |= (uint64_t)buffer[7];
}
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
/* Avoid ULL to be compatible with C89. */
value = value >> 32;
if (value == 0) {
len = 4;
} else if (value <= 0xFF) {
len = 5;
} else if (value <= 0xFFFF) {
len = 6;
} else if (value <= 0xFFFFFF) {
len = 7;
} else {
len = 8;
}
#else
len = 4;
#endif
}
return len;
}
#if BACNET_USE_SIGNED
int encode_signed8(uint8_t *apdu, int8_t value)
{
if (apdu) {
apdu[0] = (uint8_t)value;
}
return 1;
}
int decode_signed8(const uint8_t *apdu, int32_t *value)
{
if (apdu && value) {
/* negative - bit 7 is set */
if (apdu[0] & 0x80) {
*value = 0xFFFFFF00;
} else {
*value = 0;
}
*value |= (int32_t)apdu[0] & 0xFF;
}
return 1;
}
int encode_signed16(uint8_t *apdu, int16_t value)
{
if (apdu) {
apdu[0] = (uint8_t)((value >> 8) & 0xFF);
apdu[1] = (uint8_t)((value >> 0) & 0xFF);
}
return 2;
}
int decode_signed16(const uint8_t *apdu, int32_t *value)
{
if (apdu && value) {
/* negative - bit 7 is set */
if (apdu[0] & 0x80) {
*value = 0xFFFF0000;
} else {
*value = 0;
}
*value |= (int32_t)apdu[0] << 8;
*value |= (int32_t)apdu[1];
}
return 2;
}
int encode_signed24(uint8_t *apdu, int32_t value)
{
if (apdu) {
apdu[0] = (uint8_t)((value >> 16) & 0xFF);
apdu[1] = (uint8_t)((value >> 8) & 0xFF);
apdu[2] = (uint8_t)((value >> 0) & 0xFF);
}
return 3;
}
int decode_signed24(const uint8_t *apdu, int32_t *value)
{
if (apdu && value) {
/* negative - bit 7 is set */
if (apdu[0] & 0x80) {
*value = 0xFF000000;
} else {
*value = 0;
}
*value |= (int32_t)apdu[0] << 16;
*value |= (int32_t)apdu[1] << 8;
*value |= (int32_t)apdu[2];
}
return 3;
}
int encode_signed32(uint8_t *apdu, int32_t value)
{
if (apdu) {
apdu[0] = (uint8_t)((value >> 24) & 0xFF);
apdu[1] = (uint8_t)((value >> 16) & 0xFF);
apdu[2] = (uint8_t)((value >> 8) & 0xFF);
apdu[3] = (uint8_t)((value >> 0) & 0xFF);
}
return 4;
}
int decode_signed32(const uint8_t *apdu, int32_t *value)
{
if (apdu && value) {
*value = (int32_t)apdu[0] << 24;
*value |= (int32_t)apdu[1] << 16;
*value |= (int32_t)apdu[2] << 8;
*value |= (int32_t)apdu[3];
}
return 4;
}
/**
* @brief Determines the number of bytes used by a BACnet Signed Integer
* from clause 20.2.5 Encoding of an Signed Integer Value
* @param value - signed value
* @return number of bytes used by a BACnet Signed Integer
*/
int bacnet_signed_length(int32_t value)
{
int len;
if ((value >= -128) && (value < 128)) {
len = 1;
} else if ((value >= -32768) && (value < 32768)) {
len = 2;
} else if ((value >= -8388608) && (value < 8388608)) {
len = 3;
} else {
len = 4;
}
return len;
}
#endif