From d2246a5bcf654fdefbd33a5cb2c6437f888e87e0 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 4 Jan 2023 18:34:03 +0100 Subject: [PATCH] include/cctype: add c_strcasecmp() and c_strncasecmp() Sometimes, we need to compare ASCII-only strings independently on the current locales. Let's follow our cctype.h to implement such functions. Addresses: https://github.com/util-linux/util-linux/issues/1991 Signed-off-by: Karel Zak --- include/cctype.h | 34 ++++++++++++++++++++++++++++++++++ lib/strutils.c | 26 +++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/include/cctype.h b/include/cctype.h index 6ab644c6e1..4181b12256 100644 --- a/include/cctype.h +++ b/include/cctype.h @@ -322,4 +322,38 @@ static inline int c_toupper (int c) } } +static inline int c_strncasecmp(const char *a, const char *b, size_t n) +{ + int res = 0; + + for (; n > 0; a++, b++, n--) { + unsigned int x = (unsigned int) *a; + unsigned int y = (unsigned int) *b; + + res = c_tolower(x) - c_tolower(y); + if (res) + break; + } + return res; +} + +static inline int c_strcasecmp(const char *a, const char *b) +{ + int res = 0; + + if (a == b) + return 0; + + for (; *a != '\0'; a++, b++) { + unsigned int x = (unsigned int) *a; + unsigned int y = (unsigned int) *b; + + res = c_tolower(x) - c_tolower(y); + if (res) + break; + } + + return res; +} + #endif /* UTIL_LINUX_CCTYPE_H */ diff --git a/lib/strutils.c b/lib/strutils.c index db73c00fca..b35d059419 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -1208,6 +1208,9 @@ int ul_optstr_next(char **optstr, char **name, size_t *namesz, } #ifdef TEST_PROGRAM_STRUTILS + +#include "cctype.h" + struct testS { char *name; char *value; @@ -1308,6 +1311,23 @@ done: return EXIT_SUCCESS; } +static int test_strutils_cstrcasecmp(int argc, char *argv[]) +{ + char *a, *b; + + if (argc < 3) + return EXIT_FAILURE; + + a = argv[1]; + b = argv[2]; + + printf("cmp '%s' '%s' = %d\n", a, b, strcasecmp(a, b)); + printf("c_cmp '%s' '%s' = %d\n", a, b, c_strcasecmp(a, b)); + printf("c_ncmp '%s' '%s' = %d\n", a, b, c_strncasecmp(a, b, strlen(a))); + + return EXIT_SUCCESS; +} + int main(int argc, char *argv[]) { if (argc == 3 && strcmp(argv[1], "--size") == 0) { @@ -1323,10 +1343,13 @@ int main(int argc, char *argv[]) printf("%s\n", ul_stralnumcmp(argv[2], argv[3]) == 0 ? "match" : "dismatch"); return EXIT_SUCCESS; + + } else if (argc == 4 && strcmp(argv[1], "--cstrcasecmp") == 0) { + return test_strutils_cstrcasecmp(argc - 1, argv + 1); + } else if (argc == 3 && strcmp(argv[1], "--normalize") == 0) { return test_strutils_normalize(argc - 1, argv + 1); - } else if (argc == 3 && strcmp(argv[1], "--strtos64") == 0) { printf("'%s'-->%jd\n", argv[2], strtos64_or_err(argv[2], "strtos64 failed")); return EXIT_SUCCESS; @@ -1355,6 +1378,7 @@ int main(int argc, char *argv[]) " %1$s --cmp-paths \n" " %1$s --strdup-member \n" " %1$s --stralnumcmp \n" + " %1$s --cstrcasecmp \n" " %1$s --normalize \n" " %1$s --strto{s,u}{16,32,64} \n", argv[0]); -- 2.47.2