#include "glob.hpp" 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; }