Feature/comments and review (#102)
* Added comments. Replaced -1 with BACNET_STATUS_ERROR macro. * Added some DogyGen comments * Added missing return value check for booleans. * Check used bits against unused bits in bitstrings. * Added missing return value check for bitstrings. * Added sanity checks and comments. * Fixed implicit type conv warning. * Chose to keep simpler C function methods. Co-authored-by: Steve Karg <steve@kargs.net> Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
+385
-94
@@ -48,65 +48,105 @@
|
||||
#define BACNET_STRING_UTF8_VALIDATION 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize a bit string.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
*/
|
||||
void bitstring_init(BACNET_BIT_STRING *bit_string)
|
||||
{
|
||||
int i;
|
||||
|
||||
bit_string->bits_used = 0;
|
||||
for (i = 0; i < MAX_BITSTRING_BYTES; i++) {
|
||||
bit_string->value[i] = 0;
|
||||
if (bit_string) {
|
||||
bit_string->bits_used = 0;
|
||||
for (i = 0; i < MAX_BITSTRING_BYTES; i++) {
|
||||
bit_string->value[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bits in the bit string.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param bit_number Number of the bit [0..(MAX_BITSTRING_BYTES*8)-1]
|
||||
* @param value Value 0/1
|
||||
*/
|
||||
void bitstring_set_bit(
|
||||
BACNET_BIT_STRING *bit_string, uint8_t bit_number, bool value)
|
||||
{
|
||||
uint8_t byte_number = bit_number / 8;
|
||||
uint8_t bit_mask = 1;
|
||||
|
||||
if (byte_number < MAX_BITSTRING_BYTES) {
|
||||
/* set max bits used */
|
||||
if (bit_string->bits_used < (bit_number + 1)) {
|
||||
bit_string->bits_used = bit_number + 1;
|
||||
}
|
||||
bit_mask = bit_mask << (bit_number - (byte_number * 8));
|
||||
if (value) {
|
||||
bit_string->value[byte_number] |= bit_mask;
|
||||
} else {
|
||||
bit_string->value[byte_number] &= (~(bit_mask));
|
||||
if (bit_string) {
|
||||
if (byte_number < MAX_BITSTRING_BYTES) {
|
||||
/* set max bits used */
|
||||
if (bit_string->bits_used < (bit_number + 1)) {
|
||||
bit_string->bits_used = bit_number + 1;
|
||||
}
|
||||
bit_mask = bit_mask << (bit_number - (byte_number * 8));
|
||||
if (value) {
|
||||
bit_string->value[byte_number] |= bit_mask;
|
||||
} else {
|
||||
bit_string->value[byte_number] &= (~(bit_mask));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of a single bit
|
||||
* out of the bit string.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param bit_number Number of the bit [0..(MAX_BITSTRING_BYTES*8)-1]
|
||||
*
|
||||
* @return Value 0/1
|
||||
*/
|
||||
bool bitstring_bit(BACNET_BIT_STRING *bit_string, uint8_t bit_number)
|
||||
{
|
||||
bool value = false;
|
||||
uint8_t byte_number = bit_number / 8;
|
||||
uint8_t bit_mask = 1;
|
||||
|
||||
if (bit_number < (MAX_BITSTRING_BYTES * 8)) {
|
||||
bit_mask = bit_mask << (bit_number - (byte_number * 8));
|
||||
if (bit_string->value[byte_number] & bit_mask) {
|
||||
value = true;
|
||||
if (bit_string) {
|
||||
if (bit_number < (MAX_BITSTRING_BYTES * 8)) {
|
||||
bit_mask = bit_mask << (bit_number - (byte_number * 8));
|
||||
if (bit_string->value[byte_number] & bit_mask) {
|
||||
value = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of bits used.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
*
|
||||
* @return Bits used [0..(MAX_BITSTRING_BYTES*8)-1]
|
||||
*/
|
||||
uint8_t bitstring_bits_used(BACNET_BIT_STRING *bit_string)
|
||||
{
|
||||
return bit_string->bits_used;
|
||||
return (bit_string ? bit_string->bits_used : 0);
|
||||
}
|
||||
|
||||
/* returns the number of bytes that a bit string is using */
|
||||
/**
|
||||
* Returns the number of bytes that a bit string is using.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
*
|
||||
* @return Bytes used [0..MAX_BITSTRING_BYTES]
|
||||
*/
|
||||
uint8_t bitstring_bytes_used(BACNET_BIT_STRING *bit_string)
|
||||
{
|
||||
uint8_t len = 0; /* return value */
|
||||
uint8_t used_bytes = 0;
|
||||
uint8_t last_bit = 0;
|
||||
|
||||
if (bit_string->bits_used) {
|
||||
if (bit_string && bit_string->bits_used) {
|
||||
last_bit = bit_string->bits_used - 1;
|
||||
used_bytes = last_bit / 8;
|
||||
/* add one for the first byte */
|
||||
@@ -117,6 +157,14 @@ uint8_t bitstring_bytes_used(BACNET_BIT_STRING *bit_string)
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an octed at the given bit position.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param octet_index Byte index of the octed [0..MAX_BITSTRING_BYTES-1]
|
||||
*
|
||||
* @return Value of the octed.
|
||||
*/
|
||||
uint8_t bitstring_octet(BACNET_BIT_STRING *bit_string, uint8_t octet_index)
|
||||
{
|
||||
uint8_t octet = 0;
|
||||
@@ -130,6 +178,15 @@ uint8_t bitstring_octet(BACNET_BIT_STRING *bit_string, uint8_t octet_index)
|
||||
return octet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an octed at the given bit position.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param index Byte index of the octed [0..MAX_BITSTRING_BYTES-1]
|
||||
* @param octet Octet value
|
||||
*
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool bitstring_set_octet(
|
||||
BACNET_BIT_STRING *bit_string, uint8_t index, uint8_t octet)
|
||||
{
|
||||
@@ -145,13 +202,25 @@ bool bitstring_set_octet(
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the amount of bits used in the bit
|
||||
* string structure.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param bytes_used Count of bytes used.
|
||||
* @param unused_bits Count of remaining unused bits in
|
||||
* the last byte.
|
||||
*
|
||||
* @return true on success or false on error.
|
||||
*/
|
||||
bool bitstring_set_bits_used(
|
||||
BACNET_BIT_STRING *bit_string, uint8_t bytes_used, uint8_t unused_bits)
|
||||
BACNET_BIT_STRING * bit_string,
|
||||
uint8_t bytes_used,
|
||||
uint8_t unused_bits)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (bit_string) {
|
||||
/* FIXME: check that bytes_used is at least one? */
|
||||
if (bit_string && bytes_used) {
|
||||
bit_string->bits_used = bytes_used * 8;
|
||||
bit_string->bits_used -= unused_bits;
|
||||
status = true;
|
||||
@@ -160,6 +229,13 @@ bool bitstring_set_bits_used(
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the capcity of the bit string.
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
*
|
||||
* @return Capacitiy in bits [0..(MAX_BITSTRING_BYTES*8)]
|
||||
*/
|
||||
uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string)
|
||||
{
|
||||
if (bit_string) {
|
||||
@@ -169,6 +245,14 @@ uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy bits from one bit string to another.
|
||||
*
|
||||
* @param dest Pointer to the destination bit string structure.
|
||||
* @param src Pointer to the source bit string structure.
|
||||
*
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool bitstring_copy(BACNET_BIT_STRING *dest, BACNET_BIT_STRING *src)
|
||||
{
|
||||
unsigned i;
|
||||
@@ -185,25 +269,34 @@ bool bitstring_copy(BACNET_BIT_STRING *dest, BACNET_BIT_STRING *src)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* returns true if the same length and contents */
|
||||
/**
|
||||
* Returns true if the same length and contents.
|
||||
*
|
||||
* @param bitstring1 Pointer to the first bit string structure.
|
||||
* @param bitstring2 Pointer to the second bit string structure.
|
||||
*
|
||||
* @return true if the content of both bit strings are
|
||||
* the same, false otherwise.
|
||||
*/
|
||||
bool bitstring_same(
|
||||
BACNET_BIT_STRING *bitstring1, BACNET_BIT_STRING *bitstring2)
|
||||
{
|
||||
int i = 0; /* loop counter */
|
||||
int i; /* loop counter */
|
||||
int bytes_used = 0;
|
||||
uint8_t compare_mask = 0;
|
||||
|
||||
if (bitstring1 && bitstring2) {
|
||||
bytes_used = (int)(bitstring1->bits_used / 8);
|
||||
if ((bitstring1->bits_used == bitstring2->bits_used) &&
|
||||
(bitstring1->bits_used / 8 <= MAX_BITSTRING_BYTES)) {
|
||||
bytes_used = (int)(bitstring1->bits_used / 8);
|
||||
compare_mask = 0xFF >> (8 - (bitstring1->bits_used % 8));
|
||||
|
||||
(bytes_used <= MAX_BITSTRING_BYTES)) {
|
||||
/* compare fully used bytes */
|
||||
for (i = 0; i < bytes_used; i++) {
|
||||
if (bitstring1->value[i] != bitstring2->value[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* compare only the relevant bits of last partly used byte */
|
||||
compare_mask = 0xFF >> (8 - (bitstring1->bits_used % 8));
|
||||
if ((bitstring1->value[bytes_used] & compare_mask) !=
|
||||
(bitstring2->value[bytes_used] & compare_mask)) {
|
||||
return false;
|
||||
@@ -217,9 +310,18 @@ bool bitstring_same(
|
||||
}
|
||||
|
||||
#if PRINT_ENABLED
|
||||
/* converts an null terminated ASCII string to an bitstring.
|
||||
Expects "1,0,1,0,1,1" or "101011" as the bits
|
||||
returns true if successfully converted and fits; false if too long */
|
||||
/**
|
||||
* Converts an null terminated ASCII string to an bitstring.
|
||||
*
|
||||
* Expects "1,0,1,0,1,1" or "101011" as the bits
|
||||
*
|
||||
* @param bit_string Pointer to the bit string structure.
|
||||
* @param ascii Pointer to a zero terminated string, made up from
|
||||
* '0' and '1' like "010010011", that shall be
|
||||
* converted into a bit string.
|
||||
*
|
||||
* @return true if successfully converted and fits; false if too long.
|
||||
*/
|
||||
bool bitstring_init_ascii(BACNET_BIT_STRING *bit_string, const char *ascii)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
@@ -262,8 +364,19 @@ bool bitstring_init_ascii(BACNET_BIT_STRING *bit_string, const char *ascii)
|
||||
#endif
|
||||
|
||||
#define CHARACTER_STRING_CAPACITY (MAX_CHARACTER_STRING_BYTES - 1)
|
||||
/* returns false if the string exceeds capacity
|
||||
initialize by using value=NULL */
|
||||
/**
|
||||
* Initialize a BACnet characater string.
|
||||
* Returns false if the string exceeds capacity.
|
||||
* Initialize by using value=NULL
|
||||
*
|
||||
* @param char_string Pointer to the BACnet string
|
||||
* @param encoding Encoding that shall be used
|
||||
* like CHARACTER_UTF8
|
||||
* @param value C-string used to initialize the object
|
||||
* @param length C-String length in characters.
|
||||
*
|
||||
* @return true on success, false if the string exceeds capacity.
|
||||
*/
|
||||
bool characterstring_init(BACNET_CHARACTER_STRING *char_string,
|
||||
uint8_t encoding,
|
||||
const char *value,
|
||||
@@ -299,6 +412,17 @@ bool characterstring_init(BACNET_CHARACTER_STRING *char_string,
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a BACnet characater string.
|
||||
* Returns false if the string exceeds capacity.
|
||||
* Initialize by using value=NULL
|
||||
*
|
||||
* @param char_string Pointer to the BACnet string
|
||||
* @param value C-string used to initialize the object
|
||||
* @param tmax C-String length in characters.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool characterstring_init_ansi_safe(
|
||||
BACNET_CHARACTER_STRING *char_string, const char *value, size_t tmax)
|
||||
{
|
||||
@@ -306,6 +430,16 @@ bool characterstring_init_ansi_safe(
|
||||
value ? strnlen(value, tmax) : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a BACnet characater string.
|
||||
* Returns false if the string exceeds capacity.
|
||||
* Initialize by using value=NULL
|
||||
*
|
||||
* @param char_string Pointer to the BACnet string
|
||||
* @param value C-string used to initialize the object
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool characterstring_init_ansi(
|
||||
BACNET_CHARACTER_STRING *char_string, const char *value)
|
||||
{
|
||||
@@ -313,34 +447,64 @@ bool characterstring_init_ansi(
|
||||
char_string, CHARACTER_ANSI_X34, value, value ? strlen(value) : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a character string.
|
||||
*
|
||||
* @param dest Pointer to the destination string.
|
||||
* @param src Pointer to the source string.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool characterstring_copy(
|
||||
BACNET_CHARACTER_STRING *dest, BACNET_CHARACTER_STRING *src)
|
||||
{
|
||||
return characterstring_init(dest, characterstring_encoding(src),
|
||||
characterstring_value(src), characterstring_length(src));
|
||||
}
|
||||
|
||||
bool characterstring_ansi_copy(
|
||||
char *dest, size_t dest_max_len, BACNET_CHARACTER_STRING *src)
|
||||
{
|
||||
size_t i; /* counter */
|
||||
|
||||
if (dest && src && (src->encoding == CHARACTER_ANSI_X34) &&
|
||||
(src->length < dest_max_len)) {
|
||||
for (i = 0; i < dest_max_len; i++) {
|
||||
if (i < src->length) {
|
||||
dest[i] = src->value[i];
|
||||
} else {
|
||||
dest[i] = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (dest && src) {
|
||||
return characterstring_init(dest, characterstring_encoding(src),
|
||||
characterstring_value(src), characterstring_length(src));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* returns true if the character encoding and string contents are the same */
|
||||
/**
|
||||
* Copy a character string into a C-string.
|
||||
*
|
||||
* @param dest Pointer to the destination C-string buffer.
|
||||
* @param dest_max_len Size of the destination C-string buffer.
|
||||
* @param src Pointer to the source BACnet string.
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool characterstring_ansi_copy(
|
||||
char *dest, size_t dest_max_len, BACNET_CHARACTER_STRING *src)
|
||||
{
|
||||
size_t i; /* counter */
|
||||
|
||||
if (dest && src) {
|
||||
if ((src->encoding == CHARACTER_ANSI_X34) && (src->length < dest_max_len)) {
|
||||
for (i = 0; i < dest_max_len; i++) {
|
||||
if (i < src->length) {
|
||||
dest[i] = src->value[i];
|
||||
} else {
|
||||
dest[i] = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the character encoding and string
|
||||
* contents are the same.
|
||||
*
|
||||
* @param dest Pointer to the first string to test.
|
||||
* @param src Pointer to the second string to test.
|
||||
*
|
||||
* @return true if the character encoding and string contents are the same
|
||||
*/
|
||||
bool characterstring_same(
|
||||
BACNET_CHARACTER_STRING *dest, BACNET_CHARACTER_STRING *src)
|
||||
{
|
||||
@@ -348,12 +512,14 @@ bool characterstring_same(
|
||||
bool same_status = false;
|
||||
|
||||
if (src && dest) {
|
||||
if ((src->length == dest->length) &&
|
||||
(src->encoding == dest->encoding)) {
|
||||
if ((src->encoding == dest->encoding) &&
|
||||
(src->length == dest->length) &&
|
||||
(src->length <= MAX_CHARACTER_STRING_BYTES)) {
|
||||
same_status = true;
|
||||
for (i = 0; (i < src->length) && same_status; i++) {
|
||||
for (i = 0; i < src->length; i++) {
|
||||
if (src->value[i] != dest->value[i]) {
|
||||
same_status = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -370,18 +536,29 @@ bool characterstring_same(
|
||||
return same_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the BACnet string and the C-string
|
||||
* contents are the same.
|
||||
*
|
||||
* @param dest Pointer to the first string to test.
|
||||
* @param src Pointer to the second string to test.
|
||||
*
|
||||
* @return true if the character encoding and string contents are the same
|
||||
*/
|
||||
bool characterstring_ansi_same(BACNET_CHARACTER_STRING *dest, const char *src)
|
||||
{
|
||||
size_t i; /* counter */
|
||||
bool same_status = false;
|
||||
|
||||
if (src && dest) {
|
||||
if ((dest->length == strlen(src)) &&
|
||||
(dest->encoding == CHARACTER_ANSI_X34)) {
|
||||
if ((dest->encoding == CHARACTER_ANSI_X34) &&
|
||||
(dest->length == strlen(src)) &&
|
||||
(dest->length <= MAX_CHARACTER_STRING_BYTES)) {
|
||||
same_status = true;
|
||||
for (i = 0; (i < dest->length) && same_status; i++) {
|
||||
for (i = 0; i < dest->length; i++) {
|
||||
if (src[i] != dest->value[i]) {
|
||||
same_status = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,7 +577,18 @@ bool characterstring_ansi_same(BACNET_CHARACTER_STRING *dest, const char *src)
|
||||
return same_status;
|
||||
}
|
||||
|
||||
/* returns false if the string exceeds capacity */
|
||||
/**
|
||||
* Append some characters to the end of the characterstring
|
||||
*
|
||||
* @param char_string Pointer to the BACnet string to which
|
||||
* the content of the C-string shall be added.
|
||||
* @param value Pointer to the C-String to be added.
|
||||
* @param length Count of characters to add.
|
||||
*
|
||||
* @param src Pointer to the first string to test.
|
||||
*
|
||||
* @return false if the string exceeds capacity.
|
||||
*/
|
||||
bool characterstring_append(
|
||||
BACNET_CHARACTER_STRING *char_string, const char *value, size_t length)
|
||||
{
|
||||
@@ -420,9 +608,14 @@ bool characterstring_append(
|
||||
return status;
|
||||
}
|
||||
|
||||
/* This function sets a new length without changing the value.
|
||||
If length exceeds capacity, no modification happens and
|
||||
function returns false. */
|
||||
/**
|
||||
* @brief This function sets a new length without changing
|
||||
* the value. If length exceeds capacity, no modification
|
||||
* happens and function returns false.
|
||||
*
|
||||
* @return true on success, false if the string exceeds
|
||||
* capacity.
|
||||
*/
|
||||
bool characterstring_truncate(
|
||||
BACNET_CHARACTER_STRING *char_string, size_t length)
|
||||
{
|
||||
@@ -587,8 +780,8 @@ bool characterstring_printable(BACNET_CHARACTER_STRING *char_string)
|
||||
|
||||
#if BACNET_STRING_UTF8_VALIDATION
|
||||
/* Basic UTF-8 manipulation routines
|
||||
by Jeff Bezanson
|
||||
placed in the public domain Fall 2005 */
|
||||
* by Jeff Bezanson
|
||||
* placed in the public domain Fall 2005 */
|
||||
static const char trailingBytesForUTF8[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -601,19 +794,33 @@ static const char trailingBytesForUTF8[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 };
|
||||
|
||||
/* based on the valid_utf8 routine from the PCRE library by Philip Hazel
|
||||
length is in bytes, since without knowing whether the string is valid
|
||||
it's hard to know how many characters there are! */
|
||||
/**
|
||||
* @brief Based on the valid_utf8 routine from the PCRE library by Philip Hazel
|
||||
* length is in bytes, since without knowing whether the string is valid
|
||||
* it's hard to know how many characters there are!
|
||||
*
|
||||
* @param str Pointer to the character string.
|
||||
* @param length Count of bytes to check. The count of bytes
|
||||
* does not necessarily match the count of chars.
|
||||
*
|
||||
* @return true if the string is valid, false otherwise.
|
||||
*/
|
||||
bool utf8_isvalid(const char *str, size_t length)
|
||||
{
|
||||
const unsigned char *p, *pend = (unsigned char *)str + length;
|
||||
const unsigned char *p, *pend;
|
||||
unsigned char c;
|
||||
size_t ab;
|
||||
|
||||
/* empty string is valid */
|
||||
/* An empty string is valid. */
|
||||
if (length == 0) {
|
||||
return true;
|
||||
}
|
||||
/* Check pointer. */
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
/* Check characters. */
|
||||
pend = (unsigned char *) str + length;
|
||||
for (p = (const unsigned char *)str; p < pend; p++) {
|
||||
c = *p;
|
||||
/* null in middle of string */
|
||||
@@ -696,26 +903,45 @@ bool utf8_isvalid(const char *str, size_t length)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check if the character string is valid or not.
|
||||
*
|
||||
* @param char_string Pointer to the character string.
|
||||
*
|
||||
* @return true if the string is valid, false otherwise.
|
||||
*/
|
||||
bool characterstring_valid(BACNET_CHARACTER_STRING *char_string)
|
||||
{
|
||||
bool valid = false; /* return value */
|
||||
|
||||
if (char_string->encoding < MAX_CHARACTER_STRING_ENCODING) {
|
||||
if (char_string->encoding == CHARACTER_UTF8) {
|
||||
if (utf8_isvalid(char_string->value, char_string->length)) {
|
||||
if (char_string) {
|
||||
if (char_string->encoding < MAX_CHARACTER_STRING_ENCODING) {
|
||||
if (char_string->encoding == CHARACTER_UTF8) {
|
||||
/*UTF8 check*/
|
||||
if (utf8_isvalid(char_string->value, char_string->length)) {
|
||||
valid = true;
|
||||
}
|
||||
} else {
|
||||
/*non UTF8*/
|
||||
valid = true;
|
||||
}
|
||||
} else {
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
#if BACNET_USE_OCTETSTRING
|
||||
/* returns false if the string exceeds capacity
|
||||
initialize by using value=NULL */
|
||||
/**
|
||||
* @brief Initialize an octed string with the given bytes or
|
||||
* zeros, if NULL for the value is provided.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
* @param value Pointer to the bytes to be copied to the octed
|
||||
* string or NULL to initialize the octed string.
|
||||
* @param length Count of bytes used to fill the octed string.
|
||||
*
|
||||
* @return true on success, false if the string exceeds capacity.
|
||||
*/
|
||||
bool octetstring_init(
|
||||
BACNET_OCTET_STRING *octet_string, uint8_t *value, size_t length)
|
||||
{
|
||||
@@ -746,8 +972,12 @@ bool octetstring_init(
|
||||
}
|
||||
|
||||
#if PRINT_ENABLED
|
||||
/* converts an null terminated ASCII Hex string to an octet string.
|
||||
returns true if successfully converted and fits; false if too long */
|
||||
/** @brief Converts an null terminated ASCII Hex string to an octet string.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
* @param ascii_hex Pointer to the HEx-ASCII string.
|
||||
*
|
||||
* @return true if successfully converted and fits; false if too long */
|
||||
bool octetstring_init_ascii_hex(
|
||||
BACNET_OCTET_STRING *octet_string, const char *ascii_hex)
|
||||
{
|
||||
@@ -756,7 +986,7 @@ bool octetstring_init_ascii_hex(
|
||||
uint8_t value = 0;
|
||||
char hex_pair_string[3] = "";
|
||||
|
||||
if (octet_string) {
|
||||
if (octet_string && ascii_hex) {
|
||||
octet_string->length = 0;
|
||||
if (ascii_hex[0] == 0) {
|
||||
/* nothing to decode, so success! */
|
||||
@@ -793,14 +1023,31 @@ bool octetstring_init_ascii_hex(
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Copy an octed string from source to destination.
|
||||
*
|
||||
* @param dest Pointer to the destination octed string.
|
||||
* @param src Pointer to the source octed string.
|
||||
*
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool octetstring_copy(BACNET_OCTET_STRING *dest, BACNET_OCTET_STRING *src)
|
||||
{
|
||||
return octetstring_init(
|
||||
dest, octetstring_value(src), octetstring_length(src));
|
||||
}
|
||||
|
||||
/* returns the number of bytes copied, or 0 if the dest
|
||||
cannot hold entire octetstring value */
|
||||
/**
|
||||
* @brief Copy bytes from the octed string to a byte buffer.
|
||||
*
|
||||
* @param dest Pointer to the byte buffer.
|
||||
* @param length Bytes to be copied from the
|
||||
* octed string to the buffer.
|
||||
* @param src Pointer to the octed string.
|
||||
*
|
||||
* @return Returns the number of bytes copied, or 0 if
|
||||
* the dest cannot hold entire octetstring value.
|
||||
*/
|
||||
size_t octetstring_copy_value(
|
||||
uint8_t *dest, size_t length, BACNET_OCTET_STRING *src)
|
||||
{
|
||||
@@ -819,7 +1066,15 @@ size_t octetstring_copy_value(
|
||||
return bytes_copied;
|
||||
}
|
||||
|
||||
/* returns false if the string exceeds capacity */
|
||||
/**
|
||||
* @brief Append bytes to the end of the octed string.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
* @param value Pointer to the byte buffer to be appended.
|
||||
* @param length Bytes to be appended.
|
||||
*
|
||||
* @return false if the string exceeds capacity.
|
||||
*/
|
||||
bool octetstring_append(
|
||||
BACNET_OCTET_STRING *octet_string, uint8_t *value, size_t length)
|
||||
{
|
||||
@@ -839,9 +1094,16 @@ bool octetstring_append(
|
||||
return status;
|
||||
}
|
||||
|
||||
/* This function sets a new length without changing the value.
|
||||
If length exceeds capacity, no modification happens and
|
||||
function returns false. */
|
||||
/**
|
||||
* @brief This function sets a new length without changing the value.
|
||||
* If length exceeds capacity, no modification happens and the
|
||||
* function returns false.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
* @param length New length the octed string is trucated to.
|
||||
*
|
||||
* @return tur on success, false otherwise.
|
||||
*/
|
||||
bool octetstring_truncate(BACNET_OCTET_STRING *octet_string, size_t length)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
@@ -856,7 +1118,14 @@ bool octetstring_truncate(BACNET_OCTET_STRING *octet_string, size_t length)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* returns a pointer to the value. */
|
||||
/**
|
||||
* @brief Returns a pointer to the value (data) of
|
||||
* the given octed string.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
*
|
||||
* @return Value as a pointer to a byte array or NULL on error.
|
||||
*/
|
||||
uint8_t *octetstring_value(BACNET_OCTET_STRING *octet_string)
|
||||
{
|
||||
uint8_t *value = NULL;
|
||||
@@ -868,33 +1137,55 @@ uint8_t *octetstring_value(BACNET_OCTET_STRING *octet_string)
|
||||
return value;
|
||||
}
|
||||
|
||||
/* returns the length. */
|
||||
/**
|
||||
* @brief Returns the length in bytes of
|
||||
* the given octed string.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
*
|
||||
* @return Length in bytes. Returns always 0 on error.
|
||||
*/
|
||||
size_t octetstring_length(BACNET_OCTET_STRING *octet_string)
|
||||
{
|
||||
size_t length = 0;
|
||||
|
||||
if (octet_string) {
|
||||
/* FIXME: validate length is within bounds? */
|
||||
length = octet_string->length;
|
||||
/* Force length to be within bounds. */
|
||||
if (length > MAX_OCTET_STRING_BYTES) {
|
||||
length = MAX_OCTET_STRING_BYTES;
|
||||
}
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/* returns the maximum capacity. */
|
||||
/**
|
||||
* @brief Returns the maximum capacity of an octed string.
|
||||
*
|
||||
* @param octet_string Pointer to the octed string.
|
||||
*
|
||||
* @return Capacity in bytes. Returns always 0 on error.
|
||||
*/
|
||||
size_t octetstring_capacity(BACNET_OCTET_STRING *octet_string)
|
||||
{
|
||||
size_t length = 0;
|
||||
|
||||
if (octet_string) {
|
||||
/* FIXME: validate length is within bounds? */
|
||||
length = MAX_OCTET_STRING_BYTES;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/* returns true if the same length and contents */
|
||||
/**
|
||||
* @brief Returns true if the same length and contents.
|
||||
*
|
||||
* @param octet_string1 Pointer to the first octed string.
|
||||
* @param octet_string2 Pointer to the second octed string.
|
||||
*
|
||||
* @return true if the octed strings are the same, false otherwise.
|
||||
*/
|
||||
bool octetstring_value_same(
|
||||
BACNET_OCTET_STRING *octet_string1, BACNET_OCTET_STRING *octet_string2)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user