diff --git a/CMakeLists.txt b/CMakeLists.txt index 8cb65fab..0914f6c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -889,8 +889,6 @@ if(BACNET_STACK_BUILD_APPS) # NOTE: Might be that this example currently doesn't work on Windows because # of the following warning: - # 'strncasecmp': macro redefinition - $<$:/wd4005> # 'gettimeofday' undefined; assuming extern returning int $<$:/wd4013> ) diff --git a/apps/mstpcap/main.c b/apps/mstpcap/main.c index a0444620..821b0c56 100644 --- a/apps/mstpcap/main.c +++ b/apps/mstpcap/main.c @@ -18,6 +18,7 @@ #include "bacnet/iam.h" #include "bacnet/version.h" #include "bacnet/datetime.h" +#include "bacnet/bacstr.h" /* basic datalink, timer, and filename */ #include "bacnet/datalink/dlmstp.h" #include "bacnet/basic/sys/mstimer.h" @@ -28,10 +29,6 @@ #include "bacport.h" #include "rs485.h" -#ifdef _WIN32 -#define strncasecmp(x, y, z) _strnicmp(x, y, z) -#endif - /* define our Data Link Type for libPCAP */ #define DLT_BACNET_MS_TP (165) /* local min/max macros */ @@ -1100,7 +1097,7 @@ int main(int argc, char *argv[]) RS485_Set_Interface(argv[argi]); } #if defined(_WIN32) - if (strncasecmp(argv[argi], "com", 3) == 0) { + if (bacnet_strnicmp(argv[argi], "com", 3) == 0) { /* legacy command line options */ RS485_Set_Interface(argv[argi]); if ((argi + 1) < argc) { @@ -1110,7 +1107,7 @@ int main(int argc, char *argv[]) } } #else - if (strncasecmp(argv[argi], "/dev/", 5) == 0) { + if (bacnet_strnicmp(argv[argi], "/dev/", 5) == 0) { /* legacy command line options */ RS485_Set_Interface(argv[argi]); if ((argi + 1) < argc) { diff --git a/apps/writegroup/main.c b/apps/writegroup/main.c index de4755ad..8f21d605 100644 --- a/apps/writegroup/main.c +++ b/apps/writegroup/main.c @@ -159,9 +159,9 @@ int main(int argc, char *argv[]) /* decode the command line parameters */ data->group_number = strtol(argv[1], NULL, 0); data->write_priority = strtol(argv[2], NULL, 0); - if (strcasecmp(argv[3], "inhibit") == 0) { + if (bacnet_stricmp(argv[3], "inhibit") == 0) { data->inhibit_delay = WRITE_GROUP_INHIBIT_DELAY_TRUE; - } else if (strcasecmp(argv[3], "delay") == 0) { + } else if (bacnet_stricmp(argv[3], "delay") == 0) { data->inhibit_delay = WRITE_GROUP_INHIBIT_DELAY_FALSE; } else { data->inhibit_delay = WRITE_GROUP_INHIBIT_DELAY_FALSE; diff --git a/ports/bsd/bacport.h b/ports/bsd/bacport.h index 8488483e..bf649f33 100644 --- a/ports/bsd/bacport.h +++ b/ports/bsd/bacport.h @@ -36,10 +36,6 @@ #include /* for convenience */ #endif -#ifdef HAVE_STRINGS_H -#include /* for convenience */ -#endif - /* Three headers are normally needed for socket/file ioctl's: * , , and . */ diff --git a/ports/bsd/bip6.c b/ports/bsd/bip6.c index 1eaf060b..043ec4dc 100644 --- a/ports/bsd/bip6.c +++ b/ports/bsd/bip6.c @@ -121,7 +121,7 @@ void bip6_set_interface(char *ifname) debug_fprintf_bip6(stdout, "BIP6: found interface: %s\n", ifa_tmp->ifa_name); } if ((ifa_tmp->ifa_addr) && (ifa_tmp->ifa_addr->sa_family == AF_INET6) && - (strcasecmp(ifa_tmp->ifa_name, ifname) == 0)) { + (bacnet_stricmp(ifa_tmp->ifa_name, ifname) == 0)) { sin = (struct sockaddr_in6 *)ifa_tmp->ifa_addr; bvlc6_address_set(&BIP6_Addr, ntohs(sin->sin6_addr.s6_addr16[0]), ntohs(sin->sin6_addr.s6_addr16[1]), diff --git a/ports/linux/bacport.h b/ports/linux/bacport.h index 2c3436e0..b4c8dacc 100644 --- a/ports/linux/bacport.h +++ b/ports/linux/bacport.h @@ -36,10 +36,6 @@ #include /* for convenience */ #endif -#ifdef HAVE_STRINGS_H -#include /* for convenience */ -#endif - /* Three headers are normally needed for socket/file ioctl's: * , , and . */ diff --git a/ports/linux/bip6.c b/ports/linux/bip6.c index 6628bf56..71f2cbf1 100644 --- a/ports/linux/bip6.c +++ b/ports/linux/bip6.c @@ -109,7 +109,7 @@ void bip6_set_interface(char *ifname) stdout, "BIP6: found interface: %s\n", ifa_tmp->ifa_name); } if ((ifa_tmp->ifa_addr) && (ifa_tmp->ifa_addr->sa_family == AF_INET6) && - (strcasecmp(ifa_tmp->ifa_name, ifname) == 0)) { + (bacnet_stricmp(ifa_tmp->ifa_name, ifname) == 0)) { sin = (struct sockaddr_in6 *)ifa_tmp->ifa_addr; bvlc6_address_set( &BIP6_Addr, ntohs(sin->sin6_addr.s6_addr16[0]), diff --git a/src/bacnet/bacapp.c b/src/bacnet/bacapp.c index 2a1f82c5..03a0bba5 100644 --- a/src/bacnet/bacapp.c +++ b/src/bacnet/bacapp.c @@ -4200,12 +4200,12 @@ bool bacapp_parse_application_data( switch (tag_number) { #if defined(BACAPP_BOOLEAN) case BACNET_APPLICATION_TAG_BOOLEAN: - if (strcasecmp(argv, "true") == 0 || - strcasecmp(argv, "active") == 0) { + if (bacnet_stricmp(argv, "true") == 0 || + bacnet_stricmp(argv, "active") == 0) { value->type.Boolean = true; } else if ( - strcasecmp(argv, "false") == 0 || - strcasecmp(argv, "inactive") == 0) { + bacnet_stricmp(argv, "false") == 0 || + bacnet_stricmp(argv, "inactive") == 0) { value->type.Boolean = false; } else { status = strtol_checked(argv, &long_value); diff --git a/src/bacnet/bacstr.c b/src/bacnet/bacstr.c index 5ff9c065..d033663f 100644 --- a/src/bacnet/bacstr.c +++ b/src/bacnet/bacstr.c @@ -1227,12 +1227,18 @@ bool octetstring_value_same( * @param a - first string * @param b - second string * @return 0 if the strings are equal, non-zero if not - * @note The stricmp() function is not included C standard. + * @note The stricmp() function is not included in the C standard. */ int bacnet_stricmp(const char *a, const char *b) { int twin_a, twin_b; + if (a == NULL) { + return -1; + } + if (b == NULL) { + return 1; + } do { twin_a = *(const unsigned char *)a; twin_b = *(const unsigned char *)b; @@ -1245,6 +1251,47 @@ int bacnet_stricmp(const char *a, const char *b) return twin_a - twin_b; } +/** + * @brief Compare two strings, case insensitive, with length limit + * @details The strnicmp() function compares, at most, the first n characters + * of string1 and string2 without sensitivity to case. + * + * The function operates on null terminated strings. + * The string arguments to the function are expected to contain + * a null character (\0) marking the end of the string. + * + * @param a - first string + * @param b - second string + * @param length - maximum length to compare + * @return 0 if the strings are equal, non-zero if not + * @note The strnicmp() function is not included in the C standard. + */ +int bacnet_strnicmp(const char *a, const char *b, size_t length) +{ + int twin_a, twin_b; + + if (length == 0) { + return 0; + } + if (a == NULL) { + return -1; + } + if (b == NULL) { + return 1; + } + do { + twin_a = *(const unsigned char *)a; + twin_b = *(const unsigned char *)b; + twin_a = tolower(toupper(twin_a)); + twin_b = tolower(toupper(twin_b)); + a++; + b++; + length--; + } while ((twin_a == twin_b) && (twin_a != '\0') && (length > 0)); + + return twin_a - twin_b; +} + /** * @brief Return the length of a string, within a maximum length * @note The strnlen function is non-standard and not available in diff --git a/src/bacnet/bacstr.h b/src/bacnet/bacstr.h index e6a4d17e..ad5bcf57 100644 --- a/src/bacnet/bacstr.h +++ b/src/bacnet/bacstr.h @@ -170,6 +170,8 @@ bool octetstring_value_same( BACNET_STACK_EXPORT int bacnet_stricmp(const char *a, const char *b); BACNET_STACK_EXPORT +int bacnet_strnicmp(const char *a, const char *b, size_t length); +BACNET_STACK_EXPORT size_t bacnet_strnlen(const char *str, size_t maxlen); #ifdef __cplusplus diff --git a/src/bacnet/basic/sys/platform.h b/src/bacnet/basic/sys/platform.h index 075e0241..01419d5a 100644 --- a/src/bacnet/basic/sys/platform.h +++ b/src/bacnet/basic/sys/platform.h @@ -46,12 +46,6 @@ #endif #if defined(_MSC_VER) -#ifndef strcasecmp -#define strcasecmp _stricmp -#endif -#ifndef strncasecmp -#define strncasecmp _strnicmp -#endif #ifndef __inline__ #define __inline__ __inline #endif diff --git a/src/bacnet/channel_value.c b/src/bacnet/channel_value.c index 2791bf84..f306612f 100644 --- a/src/bacnet/channel_value.c +++ b/src/bacnet/channel_value.c @@ -558,13 +558,13 @@ bool bacnet_channel_value_from_ascii( return false; } if (!status) { - if (strcasecmp(argv, "null") == 0) { + if (bacnet_stricmp(argv, "null") == 0) { value->tag = BACNET_APPLICATION_TAG_NULL; status = true; } } if (!status) { - if (strcasecmp(argv, "true") == 0) { + if (bacnet_stricmp(argv, "true") == 0) { value->tag = BACNET_APPLICATION_TAG_BOOLEAN; #if defined(CHANNEL_BOOLEAN) value->type.Boolean = true; @@ -573,7 +573,7 @@ bool bacnet_channel_value_from_ascii( } } if (!status) { - if (strcasecmp(argv, "false") == 0) { + if (bacnet_stricmp(argv, "false") == 0) { value->tag = BACNET_APPLICATION_TAG_BOOLEAN; #if defined(CHANNEL_BOOLEAN) value->type.Boolean = false; diff --git a/src/bacnet/datalink/datalink.c b/src/bacnet/datalink/datalink.c index cf08e5e4..9aa981b4 100644 --- a/src/bacnet/datalink/datalink.c +++ b/src/bacnet/datalink/datalink.c @@ -8,7 +8,7 @@ * @ingroup DataLink */ #include "bacnet/datalink/datalink.h" - +#include "bacnet/bacstr.h" #if defined(BACDL_MULTIPLE) || defined FOR_DOXYGEN #if defined(BACDL_ETHERNET) #include "bacnet/datalink/ethernet.h" @@ -32,9 +32,6 @@ #if defined(BACDL_BSC) #include "bacnet/datalink/bsc/bsc-datalink.h" #endif -#ifdef HAVE_STRINGS_H -#include /* for strcasecmp() */ -#endif static enum { DATALINK_NONE = 0, @@ -48,36 +45,36 @@ static enum { void datalink_set(char *datalink_string) { - if (strcasecmp("none", datalink_string) == 0) { + if (bacnet_stricmp("none", datalink_string) == 0) { Datalink_Transport = DATALINK_NONE; } #if defined(BACDL_BIP) - else if (strcasecmp("bip", datalink_string) == 0) { + else if (bacnet_stricmp("bip", datalink_string) == 0) { Datalink_Transport = DATALINK_BIP; } #endif #if defined(BACDL_BIP6) - else if (strcasecmp("bip6", datalink_string) == 0) { + else if (bacnet_stricmp("bip6", datalink_string) == 0) { Datalink_Transport = DATALINK_BIP6; } #endif #if defined(BACDL_ETHERNET) - else if (strcasecmp("ethernet", datalink_string) == 0) { + else if (bacnet_stricmp("ethernet", datalink_string) == 0) { Datalink_Transport = DATALINK_ETHERNET; } #endif #if defined(BACDL_ARCNET) - else if (strcasecmp("arcnet", datalink_string) == 0) { + else if (bacnet_stricmp("arcnet", datalink_string) == 0) { Datalink_Transport = DATALINK_ARCNET; } #endif #if defined(BACDL_MSTP) - else if (strcasecmp("mstp", datalink_string) == 0) { + else if (bacnet_stricmp("mstp", datalink_string) == 0) { Datalink_Transport = DATALINK_MSTP; } #endif #if defined(BACDL_BSC) - else if (strcasecmp("bsc", datalink_string) == 0) { + else if (bacnet_stricmp("bsc", datalink_string) == 0) { Datalink_Transport = DATALINK_BSC; } #endif