diff --git a/cockatrice/src/game/filters/filter_string.cpp b/cockatrice/src/game/filters/filter_string.cpp index 3d168d64c..3a1a11246 100644 --- a/cockatrice/src/game/filters/filter_string.cpp +++ b/cockatrice/src/game/filters/filter_string.cpp @@ -4,10 +4,16 @@ #include #include +#include +#include #include #include #include +// Static cache for compiled regexes to avoid recompilation +static QHash regexCache; +static QMutex regexCacheMutex; + static peg::parser search(R"( Start <- QueryPartList ~ws <- [ ]+ @@ -189,10 +195,24 @@ static void setupParserRules() }; search["StringValue"] = [](const peg::SemanticValues &sv) -> StringMatcher { - // Helper function for word boundary matching - auto createWordBoundaryMatcher = [](const QString &target) { + // Helper function for word boundary matching with caching + auto createWordBoundaryMatcher = [](const QString &target) -> std::function { QString pattern = QString("\\b%1\\b").arg(QRegularExpression::escape(target)); + + // Check cache first with thread safety + QMutexLocker locker(®exCacheMutex); + auto it = regexCache.find(pattern); + if (it != regexCache.end()) { + QRegularExpression cachedRegex = it.value(); + locker.unlock(); + return [cachedRegex](const QString &s) { return cachedRegex.match(s).hasMatch(); }; + } + + // Compile new regex and add to cache QRegularExpression regex(pattern, QRegularExpression::CaseInsensitiveOption); + regexCache.insert(pattern, regex); + locker.unlock(); + return [regex](const QString &s) { return regex.match(s).hasMatch(); }; };