]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/strutils: add ul_strchr_escaped()
authorKarel Zak <kzak@redhat.com>
Mon, 2 May 2022 13:07:42 +0000 (15:07 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 2 May 2022 13:07:42 +0000 (15:07 +0200)
Like strchr(), but ignores escaped chars.

Signed-off-by: Karel Zak <kzak@redhat.com>
include/strutils.h
lib/strutils.c

index ca2b0d9a251edcf6ab11c1fee1214df2e2a3a940..45c8f982419c6879559117ca1c3bbbdfee8de19c 100644 (file)
@@ -389,6 +389,8 @@ extern int strappend(char **a, const char *b);
 
 extern const char *split(const char **state, size_t *l, const char *separator, int quoted);
 
+extern char *ul_strchr_escaped(const char *s, int c);
+
 extern int skip_fline(FILE *fp);
 extern int ul_stralnumcmp(const char *p1, const char *p2);
 
index 2dcc03d149d6b1c0f1f825d350542f25b8eb2294..efa2505c07f5784ec3a2c805d1517e9dd1fd6542 100644 (file)
@@ -998,6 +998,37 @@ static size_t strcspn_escaped(const char *s, const char *reject)
         return n - escaped;
 }
 
+/*
+ * Like strchr() but ignores @c if escaped by '\', '\\' is interpreted like '\'.
+ *
+ * For example for @c='X':
+ *
+ *      "abcdXefgXh"    --> "XefgXh"
+ *     "abcd\XefgXh"   --> "Xh"
+ *     "abcd\\XefgXh"  --> "XefgXh"
+ *     "abcd\\\XefgXh" --> "Xh"
+ *     "abcd\Xefg\Xh"  --> (null)
+ *
+ *     "abcd\\XefgXh"  --> "\XefgXh"   for @c='\\'
+ */
+char *ul_strchr_escaped(const char *s, int c)
+{
+       char *p;
+       int esc = 0;
+
+       for (p = (char *) s; p && *p; p++) {
+               if (!esc && *p == '\\') {
+                       esc = 1;
+                       continue;
+               }
+               if (*p == c && (!esc || c == '\\'))
+                       return p;
+               esc = 0;
+       }
+
+       return NULL;
+}
+
 /* Split a string into words. */
 const char *split(const char **state, size_t *l, const char *separator, int quoted)
 {
@@ -1295,6 +1326,10 @@ int main(int argc, char *argv[])
                printf("'%s'-->%hu\n", argv[2], strtou16_or_err(argv[2], "strtou16 failed"));
                return EXIT_SUCCESS;
 
+       } else if (argc == 4 && strcmp(argv[1], "--strchr-escaped") == 0) {
+               printf("\"%s\" --> \"%s\"\n", argv[2], ul_strchr_escaped(argv[2], *argv[3]));
+               return EXIT_SUCCESS;
+
        } else {
                fprintf(stderr, "usage: %1$s --size <number>[suffix]\n"
                                "       %1$s --cmp-paths <path> <path>\n"