From: Karel Zak Date: Mon, 2 May 2022 13:07:42 +0000 (+0200) Subject: lib/strutils: add ul_strchr_escaped() X-Git-Tag: v2.38.1~55 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b144dfa04eb6322b6cd717beb861c6cd8664e613;p=thirdparty%2Futil-linux.git lib/strutils: add ul_strchr_escaped() Like strchr(), but ignores escaped chars. Signed-off-by: Karel Zak --- diff --git a/include/strutils.h b/include/strutils.h index ae689a30ad..ea102723d8 100644 --- a/include/strutils.h +++ b/include/strutils.h @@ -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); diff --git a/lib/strutils.c b/lib/strutils.c index e85d265d2d..104eb3887d 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -1035,6 +1035,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) { @@ -1262,6 +1293,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 [suffix]\n" " %1$s --cmp-paths \n"