]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
include/cctype: add c_strcasecmp() and c_strncasecmp()
authorKarel Zak <kzak@redhat.com>
Wed, 4 Jan 2023 17:34:03 +0000 (18:34 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 4 Jan 2023 17:34:03 +0000 (18:34 +0100)
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 <kzak@redhat.com>
include/cctype.h
lib/strutils.c

index 6ab644c6e18846cc0119809553dce73766739eb0..4181b1225665c7261b5f6b4803264f6af97eddfa 100644 (file)
@@ -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 */
index db73c00fca072fee4efb75f9841aab4d61e4596d..b35d059419a014126aa576d5f99f9cb55a8e5362 100644 (file)
@@ -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 <path> <path>\n"
                                "       %1$s --strdup-member <str> <str>\n"
                                "       %1$s --stralnumcmp <str> <str>\n"
+                               "       %1$s --cstrcasecmp <str> <str>\n"
                                "       %1$s --normalize <str>\n"
                                "       %1$s --strto{s,u}{16,32,64} <str>\n",
                                argv[0]);