Feature/octetstring value and length api (#1264)
* feat: add octetstring_length_value_same function for length and content comparison * feat: add tests for characterstring UTF-8 validation * feat: add tests for octetstring_init_ascii_epics validation * feat: add test for bacnet_strdup string duplication validation * feat: add utf8_isvalid test cases * feat: add octet string value API for present-value octet-string value and length, and out-of-service properties
This commit is contained in:
+37
-13
@@ -1324,7 +1324,38 @@ size_t octetstring_capacity(const BACNET_OCTET_STRING *octet_string)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the same length and contents.
|
||||
* @brief Returns true if the same length and value contents.
|
||||
*
|
||||
* @param octet_string1 Pointer to the first octet string.
|
||||
* @param length Length of the second octet string.
|
||||
* @param value Pointer to the value of the second octet string.
|
||||
*
|
||||
* @return true if the octet strings are the same, false otherwise.
|
||||
*/
|
||||
bool octetstring_length_value_same(
|
||||
const BACNET_OCTET_STRING *octet_string1,
|
||||
size_t length,
|
||||
const uint8_t *value)
|
||||
{
|
||||
size_t i = 0; /* loop counter */
|
||||
|
||||
if (octet_string1 && value) {
|
||||
if ((octet_string1->length == length) &&
|
||||
(octet_string1->length <= MAX_OCTET_STRING_BYTES)) {
|
||||
for (i = 0; i < octet_string1->length; i++) {
|
||||
if (octet_string1->value[i] != value[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the same length and value contents.
|
||||
*
|
||||
* @param octet_string1 Pointer to the first octet string.
|
||||
* @param octet_string2 Pointer to the second octet string.
|
||||
@@ -1335,21 +1366,14 @@ bool octetstring_value_same(
|
||||
const BACNET_OCTET_STRING *octet_string1,
|
||||
const BACNET_OCTET_STRING *octet_string2)
|
||||
{
|
||||
size_t i = 0; /* loop counter */
|
||||
bool status = false;
|
||||
|
||||
if (octet_string1 && octet_string2) {
|
||||
if ((octet_string1->length == octet_string2->length) &&
|
||||
(octet_string1->length <= MAX_OCTET_STRING_BYTES)) {
|
||||
for (i = 0; i < octet_string1->length; i++) {
|
||||
if (octet_string1->value[i] != octet_string2->value[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (octet_string2) {
|
||||
status = octetstring_length_value_same(
|
||||
octet_string1, octet_string2->length, octet_string2->value);
|
||||
}
|
||||
|
||||
return false;
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+5
-1
@@ -173,7 +173,11 @@ BACNET_STACK_EXPORT
|
||||
size_t octetstring_length(const BACNET_OCTET_STRING *octet_string);
|
||||
BACNET_STACK_EXPORT
|
||||
size_t octetstring_capacity(const BACNET_OCTET_STRING *octet_string);
|
||||
/* returns true if the same length and contents */
|
||||
BACNET_STACK_EXPORT
|
||||
bool octetstring_length_value_same(
|
||||
const BACNET_OCTET_STRING *octet_string1,
|
||||
size_t length,
|
||||
const uint8_t *value);
|
||||
BACNET_STACK_EXPORT
|
||||
bool octetstring_value_same(
|
||||
const BACNET_OCTET_STRING *octet_string1,
|
||||
|
||||
+118
-34
@@ -21,6 +21,13 @@
|
||||
#include "bacnet/basic/sys/keylist.h"
|
||||
#include "bacnet/basic/object/osv.h"
|
||||
|
||||
typedef struct octetstring_value_descr {
|
||||
unsigned Event_State : 3;
|
||||
bool Out_Of_Service;
|
||||
BACNET_OCTET_STRING Present_Value;
|
||||
const char *Object_Name;
|
||||
} OCTETSTRING_VALUE_DESCR;
|
||||
|
||||
/* Key List for storing object data sorted by instance number */
|
||||
static OS_Keylist Object_List = NULL;
|
||||
|
||||
@@ -237,22 +244,77 @@ bool OctetString_Value_Present_Value_Set(
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the present value length for an Octet String Value object.
|
||||
* @param object_instance Object instance number.
|
||||
* @param value Pointer to octet string value.
|
||||
* @param length Length of the octet string value.
|
||||
* @param priority Write priority (1..16).
|
||||
* @return true if values are within range and present value length is set.
|
||||
*/
|
||||
bool OctetString_Value_Present_Value_Length_Set(
|
||||
uint32_t object_instance, uint8_t *value, size_t length, uint8_t priority)
|
||||
{
|
||||
OCTETSTRING_VALUE_DESCR *pObject = NULL;
|
||||
bool status = false;
|
||||
|
||||
(void)priority;
|
||||
pObject = OctetString_Value_Object(object_instance);
|
||||
if (pObject) {
|
||||
status = octetstring_init(&pObject->Present_Value, value, length);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the present value for an Octet String Value object.
|
||||
* @param object_instance Object instance number.
|
||||
* @return Pointer to present value, or NULL if object does not exist.
|
||||
* @param value Pointer to octet string structure to receive the value.
|
||||
* @return true if object exists and value is returned.
|
||||
*/
|
||||
BACNET_OCTET_STRING *OctetString_Value_Present_Value(uint32_t object_instance)
|
||||
bool OctetString_Value_Present_Value_Get(
|
||||
uint32_t object_instance, BACNET_OCTET_STRING *value)
|
||||
{
|
||||
BACNET_OCTET_STRING *value = NULL;
|
||||
OCTETSTRING_VALUE_DESCR *pObject = NULL;
|
||||
bool status = false;
|
||||
|
||||
pObject = OctetString_Value_Object(object_instance);
|
||||
if (pObject) {
|
||||
value = &pObject->Present_Value;
|
||||
status = octetstring_copy(value, &pObject->Present_Value);
|
||||
}
|
||||
|
||||
return value;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the present value length for an Octet String Value object.
|
||||
* @param object_instance Object instance number.
|
||||
* @param value Pointer to buffer to receive octet string value.
|
||||
* @param value_size Size of the value buffer.
|
||||
* @param length Pointer to receive length of the octet string value.
|
||||
* @return true if object exists and value length is returned.
|
||||
*/
|
||||
bool OctetString_Value_Present_Value_Length(
|
||||
uint32_t object_instance, uint8_t *value, size_t value_size, size_t *length)
|
||||
{
|
||||
OCTETSTRING_VALUE_DESCR *pObject = NULL;
|
||||
size_t value_length = 0;
|
||||
bool status = false;
|
||||
|
||||
pObject = OctetString_Value_Object(object_instance);
|
||||
if (pObject) {
|
||||
value_length = octetstring_length(&pObject->Present_Value);
|
||||
if (length) {
|
||||
*length = value_length;
|
||||
}
|
||||
if (value && (value_size >= value_length)) {
|
||||
memcpy(value, pObject->Present_Value.value, value_length);
|
||||
}
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,6 +385,47 @@ const char *OctetString_Value_Name_ASCII(uint32_t object_instance)
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given object instance-number, returns the out-of-service
|
||||
* property value
|
||||
*
|
||||
* @param object_instance - object-instance number of the object
|
||||
*
|
||||
* @return out-of-service property value
|
||||
*/
|
||||
bool OctetString_Value_Out_Of_Service(uint32_t object_instance)
|
||||
{
|
||||
bool value = false;
|
||||
OCTETSTRING_VALUE_DESCR *pObject;
|
||||
|
||||
pObject = OctetString_Value_Object(object_instance);
|
||||
if (pObject) {
|
||||
value = pObject->Out_Of_Service;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given object instance-number, sets the out-of-service property value
|
||||
*
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param value - boolean out-of-service value
|
||||
*
|
||||
* @return true if the out-of-service property value was set
|
||||
*/
|
||||
bool OctetString_Value_Out_Of_Service_Set(uint32_t object_instance, bool value)
|
||||
{
|
||||
OCTETSTRING_VALUE_DESCR *pObject;
|
||||
|
||||
pObject = OctetString_Value_Object(object_instance);
|
||||
if (pObject) {
|
||||
pObject->Out_Of_Service = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encodes a read-property response for an Octet String Value object.
|
||||
* @param rpdata Read property request/response context.
|
||||
@@ -331,27 +434,17 @@ const char *OctetString_Value_Name_ASCII(uint32_t object_instance)
|
||||
int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
BACNET_OCTET_STRING *real_value = NULL;
|
||||
BACNET_BIT_STRING bit_string = { 0 };
|
||||
BACNET_CHARACTER_STRING char_string = { 0 };
|
||||
BACNET_OCTET_STRING octet_value = { 0 };
|
||||
bool state = false;
|
||||
uint8_t *apdu = NULL;
|
||||
OCTETSTRING_VALUE_DESCR *pObject = NULL;
|
||||
|
||||
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
|
||||
(rpdata->application_data_len == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
apdu = rpdata->application_data;
|
||||
|
||||
pObject = OctetString_Value_Object(rpdata->object_instance);
|
||||
if (!pObject) {
|
||||
rpdata->error_class = ERROR_CLASS_OBJECT;
|
||||
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len = encode_application_object_id(
|
||||
@@ -372,9 +465,9 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
break;
|
||||
|
||||
case PROP_PRESENT_VALUE:
|
||||
real_value =
|
||||
OctetString_Value_Present_Value(rpdata->object_instance);
|
||||
apdu_len = encode_application_octet_string(&apdu[0], real_value);
|
||||
OctetString_Value_Present_Value_Get(
|
||||
rpdata->object_instance, &octet_value);
|
||||
apdu_len = encode_application_octet_string(&apdu[0], &octet_value);
|
||||
break;
|
||||
|
||||
case PROP_STATUS_FLAGS:
|
||||
@@ -384,7 +477,7 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(
|
||||
&bit_string, STATUS_FLAG_OUT_OF_SERVICE,
|
||||
pObject->Out_Of_Service);
|
||||
OctetString_Value_Out_Of_Service(rpdata->object_instance));
|
||||
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
@@ -395,7 +488,7 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
break;
|
||||
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
state = pObject->Out_Of_Service;
|
||||
state = OctetString_Value_Out_Of_Service(rpdata->object_instance);
|
||||
apdu_len = encode_application_boolean(&apdu[0], state);
|
||||
break;
|
||||
default:
|
||||
@@ -418,7 +511,6 @@ bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value = { 0 };
|
||||
OCTETSTRING_VALUE_DESCR *pObject = NULL;
|
||||
|
||||
if (wp_data == NULL) {
|
||||
return false;
|
||||
@@ -426,24 +518,15 @@ bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
if (wp_data->application_data_len == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* decode the some of the request */
|
||||
len = bacapp_decode_application_data(
|
||||
wp_data->application_data, wp_data->application_data_len, &value);
|
||||
/* FIXME: len < application_data_len: more data? */
|
||||
if (len < 0) {
|
||||
/* error while decoding - a value larger than we can handle */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
return false;
|
||||
}
|
||||
pObject = OctetString_Value_Object(wp_data->object_instance);
|
||||
if (!pObject) {
|
||||
wp_data->error_class = ERROR_CLASS_OBJECT;
|
||||
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (wp_data->object_property) {
|
||||
case PROP_PRESENT_VALUE:
|
||||
status = write_property_type_valid(
|
||||
@@ -473,7 +556,8 @@ bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
status = write_property_type_valid(
|
||||
wp_data, &value, BACNET_APPLICATION_TAG_BOOLEAN);
|
||||
if (status) {
|
||||
pObject->Out_Of_Service = value.type.Boolean;
|
||||
OctetString_Value_Out_Of_Service_Set(
|
||||
wp_data->object_instance, value.type.Boolean);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -20,13 +20,6 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct octetstring_value_descr {
|
||||
unsigned Event_State : 3;
|
||||
bool Out_Of_Service;
|
||||
BACNET_OCTET_STRING Present_Value;
|
||||
const char *Object_Name;
|
||||
} OCTETSTRING_VALUE_DESCR;
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void OctetString_Value_Property_Lists(
|
||||
const int32_t **pRequired,
|
||||
@@ -65,8 +58,22 @@ bool OctetString_Value_Present_Value_Set(
|
||||
const BACNET_OCTET_STRING *value,
|
||||
uint8_t priority);
|
||||
BACNET_STACK_EXPORT
|
||||
bool OctetString_Value_Present_Value_Get(
|
||||
uint32_t object_instance, BACNET_OCTET_STRING *value);
|
||||
BACNET_STACK_DEPRECATED("Use OctetString_Value_Present_Value_Get() instead")
|
||||
BACNET_STACK_EXPORT
|
||||
BACNET_OCTET_STRING *OctetString_Value_Present_Value(uint32_t object_instance);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool OctetString_Value_Present_Value_Length_Set(
|
||||
uint32_t object_instance, uint8_t *value, size_t length, uint8_t priority);
|
||||
BACNET_STACK_EXPORT
|
||||
bool OctetString_Value_Present_Value_Length(
|
||||
uint32_t object_instance,
|
||||
uint8_t *value,
|
||||
size_t value_size,
|
||||
size_t *length);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool OctetString_Value_Change_Of_Value(uint32_t instance);
|
||||
BACNET_STACK_EXPORT
|
||||
@@ -83,7 +90,7 @@ bool OctetString_Value_Description_Set(uint32_t instance, const char *new_name);
|
||||
BACNET_STACK_EXPORT
|
||||
bool OctetString_Value_Out_Of_Service(uint32_t instance);
|
||||
BACNET_STACK_EXPORT
|
||||
void OctetString_Value_Out_Of_Service_Set(uint32_t instance, bool oos_flag);
|
||||
bool OctetString_Value_Out_Of_Service_Set(uint32_t instance, bool oos_flag);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
uint32_t OctetString_Value_Create(uint32_t object_instance);
|
||||
|
||||
Reference in New Issue
Block a user