diff --git a/CHANGELOG.md b/CHANGELOG.md index 91221c16..4ebc61d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ The git repositories are hosted at the following sites: ### Fixed +* Fixed library specific strcmp/stricmp functions match standard strcmp. (#1173) * Fixed compiler macro redefined warning when optional datatypes are defined globally. (#1172) * Fixed copy and compare API of BACnetObjectPropertyReference structure. (#1171) diff --git a/src/bacnet/bacstr.c b/src/bacnet/bacstr.c index 2a2de1a1..03c27d5e 100644 --- a/src/bacnet/bacstr.c +++ b/src/bacnet/bacstr.c @@ -1299,6 +1299,25 @@ bool octetstring_value_same( } #endif +/** + * @brief Compare two strings, case sensitive or insensitive, with length limit + * @details The strncmp() function compares, at most, the first n characters + * of string1 and string2. + * 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, or zero for full length of the + * first string argument. + * @param case_insensitive - true for case insensitive comparison + * @return 0 if the strings are equal, non-zero if not + * The sign of a nonzero value returned by the comparison functions + * memcmp, strcmp, and strncmp is determined by the sign of the + * difference between the values of the first pair of characters + * (both interpreted as unsigned char) that differ in the objects + * being compared. + */ static int bacnet_strnicmp_internal( const char *a, const char *b, size_t length, bool case_insensitive) { @@ -1328,15 +1347,57 @@ static int bacnet_strnicmp_internal( return twin_a - twin_b; } +/** + * @brief Compare two strings, case sensitive or insensitive + * @param a - first string + * @param b - second string + * @param case_insensitive - true for case insensitive comparison + * @return 0 if the strings are equal, non-zero if not + * The sign of a nonzero value returned by the comparison functions + * memcmp, strcmp, and strncmp is determined by the sign of the + * difference between the values of the first pair of characters + * (both interpreted as unsigned char) that differ in the objects + * being compared. + */ +static int +bacnet_stricmp_internal(const char *a, const char *b, bool case_insensitive) +{ + 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; + if (case_insensitive) { + twin_a = tolower(toupper(twin_a)); + twin_b = tolower(toupper(twin_b)); + } + a++; + b++; + } while ((twin_a == twin_b) && (twin_a != '\0')); + + return twin_a - twin_b; +} + /** * @brief Compare two strings, case sensitive * @param a - first string * @param b - second string * @return 0 if the strings are equal, non-zero if not + * The sign of a nonzero value returned by the comparison functions + * memcmp, strcmp, and strncmp is determined by the sign of the + * difference between the values of the first pair of characters + * (both interpreted as unsigned char) that differ in the objects + * being compared. */ int bacnet_strcmp(const char *a, const char *b) { - return bacnet_strnicmp_internal(a, b, 0, false); + return bacnet_stricmp_internal(a, b, false); } /** @@ -1344,11 +1405,16 @@ int bacnet_strcmp(const char *a, const char *b) * @param a - first string * @param b - second string * @return 0 if the strings are equal, non-zero if not + * The sign of a nonzero value returned by the comparison functions + * memcmp, strcmp, and strncmp is determined by the sign of the + * difference between the values of the first pair of characters + * (both interpreted as unsigned char) that differ in the objects + * being compared. * @note The stricmp() function is not included in the C standard. */ int bacnet_stricmp(const char *a, const char *b) { - return bacnet_strnicmp_internal(a, b, 0, true); + return bacnet_stricmp_internal(a, b, true); } /** @@ -1364,6 +1430,11 @@ int bacnet_stricmp(const char *a, const char *b) * @param b - second string * @param length - maximum length to compare * @return 0 if the strings are equal, non-zero if not + * The sign of a nonzero value returned by the comparison functions + * memcmp, strcmp, and strncmp is determined by the sign of the + * difference between the values of the first pair of characters + * (both interpreted as unsigned char) that differ in the objects + * being compared. */ int bacnet_strncmp(const char *a, const char *b, size_t length) { @@ -1383,6 +1454,11 @@ int bacnet_strncmp(const char *a, const char *b, size_t length) * @param b - second string * @param length - maximum length to compare * @return 0 if the strings are equal, non-zero if not + * The sign of a nonzero value returned by the comparison functions + * memcmp, strcmp, and strncmp is determined by the sign of the + * difference between the values of the first pair of characters + * (both interpreted as unsigned char) that differ in the objects + * being compared. * @note The strnicmp() function is not included in the C standard. */ int bacnet_strnicmp(const char *a, const char *b, size_t length) diff --git a/src/bacnet/indtext.c b/src/bacnet/indtext.c index 8c4c8210..9ca1b22d 100644 --- a/src/bacnet/indtext.c +++ b/src/bacnet/indtext.c @@ -17,7 +17,7 @@ * @param data_list - list of strings and indices * @param search_name - string to search for * @param found_index - index of the string found - * @return true if the string is found + * @return true if the matching string is found */ bool indtext_by_string( INDTEXT_DATA *data_list, const char *search_name, uint32_t *found_index) @@ -27,7 +27,7 @@ bool indtext_by_string( if (data_list && search_name) { while (data_list->pString) { - if (strcmp(data_list->pString, search_name) == 0) { + if (bacnet_strcmp(data_list->pString, search_name) == 0) { index = data_list->index; found = true; break; @@ -48,7 +48,7 @@ bool indtext_by_string( * @param data_list - list of strings and indices * @param search_name - string to search for * @param found_index - index of the string found - * @return true if the string is found + * @return true if the matching string is found */ bool indtext_by_istring( INDTEXT_DATA *data_list, const char *search_name, uint32_t *found_index) diff --git a/test/bacnet/indtext/src/main.c b/test/bacnet/indtext/src/main.c index 9a44dce7..98a55861 100644 --- a/test/bacnet/indtext/src/main.c +++ b/test/bacnet/indtext/src/main.c @@ -16,9 +16,12 @@ /** * @brief Test */ -static INDTEXT_DATA data_list[] = { { 1, "Joshua" }, { 2, "Mary" }, - { 3, "Anna" }, { 4, "Christopher" }, - { 5, "Patricia" }, { 0, NULL } }; +static INDTEXT_DATA data_list[] = { + { 1, "Joshua" }, { 2, "Mary" }, + { 3, "Anna" }, { 4, "Christopher" }, + { 5, "Patricia" }, { 6, "JoshuaMaryAnnaChristopherPatricia" }, + { 0, NULL } +}; #if defined(CONFIG_ZTEST_NEW_API) ZTEST(indtext_tests, testIndexText) @@ -26,11 +29,11 @@ ZTEST(indtext_tests, testIndexText) static void testIndexText(void) #endif { - unsigned i; /*counter */ + uint32_t i; /*counter */ const char *pString; - unsigned index; + uint32_t index; bool valid; - unsigned count = 0; + uint32_t count = 0; for (i = 0; i < 10; i++) { pString = indtext_by_index(data_list, i); @@ -38,7 +41,7 @@ static void testIndexText(void) count++; valid = indtext_by_string(data_list, pString, &index); zassert_true(valid, NULL); - zassert_equal(index, i, NULL); + zassert_equal(index, i, "index=%u i=%u", index, i); zassert_equal( index, indtext_by_string_default(data_list, pString, index), NULL);