perf tools: Enhance glob string matching
authorMasami Hiramatsu <mhiramat@redhat.com>
Tue, 5 Jan 2010 22:47:24 +0000 (17:47 -0500)
committerIngo Molnar <mingo@elte.hu>
Wed, 13 Jan 2010 09:09:14 +0000 (10:09 +0100)
Enhance strglobmatch() for supporting character classes([CHARS],
complementation and ranges are also supported) and escaped
special characters (\*, \? etc).

Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: systemtap <systemtap@sources.redhat.com>
Cc: DLE <dle-develop@lists.sourceforge.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20100105224724.19431.56271.stgit@dhcp-100-2-132.bos.redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
tools/perf/util/string.c

index 5352d7d..c397d4f 100644 (file)
@@ -227,16 +227,73 @@ fail:
        return NULL;
 }
 
-/* Glob expression pattern matching */
+/* Character class matching */
+static bool __match_charclass(const char *pat, char c, const char **npat)
+{
+       bool complement = false, ret = true;
+
+       if (*pat == '!') {
+               complement = true;
+               pat++;
+       }
+       if (*pat++ == c)        /* First character is special */
+               goto end;
+
+       while (*pat && *pat != ']') {   /* Matching */
+               if (*pat == '-' && *(pat + 1) != ']') { /* Range */
+                       if (*(pat - 1) <= c && c <= *(pat + 1))
+                               goto end;
+                       if (*(pat - 1) > *(pat + 1))
+                               goto error;
+                       pat += 2;
+               } else if (*pat++ == c)
+                       goto end;
+       }
+       if (!*pat)
+               goto error;
+       ret = false;
+
+end:
+       while (*pat && *pat != ']')     /* Searching closing */
+               pat++;
+       if (!*pat)
+               goto error;
+       *npat = pat + 1;
+       return complement ? !ret : ret;
+
+error:
+       return false;
+}
+
+/**
+ * strglobmatch - glob expression pattern matching
+ * @str: the target string to match
+ * @pat: the pattern string to match
+ *
+ * This returns true if the @str matches @pat. @pat can includes wildcards
+ * ('*','?') and character classes ([CHARS], complementation and ranges are
+ * also supported). Also, this supports escape character ('\') to use special
+ * characters as normal character.
+ *
+ * Note: if @pat syntax is broken, this always returns false.
+ */
 bool strglobmatch(const char *str, const char *pat)
 {
        while (*str && *pat && *pat != '*') {
-               if (*pat == '?') {
+               if (*pat == '?') {      /* Matches any single character */
                        str++;
                        pat++;
-               } else
-                       if (*str++ != *pat++)
+                       continue;
+               } else if (*pat == '[') /* Character classes/Ranges */
+                       if (__match_charclass(pat + 1, *str, &pat)) {
+                               str++;
+                               continue;
+                       } else
                                return false;
+               else if (*pat == '\\') /* Escaped char match as normal char */
+                       pat++;
+               if (*str++ != *pat++)
+                       return false;
        }
        /* Check wild card */
        if (*pat == '*') {