From e74bc2ed1da954d9a3ea3fd95351e7cc30c4df55 Mon Sep 17 00:00:00 2001 From: dmknght Date: Fri, 13 Nov 2020 15:11:02 +0700 Subject: [PATCH] Add glob matching --- src/fglob.nim | 5 ++ src/glob_matching.c | 129 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/fglob.nim create mode 100644 src/glob_matching.c diff --git a/src/fglob.nim b/src/fglob.nim new file mode 100644 index 0000000..ed0a40d --- /dev/null +++ b/src/fglob.nim @@ -0,0 +1,5 @@ +{.compile: "glob_matching.c".} + +proc g_match(s, p: cstring): cint {.importc.} + +echo g_match("abcdef", "bc") \ No newline at end of file diff --git a/src/glob_matching.c b/src/glob_matching.c new file mode 100644 index 0000000..4f0599d --- /dev/null +++ b/src/glob_matching.c @@ -0,0 +1,129 @@ +/* + * robust glob pattern matcher + * ozan s. yigit/dec 1994 + * public domain + * + * glob patterns: + * * matches zero or more characters + * ? matches any single character + * [set] matches any character in the set + * [!set] matches any character NOT in the set + * where a set is a group of characters or ranges. a range + * is written as two characters seperated with a hyphen: a-z denotes + * all characters between a to z inclusive. + * [-set] set matches a literal hypen and any character in the set + * []set] matches a literal close bracket and any character in the set + * + * char matches itself except where char is '*' or '?' or '[' + * \char matches char, including any pattern character + * + * examples: + * a*c ac abc abbc ... + * a?c acc abc aXc ... + * a[a-z]c aac abc acc ... + * a[-a-z]c a-c aac abc ... + * + */ + +#ifndef NEGATE +#define NEGATE '!' /* std cset negation char */ +#endif + +#define TRUE 1 +#define FALSE 0 + +int g_match (const char *str, const char *p) +{ + int negate; + int match; + int c; + + while (*p) { + if (!*str && *p != '*') + return FALSE; + + switch (c = *p++) { + + case '*': + while (*p == '*') + p++; + + if (!*p) + return TRUE; + + if (*p != '?' && *p != '[' && *p != '\\') + while (*str && *p != *str) + str++; + + while (*str) { + if (g_match (str, p)) + return TRUE; + str++; + } + return FALSE; + + case '?': + if (*str) + break; + return FALSE; +/* + * set specification is inclusive, that is [a-z] is a, z and + * everything in between. this means [z-a] may be interpreted + * as a set that contains z, a and nothing in between. + */ + case '[': + if (*p != NEGATE) + negate = FALSE; + else { + negate = TRUE; + p++; + } + + match = FALSE; + + while (!match && (c = *p++)) { + if (!*p) + return FALSE; + if (*p == '-') { /* c-c */ + if (!*++p) + return FALSE; + if (*p != ']') { + if (*str == c || *str == *p || + (*str > c && *str < *p)) + match = TRUE; + } + else { /* c-] */ + if (*str >= c) + match = TRUE; + break; + } + } + else { /* cc or c] */ + if (c == *str) + match = TRUE; + if (*p != ']') { + if (*p == *str) + match = TRUE; + } + else + break; + } + } + + if (negate == match) + return FALSE; +/* + * if there is a match, skip past the cset and continue on + */ + while (*p && *p != ']') + p++; + if (!*p++) /* oops! */ + return FALSE; + break; + + } + str++; + } + + return !*str; +} -- GitLab