|
@@ -227,16 +227,73 @@ fail:
|
|
return NULL;
|
|
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)
|
|
bool strglobmatch(const char *str, const char *pat)
|
|
{
|
|
{
|
|
while (*str && *pat && *pat != '*') {
|
|
while (*str && *pat && *pat != '*') {
|
|
- if (*pat == '?') {
|
|
|
|
|
|
+ if (*pat == '?') { /* Matches any single character */
|
|
str++;
|
|
str++;
|
|
pat++;
|
|
pat++;
|
|
- } else
|
|
|
|
- if (*str++ != *pat++)
|
|
|
|
|
|
+ continue;
|
|
|
|
+ } else if (*pat == '[') /* Character classes/Ranges */
|
|
|
|
+ if (__match_charclass(pat + 1, *str, &pat)) {
|
|
|
|
+ str++;
|
|
|
|
+ continue;
|
|
|
|
+ } else
|
|
return false;
|
|
return false;
|
|
|
|
+ else if (*pat == '\\') /* Escaped char match as normal char */
|
|
|
|
+ pat++;
|
|
|
|
+ if (*str++ != *pat++)
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
/* Check wild card */
|
|
/* Check wild card */
|
|
if (*pat == '*') {
|
|
if (*pat == '*') {
|