diff options
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/eval.hh | 4 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 8 |
2 files changed, 9 insertions, 3 deletions
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index cabc92d15..34a212aa4 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -114,6 +114,9 @@ private: /* Cache used by checkSourcePath(). */ std::unordered_map<Path, Path> resolvedPaths; + /* Cache used by prim_match(). */ + std::unordered_map<std::string, std::regex> regexCache; + public: EvalState(const Strings & _searchPath, ref<Store> store); @@ -314,6 +317,7 @@ private: friend struct ExprOpConcatLists; friend struct ExprSelect; friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v); + friend void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v); }; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 29302c9b6..4cd28698c 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1811,19 +1811,21 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args, /* Match a regular expression against a string and return either ‘null’ or a list containing substring matches. */ -static void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v) +void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v) { auto re = state.forceStringNoCtx(*args[0], pos); try { - std::regex regex(re, std::regex::extended); + auto regex = state.regexCache.find(re); + if (regex == state.regexCache.end()) + regex = state.regexCache.emplace(re, std::regex(re, std::regex::extended)).first; PathSet context; const std::string str = state.forceString(*args[1], context, pos); std::smatch match; - if (!std::regex_match(str, match, regex)) { + if (!std::regex_match(str, match, regex->second)) { mkNull(v); return; } |