94 lines
1.8 KiB
C++
94 lines
1.8 KiB
C++
#include "glob.h"
|
|
|
|
Glob_Result glob(const char* pattern, const char* text)
|
|
{
|
|
while (*pattern != '\0' && *text != '\0') {
|
|
switch (*pattern) {
|
|
case '?': {
|
|
pattern += 1;
|
|
text += 1;
|
|
}
|
|
break;
|
|
|
|
case '*': {
|
|
Glob_Result result = glob(pattern + 1, text);
|
|
if (result != Glob_Result::UNMATCHED) return result;
|
|
text += 1;
|
|
}
|
|
break;
|
|
|
|
case '[': {
|
|
bool matched = false;
|
|
bool negate = false;
|
|
|
|
pattern += 1; // skipping [
|
|
if (*pattern == '\0') return Glob_Result::SYNTAX_ERROR; // unclosed [
|
|
|
|
if (*pattern == '!') {
|
|
negate = true;
|
|
pattern += 1;
|
|
if (*pattern == '\0') return Glob_Result::SYNTAX_ERROR; // unclosed [
|
|
}
|
|
|
|
char prev = *pattern;
|
|
matched |= prev == *text;
|
|
pattern += 1;
|
|
|
|
while (*pattern != ']' && *pattern != '\0') {
|
|
switch (*pattern) {
|
|
case '-': {
|
|
pattern += 1;
|
|
switch (*pattern) {
|
|
case ']':
|
|
matched |= '-' == *text;
|
|
break;
|
|
case '\0':
|
|
return Glob_Result::SYNTAX_ERROR; // unclosed [
|
|
default: {
|
|
matched |= prev <= *text && *text <= *pattern;
|
|
prev = *pattern;
|
|
pattern += 1;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default: {
|
|
prev = *pattern;
|
|
matched |= prev == *text;
|
|
pattern += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (*pattern != ']') return Glob_Result::SYNTAX_ERROR; // unclosed [
|
|
if (negate) matched = !matched;
|
|
if (!matched) return Glob_Result::UNMATCHED;
|
|
|
|
pattern += 1;
|
|
text += 1;
|
|
}
|
|
break;
|
|
|
|
case '\\':
|
|
pattern += 1;
|
|
if (*pattern == '\0') return Glob_Result::SYNTAX_ERROR; // unfinished escape
|
|
// fallthrough
|
|
default: {
|
|
if (*pattern == *text) {
|
|
pattern += 1;
|
|
text += 1;
|
|
}
|
|
else {
|
|
return Glob_Result::UNMATCHED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (*text == '\0') {
|
|
while (*pattern == '*') pattern += 1;
|
|
if (*pattern == '\0') return Glob_Result::MATCHED;
|
|
}
|
|
|
|
return Glob_Result::UNMATCHED;
|
|
} |