137 lines
2.2 KiB
C++
137 lines
2.2 KiB
C++
#ifndef GLOB_HPP
|
|
#define GLOB_HPP
|
|
|
|
enum class Glob_Result
|
|
{
|
|
OOM_ERROR,
|
|
ENCODING_ERROR,
|
|
SYNTAX_ERROR,
|
|
UNMATCHED,
|
|
MATCHED,
|
|
};
|
|
|
|
// https://github.com/tsoding/glob.h
|
|
Glob_Result glob(const char *pattern, const char *text);
|
|
|
|
#endif // GLOB_HPP
|
|
|
|
#ifdef GLOB_IMPLEMENTATION
|
|
|
|
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;
|
|
}
|
|
#endif // GLOB_IMPLEMENTATION
|