#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