Refactor/snprintf next common shift function (#656)

This commit is contained in:
Steve Karg
2024-05-30 09:16:05 -05:00
committed by GitHub
parent 309964e929
commit 0cbf7414a4
5 changed files with 277 additions and 446 deletions
+54 -267
View File
@@ -1864,6 +1864,31 @@ int bacapp_data_len(
return total_len; return total_len;
} }
/**
* @brief Shift the buffer pointer and decrease the size after an snprintf
* @param len - number of bytes (excluding terminating NULL byte) from snprintf
* @param buf - pointer to the buffer pointer
* @param buf_size - pointer to the buffer size
* @return number of bytes (excluding terminating NULL byte) from snprintf
*/
int bacapp_snprintf_shift(int len, char **buf, size_t *buf_size)
{
if (buf) {
if (*buf) {
*buf += len;
}
}
if (buf_size) {
if ((*buf_size) >= len) {
*buf_size -= len;
} else {
*buf_size = 0;
}
}
return len;
}
#if defined(BACAPP_DATE) #if defined(BACAPP_DATE)
/** /**
* @brief Print a date value to a string for EPICS * @brief Print a date value to a string for EPICS
@@ -1891,29 +1916,13 @@ static int bacapp_snprintf_date(char *str, size_t str_len, BACNET_DATE *bdate)
/* cppcheck-suppress nullPointer */ /* cppcheck-suppress nullPointer */
/* cppcheck-suppress ctunullpointer */ /* cppcheck-suppress ctunullpointer */
slen = snprintf(str, str_len, "%s, %s", weekday_text, month_text); slen = snprintf(str, str_len, "%s, %s", weekday_text, month_text);
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
if (bdate->day == 255) { if (bdate->day == 255) {
slen = snprintf(str, str_len, " (unspecified), "); slen = snprintf(str, str_len, " (unspecified), ");
} else { } else {
slen = snprintf(str, str_len, " %u, ", (unsigned)bdate->day); slen = snprintf(str, str_len, " %u, ", (unsigned)bdate->day);
} }
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
if (bdate->year == 2155) { if (bdate->year == 2155) {
slen = snprintf(str, str_len, "(unspecified)"); slen = snprintf(str, str_len, "(unspecified)");
} else { } else {
@@ -1949,43 +1958,19 @@ static int bacapp_snprintf_time(char *str, size_t str_len, BACNET_TIME *btime)
/* cppcheck-suppress nullPointer */ /* cppcheck-suppress nullPointer */
slen = snprintf(str, str_len, "%02u:", (unsigned)btime->hour); slen = snprintf(str, str_len, "%02u:", (unsigned)btime->hour);
} }
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
if (btime->min == 255) { if (btime->min == 255) {
slen = snprintf(str, str_len, "**:"); slen = snprintf(str, str_len, "**:");
} else { } else {
slen = snprintf(str, str_len, "%02u:", (unsigned)btime->min); slen = snprintf(str, str_len, "%02u:", (unsigned)btime->min);
} }
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
if (btime->sec == 255) { if (btime->sec == 255) {
slen = snprintf(str, str_len, "**."); slen = snprintf(str, str_len, "**.");
} else { } else {
slen = snprintf(str, str_len, "%02u.", (unsigned)btime->sec); slen = snprintf(str, str_len, "%02u.", (unsigned)btime->sec);
} }
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
if (btime->hundredths == 255) { if (btime->hundredths == 255) {
slen = snprintf(str, str_len, "**"); slen = snprintf(str, str_len, "**");
} else { } else {
@@ -2043,16 +2028,7 @@ static int bacapp_snprintf_weeklyschedule(char *str,
slen = snprintf( slen = snprintf(
str, str_len, "(%s; ", bactext_application_tag_name(inner_tag)); str, str_len, "(%s; ", bactext_application_tag_name(inner_tag));
} }
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
for (wi = 0; wi < loopend; wi++) { for (wi = 0; wi < loopend; wi++) {
BACNET_DAILY_SCHEDULE *ds = &ws->weeklySchedule[wi]; BACNET_DAILY_SCHEDULE *ds = &ws->weeklySchedule[wi];
if (arrayIndex == BACNET_ARRAY_ALL) { if (arrayIndex == BACNET_ARRAY_ALL) {
@@ -2063,81 +2039,28 @@ static int bacapp_snprintf_weeklyschedule(char *str,
? weekdaynames[arrayIndex - 1] ? weekdaynames[arrayIndex - 1]
: "???"); : "???");
} }
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
for (ti = 0; ti < ds->TV_Count; ti++) { for (ti = 0; ti < ds->TV_Count; ti++) {
slen = slen =
bacapp_snprintf_time(str, str_len, &ds->Time_Values[ti].Time); bacapp_snprintf_time(str, str_len, &ds->Time_Values[ti].Time);
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
}
slen = snprintf(str, str_len, " "); slen = snprintf(str, str_len, " ");
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
bacnet_primitive_to_application_data_value( bacnet_primitive_to_application_data_value(
&dummyDataValue, &ds->Time_Values[ti].Value); &dummyDataValue, &ds->Time_Values[ti].Value);
dummyPropValue.value = &dummyDataValue; dummyPropValue.value = &dummyDataValue;
dummyPropValue.object_property = PROP_PRESENT_VALUE; dummyPropValue.object_property = PROP_PRESENT_VALUE;
dummyPropValue.object_type = OBJECT_SCHEDULE; dummyPropValue.object_type = OBJECT_SCHEDULE;
slen = bacapp_snprintf_value(str, str_len, &dummyPropValue); slen = bacapp_snprintf_value(str, str_len, &dummyPropValue);
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
if (ti < ds->TV_Count - 1) { if (ti < ds->TV_Count - 1) {
slen = snprintf(str, str_len, ", "); slen = snprintf(str, str_len, ", ");
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
} }
} }
if (wi < loopend - 1) { if (wi < loopend - 1) {
slen = snprintf(str, str_len, "]; "); slen = snprintf(str, str_len, "]; ");
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
} }
} }
slen = snprintf(str, str_len, "])"); slen = snprintf(str, str_len, "])");
@@ -2219,16 +2142,8 @@ int bacapp_snprintf_value(
octet_str = octetstring_value(&value->type.Octet_String); octet_str = octetstring_value(&value->type.Octet_String);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
slen = snprintf(str, str_len, "%02X", *octet_str); slen = snprintf(str, str_len, "%02X", *octet_str);
ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
octet_str++; octet_str++;
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
} }
} }
break; break;
@@ -2238,15 +2153,7 @@ int bacapp_snprintf_value(
len = characterstring_length(&value->type.Character_String); len = characterstring_length(&value->type.Character_String);
char_str = characterstring_value(&value->type.Character_String); char_str = characterstring_value(&value->type.Character_String);
slen = snprintf(str, str_len, "\""); slen = snprintf(str, str_len, "\"");
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
#if (__STDC_VERSION__ >= 199901L) && defined(__STDC_ISO_10646__) #if (__STDC_VERSION__ >= 199901L) && defined(__STDC_ISO_10646__)
if (characterstring_encoding(&value->type.Character_String) == if (characterstring_encoding(&value->type.Character_String) ==
CHARACTER_UTF8) { CHARACTER_UTF8) {
@@ -2266,15 +2173,7 @@ int bacapp_snprintf_value(
} }
/* For portability, cast wchar_t to wint_t */ /* For portability, cast wchar_t to wint_t */
slen = snprintf(str, str_len, "%lc", (wint_t)wc); slen = snprintf(str, str_len, "%lc", (wint_t)wc);
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
if (len > wclen) { if (len > wclen) {
len -= wclen; len -= wclen;
char_str += wclen; char_str += wclen;
@@ -2291,15 +2190,7 @@ int bacapp_snprintf_value(
} else { } else {
slen = snprintf(str, str_len, "%c", '.'); slen = snprintf(str, str_len, "%c", '.');
} }
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
char_str++; char_str++;
} }
} }
@@ -2311,39 +2202,15 @@ int bacapp_snprintf_value(
case BACNET_APPLICATION_TAG_BIT_STRING: case BACNET_APPLICATION_TAG_BIT_STRING:
len = bitstring_bits_used(&value->type.Bit_String); len = bitstring_bits_used(&value->type.Bit_String);
slen = snprintf(str, str_len, "{"); slen = snprintf(str, str_len, "{");
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
bool bit; bool bit;
bit = bitstring_bit(&value->type.Bit_String, (uint8_t)i); bit = bitstring_bit(&value->type.Bit_String, (uint8_t)i);
slen = snprintf(str, str_len, "%s", bit ? "true" : "false"); slen = snprintf(str, str_len, "%s", bit ? "true" : "false");
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
if (i < (len - 1)) { if (i < (len - 1)) {
slen = snprintf(str, str_len, ","); slen = snprintf(str, str_len, ",");
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
} }
} }
slen = snprintf(str, str_len, "}"); slen = snprintf(str, str_len, "}");
@@ -2464,15 +2331,7 @@ int bacapp_snprintf_value(
#if defined(BACAPP_OBJECT_ID) #if defined(BACAPP_OBJECT_ID)
case BACNET_APPLICATION_TAG_OBJECT_ID: case BACNET_APPLICATION_TAG_OBJECT_ID:
slen = snprintf(str, str_len, "("); slen = snprintf(str, str_len, "(");
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
if (value->type.Object_Id.type <= BACNET_OBJECT_TYPE_LAST) { if (value->type.Object_Id.type <= BACNET_OBJECT_TYPE_LAST) {
slen = snprintf(str, str_len, "%s, ", slen = snprintf(str, str_len, "%s, ",
bactext_object_type_name(value->type.Object_Id.type)); bactext_object_type_name(value->type.Object_Id.type));
@@ -2484,15 +2343,7 @@ int bacapp_snprintf_value(
slen = snprintf(str, str_len, "proprietary %u, ", slen = snprintf(str, str_len, "proprietary %u, ",
(unsigned)value->type.Object_Id.type); (unsigned)value->type.Object_Id.type);
} }
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
ret_val += slen;
slen = snprintf(str, str_len, "%lu)", slen = snprintf(str, str_len, "%lu)",
(unsigned long)value->type.Object_Id.instance); (unsigned long)value->type.Object_Id.instance);
ret_val += slen; ret_val += slen;
@@ -2502,25 +2353,9 @@ int bacapp_snprintf_value(
case BACNET_APPLICATION_TAG_DATERANGE: case BACNET_APPLICATION_TAG_DATERANGE:
slen = bacapp_snprintf_date( slen = bacapp_snprintf_date(
str, str_len, &value->type.Date_Range.startdate); str, str_len, &value->type.Date_Range.startdate);
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
slen = snprintf(str, str_len, ".."); slen = snprintf(str, str_len, "..");
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
slen = bacapp_snprintf_date( slen = bacapp_snprintf_date(
str, str_len, &value->type.Date_Range.enddate); str, str_len, &value->type.Date_Range.enddate);
ret_val += slen; ret_val += slen;
@@ -2537,25 +2372,9 @@ int bacapp_snprintf_value(
case BACNET_APPLICATION_TAG_DATETIME: case BACNET_APPLICATION_TAG_DATETIME:
slen = bacapp_snprintf_date( slen = bacapp_snprintf_date(
str, str_len, &value->type.Date_Time.date); str, str_len, &value->type.Date_Time.date);
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
slen = snprintf(str, str_len, "-"); slen = snprintf(str, str_len, "-");
ret_val += slen; ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
if (str) {
str += slen;
}
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
slen = bacapp_snprintf_time( slen = bacapp_snprintf_time(
str, str_len, &value->type.Date_Time.time); str, str_len, &value->type.Date_Time.time);
ret_val += slen; ret_val += slen;
@@ -2578,27 +2397,11 @@ int bacapp_snprintf_value(
case BACNET_APPLICATION_TAG_COLOR_COMMAND: case BACNET_APPLICATION_TAG_COLOR_COMMAND:
/* BACnetColorCommand */ /* BACnetColorCommand */
slen = snprintf(str, str_len, "("); slen = snprintf(str, str_len, "(");
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
}
ret_val += slen;
slen = snprintf(str, str_len, "%s", slen = snprintf(str, str_len, "%s",
bactext_color_operation_name( bactext_color_operation_name(
value->type.Color_Command.operation)); value->type.Color_Command.operation));
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
}
ret_val += slen;
/* FIXME: add the Lighting Command optional values */ /* FIXME: add the Lighting Command optional values */
slen = snprintf(str, str_len, ")"); slen = snprintf(str, str_len, ")");
ret_val += slen; ret_val += slen;
@@ -2641,31 +2444,15 @@ int bacapp_snprintf_value(
len = characterstring_length(name); len = characterstring_length(name);
char_str = characterstring_value(name); char_str = characterstring_value(name);
slen = snprintf(str, str_len, "\""); slen = snprintf(str, str_len, "\"");
if (str) { ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
str += slen;
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
}
ret_val += slen;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (isprint(*((unsigned char *)char_str))) { if (isprint(*((unsigned char *)char_str))) {
slen = snprintf(str, str_len, "%c", *char_str); slen = snprintf(str, str_len, "%c", *char_str);
} else { } else {
slen = snprintf(str, str_len, "%c", '.'); slen = snprintf(str, str_len, "%c", '.');
} }
ret_val += bacapp_snprintf_shift(slen, &str, &str_len);
char_str++; char_str++;
if (str) {
str += slen;
if (str_len >= slen) {
str_len -= slen;
} else {
str_len = 0;
}
}
ret_val += slen;
} }
slen = snprintf(str, str_len, "\""); slen = snprintf(str, str_len, "\"");
ret_val += slen; ret_val += slen;
+6
View File
@@ -314,6 +314,12 @@ extern "C" {
#define BACAPP_PRINT_ENABLED #define BACAPP_PRINT_ENABLED
#endif #endif
#endif #endif
BACNET_STACK_EXPORT
int bacapp_snprintf_shift(
int len,
char **buf,
size_t *buf_size);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
int bacapp_snprintf_value( int bacapp_snprintf_value(
char *str, char *str,
+174 -145
View File
@@ -71,8 +71,7 @@ void bacnet_destination_default_init(BACNET_DESTINATION *destination)
* @param r2 - BACnetRecipient 2 structure * @param r2 - BACnetRecipient 2 structure
* @return true if r1 and r2 are the same * @return true if r1 and r2 are the same
*/ */
bool bacnet_recipient_same( bool bacnet_recipient_same(BACNET_RECIPIENT *r1, BACNET_RECIPIENT *r2)
BACNET_RECIPIENT *r1, BACNET_RECIPIENT *r2)
{ {
bool status = false; bool status = false;
@@ -103,8 +102,7 @@ bool bacnet_recipient_same(
* @param src - BACnetRecipient 1 structure * @param src - BACnetRecipient 1 structure
* @param dest - BACnetRecipient 2 structure * @param dest - BACnetRecipient 2 structure
*/ */
void bacnet_recipient_copy( void bacnet_recipient_copy(BACNET_RECIPIENT *dest, BACNET_RECIPIENT *src)
BACNET_RECIPIENT *dest, BACNET_RECIPIENT *src)
{ {
if (dest && src) { if (dest && src) {
memmove(dest, src, sizeof(BACNET_RECIPIENT)); memmove(dest, src, sizeof(BACNET_RECIPIENT));
@@ -170,8 +168,7 @@ bool bacnet_destination_same(BACNET_DESTINATION *d1, BACNET_DESTINATION *d2)
status = (datetime_compare_time(&d1->ToTime, &d2->ToTime) == 0); status = (datetime_compare_time(&d1->ToTime, &d2->ToTime) == 0);
} }
if (status) { if (status) {
status = bacnet_recipient_same( status = bacnet_recipient_same(&d1->Recipient, &d2->Recipient);
&d1->Recipient, &d2->Recipient);
} }
if (status) { if (status) {
status = (d1->ProcessIdentifier == d2->ProcessIdentifier); status = (d1->ProcessIdentifier == d2->ProcessIdentifier);
@@ -252,7 +249,8 @@ int bacnet_destination_encode(uint8_t *apdu, BACNET_DESTINATION *destination)
apdu += len; apdu += len;
} }
if (destination->Recipient.tag == BACNET_RECIPIENT_TAG_DEVICE) { if (destination->Recipient.tag == BACNET_RECIPIENT_TAG_DEVICE) {
len = encode_context_object_id(apdu, 0, OBJECT_DEVICE, len = encode_context_object_id(
apdu, 0, OBJECT_DEVICE,
destination->Recipient.type.device.instance); destination->Recipient.type.device.instance);
apdu_len += len; apdu_len += len;
if (apdu) { if (apdu) {
@@ -392,7 +390,8 @@ int bacnet_destination_decode(
if (decode_is_context_tag(apdu, BACNET_RECIPIENT_TAG_DEVICE)) { if (decode_is_context_tag(apdu, BACNET_RECIPIENT_TAG_DEVICE)) {
/* device [0] BACnetObjectIdentifier */ /* device [0] BACnetObjectIdentifier */
destination->Recipient.tag = BACNET_RECIPIENT_TAG_DEVICE; destination->Recipient.tag = BACNET_RECIPIENT_TAG_DEVICE;
len = decode_context_object_id(apdu, BACNET_RECIPIENT_TAG_DEVICE, len = decode_context_object_id(
apdu, BACNET_RECIPIENT_TAG_DEVICE,
&destination->Recipient.type.device.type, &destination->Recipient.type.device.type,
&destination->Recipient.type.device.instance); &destination->Recipient.type.device.instance);
if (len == BACNET_STATUS_ERROR) { if (len == BACNET_STATUS_ERROR) {
@@ -462,56 +461,52 @@ int bacnet_destination_decode(
return apdu_len; return apdu_len;
} }
#define LEN_BRANCH(snprintf_expr) \
do { \
len = snprintf_expr; \
output_len += len; \
if (buf) { \
if (len > buf_size) { \
return -1; \
} else { \
buf += len; \
buf_size -= len; \
} \
} \
} while (0)
/** /**
* Convert BACnet_Destination to ASCII for printing * Convert BACnet_Destination to ASCII for printing
* *
* Output format: * Output format:
* *
* (ValidDays=[1,2,5,6,7];FromTime=0:00:00.0;ToTime=23:59:59.9;Recipient=Device(type=8,instance=15);ProcessIdentifier=0;ConfirmedNotify=false;Transitions=[to-offnormal,to-fault,to-normal]) * (
* ValidDays=[1,2,5,6,7];
* FromTime=0:00:00.0;
* ToTime=23:59:59.9;
* Recipient=Device(type=8,instance=15);
* ProcessIdentifier=0;
* ConfirmedNotify=false;
* Transitions=[to-offnormal,to-fault,to-normal]
* )
* *
* - ValidDays ... array of numbers, 1=Mon through 7=Sun * - ValidDays ... array of numbers, 1=Mon through 7=Sun
* - FromTime, ToTime ... HH:MM:SS.s * - FromTime, ToTime ... HH:MM:SS.s
* - Recipient ... two variants: Recipient=Device(type=8,instance=15) or Recipient=Address(net=1234,mac=c0:a8:00:0f) * - Recipient ... two variants: Recipient=Device(type=8,instance=15) or
* Recipient=Address(net=1234,mac=c0:a8:00:0f)
* - type ... bacnet object type enum * - type ... bacnet object type enum
* - instance ... bacnet object instance * - instance ... bacnet object instance
* - net ... bacnet network number * - net ... bacnet network number
* - mac ... bacnet MAC address; can be separated by colons or periods. * - mac ... bacnet MAC address; can be separated by colons or periods.
* - ProcessIdentifier ... 32bit unsigned int, process ID * - ProcessIdentifier ... 32bit unsigned int, process ID
* - ConfirmedNotify ... true or false * - ConfirmedNotify ... true or false
* - Transitions ... array with any of the three items: to-offnormal, to-fault, to-normal * - Transitions ... array with any of the three items: to-offnormal, to-fault,
* to-normal
* *
* @param bacdest - Destination struct to convert to ASCII * @param bacdest - Destination struct to convert to ASCII
* @param buf - ASCII output buffer * @param buf - ASCII output buffer
* @param buf_size - ASCII output buffer capacity * @param buf_size - ASCII output buffer capacity
* *
* @return the number of characters which would be generated for the given * @return the number of characters which would be generated for the given
* input, excluding the trailing null. negative is returned if the capacity was not sufficient. * input, excluding the trailing null.
* @note buf and buf_size may be null and zero to return only the size * @note buf and buf_size may be null and zero to return only the size
*/ */
int bacnet_destination_to_ascii(const BACNET_DESTINATION *bacdest, char *buf, size_t buf_size) int bacnet_destination_to_ascii(
const BACNET_DESTINATION *bacdest, char *buf, size_t buf_size)
{ {
int len = 0; int len = 0;
int output_len = 0; int buf_len = 0;
bool comma; bool comma;
int i; int i;
LEN_BRANCH(snprintf(buf, buf_size, "(")); len = snprintf(buf, buf_size, "(");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
/* /*
BACnetDaysOfWeek ::= BIT STRING { BACnetDaysOfWeek ::= BIT STRING {
monday (0), monday (0),
@@ -523,68 +518,80 @@ int bacnet_destination_to_ascii(const BACNET_DESTINATION *bacdest, char *buf, si
sunday (6) sunday (6)
} }
*/ */
/* Use numbers 1-7 (ISO 8601) */ /* Use numbers 1-7 (ISO 8601) */
LEN_BRANCH(snprintf(buf, buf_size, "ValidDays=[")); len = snprintf(buf, buf_size, "ValidDays=[");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
comma = false; comma = false;
for (i = 0; i < 7; i++) { for (i = 0; i < 7; i++) {
if (bitstring_bit((BACNET_BIT_STRING *) &bacdest->ValidDays, i)) { if (bitstring_bit((BACNET_BIT_STRING *)&bacdest->ValidDays, i)) {
if (comma) { if (comma) {
LEN_BRANCH(snprintf(buf, buf_size, ",")); len = snprintf(buf, buf_size, ",");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
} }
LEN_BRANCH(snprintf(buf, buf_size, "%d", i + 1)); len = snprintf(buf, buf_size, "%d", i + 1);
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
comma = true; comma = true;
} }
} }
LEN_BRANCH(snprintf(buf, buf_size, "];")); len = snprintf(buf, buf_size, "];");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
LEN_BRANCH(snprintf(buf, buf_size, "FromTime=%d:%02d:%02d.%02d;", len = snprintf(
bacdest->FromTime.hour, buf, buf_size, "FromTime=%d:%02d:%02d.%02d;", bacdest->FromTime.hour,
bacdest->FromTime.min, bacdest->FromTime.min, bacdest->FromTime.sec,
bacdest->FromTime.sec, bacdest->FromTime.hundredths);
bacdest->FromTime.hundredths buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
)); len = snprintf(
buf, buf_size, "ToTime=%d:%02d:%02d.%02d;", bacdest->ToTime.hour,
bacdest->ToTime.min, bacdest->ToTime.sec, bacdest->ToTime.hundredths);
LEN_BRANCH(snprintf(buf, buf_size, "ToTime=%d:%02d:%02d.%02d;", buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
bacdest->ToTime.hour, len = snprintf(buf, buf_size, "Recipient=");
bacdest->ToTime.min, buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
bacdest->ToTime.sec,
bacdest->ToTime.hundredths
));
LEN_BRANCH(snprintf(buf, buf_size, "Recipient="));
if (bacdest->Recipient.tag == BACNET_RECIPIENT_TAG_DEVICE) { if (bacdest->Recipient.tag == BACNET_RECIPIENT_TAG_DEVICE) {
LEN_BRANCH(snprintf(buf, buf_size, "Device(type=%d,instance=%lu)", len = snprintf(
bacdest->Recipient.type.device.type, buf, buf_size, "Device(type=%d,instance=%lu)",
(unsigned long)bacdest->Recipient.type.device.instance)); bacdest->Recipient.type.device.type,
(unsigned long)bacdest->Recipient.type.device.instance);
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
} else { } else {
/* /*
BACnetAddress ::= SEQUENCE { BACnetAddress ::= SEQUENCE {
network-number Unsigned16, -- A value of 0 indicates the local network network-number Unsigned16, -- A value of 0 indicates the local
mac-address OCTET STRING -- A string of length 0 indicates a broadcast network mac-address OCTET STRING -- A string of length 0 indicates
a broadcast
} }
*/ */
LEN_BRANCH(snprintf(buf, buf_size, "Address(net=%d,mac=", bacdest->Recipient.type.address.net)); len = snprintf(
buf, buf_size,
"Address(net=%d,mac=", bacdest->Recipient.type.address.net);
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
/* TODO determine if it's IPv4+port or Ethernet mac address and print it nicer - how? Both are 6 bytes long. */ /* TODO determine if it's IPv4+port or Ethernet mac address and print it
* nicer - how? Both are 6 bytes long. */
for (i = 0; i < bacdest->Recipient.type.address.mac_len; i++) { for (i = 0; i < bacdest->Recipient.type.address.mac_len; i++) {
if (i > 0) { if (i > 0) {
LEN_BRANCH(snprintf(buf, buf_size, ":")); len = snprintf(buf, buf_size, ":");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
} }
LEN_BRANCH(snprintf(buf, buf_size, "%02x", bacdest->Recipient.type.address.mac[i])); len = snprintf(
buf, buf_size, "%02x", bacdest->Recipient.type.address.mac[i]);
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
} }
LEN_BRANCH(snprintf(buf, buf_size, ")")); len = snprintf(buf, buf_size, ")");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
} }
LEN_BRANCH(snprintf(buf, buf_size, ";")); len = snprintf(buf, buf_size, ";");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
LEN_BRANCH(snprintf(buf, buf_size, "ProcessIdentifier=%lu;", len = snprintf(
(unsigned long)bacdest->ProcessIdentifier)); buf, buf_size, "ProcessIdentifier=%lu;",
(unsigned long)bacdest->ProcessIdentifier);
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
LEN_BRANCH(snprintf(buf, buf_size, "ConfirmedNotify=%s;", len = snprintf(
bacdest->ConfirmedNotify ? "true" : "false" buf, buf_size, "ConfirmedNotify=%s;",
)); bacdest->ConfirmedNotify ? "true" : "false");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
/* /*
BACnetEventTransitionBits ::= BIT STRING { BACnetEventTransitionBits ::= BIT STRING {
@@ -593,36 +600,49 @@ int bacnet_destination_to_ascii(const BACNET_DESTINATION *bacdest, char *buf, si
to-normal (2) to-normal (2)
} }
*/ */
LEN_BRANCH(snprintf(buf, buf_size, "Transitions=[")); len = snprintf(buf, buf_size, "Transitions=[");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
comma = false; comma = false;
/* TODO remove casting when bitstring_bit() has const added - Github issue #320 */ /* TODO remove casting when bitstring_bit() has const added - Github issue
if (bitstring_bit((BACNET_BIT_STRING *) &bacdest->Transitions, TRANSITION_TO_OFFNORMAL)) { * #320 */
LEN_BRANCH(snprintf(buf, buf_size, "to-offnormal")); if (bitstring_bit(
(BACNET_BIT_STRING *)&bacdest->Transitions,
TRANSITION_TO_OFFNORMAL)) {
len = snprintf(buf, buf_size, "to-offnormal");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
comma = true; comma = true;
} }
if (bitstring_bit((BACNET_BIT_STRING *) &bacdest->Transitions, TRANSITION_TO_FAULT)) { if (bitstring_bit(
(BACNET_BIT_STRING *)&bacdest->Transitions, TRANSITION_TO_FAULT)) {
if (comma) { if (comma) {
LEN_BRANCH(snprintf(buf, buf_size, ",")); len = snprintf(buf, buf_size, ",");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
} }
LEN_BRANCH(snprintf(buf, buf_size, "to-fault")); len = snprintf(buf, buf_size, "to-fault");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
comma = true; comma = true;
} }
if (bitstring_bit((BACNET_BIT_STRING *) &bacdest->Transitions, TRANSITION_TO_NORMAL)) { if (bitstring_bit(
(BACNET_BIT_STRING *)&bacdest->Transitions, TRANSITION_TO_NORMAL)) {
if (comma) { if (comma) {
LEN_BRANCH(snprintf(buf, buf_size, ",")); len = snprintf(buf, buf_size, ",");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
} }
LEN_BRANCH(snprintf(buf, buf_size, "to-normal")); len = snprintf(buf, buf_size, "to-normal");
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
} }
LEN_BRANCH(snprintf(buf, buf_size, "])")); /* end of the outer paren */ len = snprintf(buf, buf_size, "])"); /* end of the outer paren */
buf_len += bacapp_snprintf_shift(len, &buf, &buf_size);
return output_len; return buf_len;
} }
/** /**
* Parse BACnet_Destination from ASCII string (as entered by user) * Parse BACnet_Destination from ASCII string (as entered by user)
* *
* @param bacdest - Destination struct to pupulate with data from the ASCII string * @param bacdest - Destination struct to pupulate with data from the ASCII
* string
* @param buf - ASCII string, zero terminated * @param buf - ASCII string, zero terminated
* @return true on success * @return true on success
*/ */
@@ -658,14 +678,9 @@ bool bacnet_destination_from_ascii(BACNET_DESTINATION *bacdest, const char *buf)
enum ParseKeyword kw = 0; enum ParseKeyword kw = 0;
BACNET_TIME *ptime; BACNET_TIME *ptime;
BACNET_MAC_ADDRESS tmpmac; BACNET_MAC_ADDRESS tmpmac;
static const char * KW_LOOKUP[] = { static const char *KW_LOOKUP[] = {
"ValidDays", "ValidDays", "FromTime", "ToTime", "Recipient",
"FromTime", "ProcessIdentifier", "ConfirmedNotify", "Transitions",
"ToTime",
"Recipient",
"ProcessIdentifier",
"ConfirmedNotify",
"Transitions",
}; };
if (bacdest == NULL || buf == NULL) { if (bacdest == NULL || buf == NULL) {
@@ -674,7 +689,6 @@ bool bacnet_destination_from_ascii(BACNET_DESTINATION *bacdest, const char *buf)
bacnet_destination_default_init(bacdest); bacnet_destination_default_init(bacdest);
/* Helper macros to simplify the parser ... */ /* Helper macros to simplify the parser ... */
/* true if the character is whitespace */ /* true if the character is whitespace */
@@ -682,48 +696,49 @@ bool bacnet_destination_from_ascii(BACNET_DESTINATION *bacdest, const char *buf)
/* Discard characters while they match a given test. Goes to parse_end on NUL. /* Discard characters while they match a given test. Goes to parse_end on NUL.
* ctest is a boolean expression where c is the tested character */ * ctest is a boolean expression where c is the tested character */
#define DISCARD_WHILE(ctest) \ #define DISCARD_WHILE(ctest) \
do { \ do { \
while(1) { \ while (1) { \
c = buf[pos]; \ c = buf[pos]; \
if (c == 0) { \ if (c == 0) { \
goto parse_end; \ goto parse_end; \
} \ } \
if ((ctest)) { \ if ((ctest)) { \
pos++; \ pos++; \
continue; \ continue; \
} \ } \
break; \ break; \
} \ } \
} while(0) } while (0)
/* Discard all whitespace. Goes to parse_end on NUL. */ /* Discard all whitespace. Goes to parse_end on NUL. */
#define DISCARD_WHITESPACE() DISCARD_WHILE(ISWHITE(c)) #define DISCARD_WHITESPACE() DISCARD_WHILE(ISWHITE(c))
/* Must consume a given word; return false otherwise. */ /* Must consume a given word; return false otherwise. */
#define MUST_CONSUME(s) \ #define MUST_CONSUME(s) \
do { \ do { \
_must_consume_tmplen = strlen(s); \ _must_consume_tmplen = strlen(s); \
if (0 == strncmp(&buf[pos], s, _must_consume_tmplen)) { \ if (0 == strncmp(&buf[pos], s, _must_consume_tmplen)) { \
pos += _must_consume_tmplen; \ pos += _must_consume_tmplen; \
} else { \ } else { \
return false; \ return false; \
} \ } \
} while(0) } while (0)
/* Collect a decimal number and store the result into tmp; stop on a non-digit. Clobbers "c" and "tmp". TODO replace with strtol? */ /* Collect a decimal number and store the result into tmp; stop on a non-digit.
#define COLLECT_NUMBER_TMP(maxdigits) \ * Clobbers "c" and "tmp". TODO replace with strtol? */
do { \ #define COLLECT_NUMBER_TMP(maxdigits) \
tmp = 0; \ do { \
for (_number_i = 0; _number_i < (maxdigits); _number_i++) { \ tmp = 0; \
c = buf[pos]; \ for (_number_i = 0; _number_i < (maxdigits); _number_i++) { \
if (c >= '0' && c <= '9') { \ c = buf[pos]; \
tmp = (tmp * 10) + (c - '0'); \ if (c >= '0' && c <= '9') { \
pos++; \ tmp = (tmp * 10) + (c - '0'); \
} else { \ pos++; \
break; \ } else { \
} \ break; \
} \ } \
} \
} while (0) } while (0)
/* Go through all key=value pieces in the string */ /* Go through all key=value pieces in the string */
@@ -763,7 +778,9 @@ bool bacnet_destination_from_ascii(BACNET_DESTINATION *bacdest, const char *buf)
} }
break; break;
case PH_VALUE_SPACER: /* Equals between key and value, also consuming opening square bracket if present. */ case PH_VALUE_SPACER: /* Equals between key and value, also
consuming opening square bracket if
present. */
DISCARD_WHITESPACE(); DISCARD_WHITESPACE();
MUST_CONSUME("="); MUST_CONSUME("=");
DISCARD_WHILE(c == '[' || ISWHITE(c)); DISCARD_WHILE(c == '[' || ISWHITE(c));
@@ -792,7 +809,8 @@ bool bacnet_destination_from_ascii(BACNET_DESTINATION *bacdest, const char *buf)
} }
if (j == 0) { if (j == 0) {
if (c >= '1' && c <= '7') { if (c >= '1' && c <= '7') {
bitstring_set_bit(&bacdest->ValidDays, c - '1', true); bitstring_set_bit(
&bacdest->ValidDays, c - '1', true);
pos++; pos++;
j = 1; j = 1;
} else { } else {
@@ -815,7 +833,8 @@ bool bacnet_destination_from_ascii(BACNET_DESTINATION *bacdest, const char *buf)
ptime = &bacdest->ToTime; ptime = &bacdest->ToTime;
} }
/* TODO implemented in bacapp_parse_application_data - extract & reuse? */ /* TODO implemented in bacapp_parse_application_data -
* extract & reuse? */
/* Hour */ /* Hour */
COLLECT_NUMBER_TMP(2); COLLECT_NUMBER_TMP(2);
@@ -887,17 +906,20 @@ bool bacnet_destination_from_ascii(BACNET_DESTINATION *bacdest, const char *buf)
if (j == 0) { if (j == 0) {
if (0 == if (0 ==
strncmp(&buf[pos], "to-offnormal", 12)) { strncmp(&buf[pos], "to-offnormal", 12)) {
bitstring_set_bit(&bacdest->Transitions, bitstring_set_bit(
&bacdest->Transitions,
TRANSITION_TO_OFFNORMAL, true); TRANSITION_TO_OFFNORMAL, true);
pos += 12; pos += 12;
} else if (0 == } else if (
strncmp(&buf[pos], "to-fault", 8)) { 0 == strncmp(&buf[pos], "to-fault", 8)) {
bitstring_set_bit(&bacdest->Transitions, bitstring_set_bit(
&bacdest->Transitions,
TRANSITION_TO_FAULT, true); TRANSITION_TO_FAULT, true);
pos += 8; pos += 8;
} else if (0 == } else if (
strncmp(&buf[pos], "to-normal", 9)) { 0 == strncmp(&buf[pos], "to-normal", 9)) {
bitstring_set_bit(&bacdest->Transitions, bitstring_set_bit(
&bacdest->Transitions,
TRANSITION_TO_NORMAL, true); TRANSITION_TO_NORMAL, true);
pos += 9; pos += 9;
} else { } else {
@@ -914,7 +936,8 @@ bool bacnet_destination_from_ascii(BACNET_DESTINATION *bacdest, const char *buf)
case KW_Recipient: case KW_Recipient:
if (0 == strncmp(&buf[pos], "Device", 6)) { if (0 == strncmp(&buf[pos], "Device", 6)) {
pos += 6; pos += 6;
bacdest->Recipient.tag = BACNET_RECIPIENT_TAG_DEVICE; bacdest->Recipient.tag =
BACNET_RECIPIENT_TAG_DEVICE;
DISCARD_WHITESPACE(); DISCARD_WHITESPACE();
MUST_CONSUME("("); MUST_CONSUME("(");
@@ -943,7 +966,8 @@ bool bacnet_destination_from_ascii(BACNET_DESTINATION *bacdest, const char *buf)
} else if (0 == strncmp(&buf[pos], "Address", 7)) { } else if (0 == strncmp(&buf[pos], "Address", 7)) {
pos += 7; pos += 7;
bacdest->Recipient.tag = BACNET_RECIPIENT_TAG_ADDRESS; bacdest->Recipient.tag =
BACNET_RECIPIENT_TAG_ADDRESS;
DISCARD_WHITESPACE(); DISCARD_WHITESPACE();
MUST_CONSUME("("); MUST_CONSUME("(");
@@ -964,13 +988,18 @@ bool bacnet_destination_from_ascii(BACNET_DESTINATION *bacdest, const char *buf)
MUST_CONSUME("="); MUST_CONSUME("=");
DISCARD_WHITESPACE(); DISCARD_WHITESPACE();
if (!bacnet_address_mac_from_ascii(&tmpmac, &buf[pos])) { if (!bacnet_address_mac_from_ascii(
&tmpmac, &buf[pos])) {
return false; return false;
} }
bacdest->Recipient.type.address.mac_len = tmpmac.len; bacdest->Recipient.type.address.mac_len =
memcpy(&bacdest->Recipient.type.address.mac, &tmpmac.adr, MAX_MAC_LEN); tmpmac.len;
memcpy(
&bacdest->Recipient.type.address.mac,
&tmpmac.adr, MAX_MAC_LEN);
/* address_mac_from_ascii doesn't return number of digits /* address_mac_from_ascii doesn't return number of
* digits
* - we have to discard until ) */ * - we have to discard until ) */
DISCARD_WHILE(c != ')'); DISCARD_WHILE(c != ')');
+33 -28
View File
@@ -35,7 +35,10 @@
#include <stdint.h> /* for standard integer types uint8_t etc. */ #include <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */ #include <stdbool.h> /* for the standard bool type. */
#include <stdio.h> #include <stdio.h>
#include "bacnet/bacenum.h" /* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/bacapp.h"
#include "bacnet/bacdcode.h" #include "bacnet/bacdcode.h"
#include "bacnet/bacint.h" #include "bacnet/bacint.h"
#include "bacnet/datalink/bvlc6.h" #include "bacnet/datalink/bvlc6.h"
@@ -641,6 +644,32 @@ bool bvlc6_address_get(BACNET_IP6_ADDRESS *addr,
return status; return status;
} }
/**
* @brief Shift the buffer pointer and decrease the size after an snprintf
* @param len - number of bytes (excluding terminating NULL byte) from snprintf
* @param buf - pointer to the buffer pointer
* @param buf_size - pointer to the buffer size
* @return number of bytes (excluding terminating NULL byte) from snprintf
*/
static int snprintf_shift(int len, char **buf, size_t *buf_size)
{
if (buf) {
if (*buf) {
*buf += len;
}
}
if (buf_size) {
if ((*buf_size) >= len) {
*buf_size -= len;
} else {
*buf_size = 0;
}
}
return len;
}
/** Convert IPv6 Address from ASCII /** Convert IPv6 Address from ASCII
* *
* IPv6 addresses are represented as eight groups, separated by colons, * IPv6 addresses are represented as eight groups, separated by colons,
@@ -689,41 +718,17 @@ int bvlc6_address_to_ascii(BACNET_IP6_ADDRESS *addr, char *buf, size_t buf_size)
if ((a == 0) && (f >= 0)) { if ((a == 0) && (f >= 0)) {
if (f++ == 0) { if (f++ == 0) {
len = snprintf(buf, buf_size, "::"); len = snprintf(buf, buf_size, "::");
if (buf) { n += snprintf_shift(len, &buf, &buf_size);
buf += len;
}
if (len > buf_size) {
buf_size = 0;
} else {
buf_size -= len;
}
n += len;
} }
} else { } else {
if (f > 0) { if (f > 0) {
f = -1; f = -1;
} else if (i > 0) { } else if (i > 0) {
len = snprintf(buf, buf_size, ":"); len = snprintf(buf, buf_size, ":");
if (buf) { n += snprintf_shift(len, &buf, &buf_size);
buf += len;
}
if (len > buf_size) {
buf_size = 0;
} else {
buf_size -= len;
}
n += len;
} }
len = snprintf(buf, buf_size, "%x", a); len = snprintf(buf, buf_size, "%x", a);
if (buf) { n += snprintf_shift(len, &buf, &buf_size);
buf += len;
}
if (len > buf_size) {
buf_size = 0;
} else {
buf_size -= len;
}
n += len;
} }
} }
+10 -6
View File
@@ -117,7 +117,7 @@ static void test_BACnetDestination_ASCII(void)
#endif #endif
{ {
BACNET_DESTINATION destination = { 0 }, test_destination = { 0 }; BACNET_DESTINATION destination = { 0 }, test_destination = { 0 };
int len = 0, test_len = 0; int len = 0, test_len = 0, null_len = 0;
const char *ascii = "(" const char *ascii = "("
"ValidDays=[1,2,3,4,5,6,7];" "ValidDays=[1,2,3,4,5,6,7];"
"FromTime=0:00:00.0;ToTime=23:59:59.99;" "FromTime=0:00:00.0;ToTime=23:59:59.99;"
@@ -135,13 +135,17 @@ static void test_BACnetDestination_ASCII(void)
status = bacnet_destination_same(&destination, &test_destination); status = bacnet_destination_same(&destination, &test_destination);
zassert_true(status, NULL); zassert_true(status, NULL);
/* get the length */ /* get the length */
len = bacnet_destination_to_ascii(&test_destination, NULL, 0); null_len = bacnet_destination_to_ascii(&test_destination, NULL, 0);
if (len > 0) { if (null_len > 0) {
test_ascii = calloc(len, 1); test_ascii = calloc(null_len, 1);
if (test_ascii) { if (test_ascii) {
test_len = test_len =
bacnet_destination_to_ascii(&test_destination, test_ascii, len); bacnet_destination_to_ascii(&test_destination, test_ascii, null_len);
zassert_equal(len, test_len, NULL); zassert_equal(null_len, test_len, NULL);
while (--test_len) {
len = bacnet_destination_to_ascii(&test_destination, test_ascii, test_len);
zassert_equal(len, null_len, NULL);
}
free(test_ascii); free(test_ascii);
} }
} }