This commit is contained in:
Eelco Dolstra 2016-10-19 16:32:24 +02:00
commit 795d9b8668
5 changed files with 16 additions and 93 deletions

View file

@ -33,8 +33,8 @@ DrvName::DrvName(const string & s) : hits(0)
bool DrvName::matches(DrvName & n) bool DrvName::matches(DrvName & n)
{ {
if (name != "*") { if (name != "*") {
if (!regex) regex = std::shared_ptr<Regex>(new Regex(name)); if (!regex) regex = std::unique_ptr<std::regex>(new std::regex(name, std::regex::extended));
if (!regex->matches(n.name)) return false; if (!std::regex_match(n.name, *regex)) return false;
} }
if (version != "" && version != n.version) return false; if (version != "" && version != n.version) return false;
return true; return true;

View file

@ -3,7 +3,7 @@
#include <memory> #include <memory>
#include "types.hh" #include "types.hh"
#include "regex.hh" #include <regex>
namespace nix { namespace nix {
@ -19,7 +19,7 @@ struct DrvName
bool matches(DrvName & n); bool matches(DrvName & n);
private: private:
std::shared_ptr<Regex> regex; std::unique_ptr<std::regex> regex;
}; };
typedef list<DrvName> DrvNames; typedef list<DrvName> DrvNames;

View file

@ -18,6 +18,7 @@
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <regex>
#include <dlfcn.h> #include <dlfcn.h>
@ -1618,25 +1619,26 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args,
null or a list containing substring matches. */ null or a list containing substring matches. */
static void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v) static void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v)
{ {
Regex regex(state.forceStringNoCtx(*args[0], pos), true); std::regex regex(state.forceStringNoCtx(*args[0], pos), std::regex::extended);
PathSet context; PathSet context;
string s = state.forceString(*args[1], context, pos); const std::string str = state.forceString(*args[1], context, pos);
Regex::Subs subs;
if (!regex.matches(s, subs)) { std::smatch match;
if (!std::regex_match(str, match, regex)) {
mkNull(v); mkNull(v);
return; return;
} }
unsigned int len = subs.empty() ? 0 : subs.rbegin()->first + 1; // the first match is the whole string
const size_t len = match.size() - 1;
state.mkList(v, len); state.mkList(v, len);
for (unsigned int n = 0; n < len; ++n) { for (size_t i = 0; i < len; ++i) {
auto i = subs.find(n); if (!match[i+1].matched)
if (i == subs.end()) mkNull(*(v.listElems()[i] = state.allocValue()));
mkNull(*(v.listElems()[n] = state.allocValue()));
else else
mkString(*(v.listElems()[n] = state.allocValue()), i->second); mkString(*(v.listElems()[i] = state.allocValue()), match[i + 1].str().c_str());
} }
} }

View file

@ -1,50 +0,0 @@
#include "regex.hh"
#include "types.hh"
#include <algorithm>
namespace nix {
Regex::Regex(const string & pattern, bool subs)
{
/* Patterns must match the entire string. */
int err = regcomp(&preg, ("^(" + pattern + ")$").c_str(), (subs ? 0 : REG_NOSUB) | REG_EXTENDED);
if (err) throw RegexError(format("compiling pattern %1%: %2%") % pattern % showError(err));
nrParens = subs ? std::count(pattern.begin(), pattern.end(), '(') : 0;
}
Regex::~Regex()
{
regfree(&preg);
}
bool Regex::matches(const string & s)
{
int err = regexec(&preg, s.c_str(), 0, 0, 0);
if (err == 0) return true;
else if (err == REG_NOMATCH) return false;
throw Error(format("matching string %1%: %2%") % s % showError(err));
}
bool Regex::matches(const string & s, Subs & subs)
{
regmatch_t pmatch[nrParens + 2];
int err = regexec(&preg, s.c_str(), nrParens + 2, pmatch, 0);
if (err == 0) {
for (unsigned int n = 2; n < nrParens + 2; ++n)
if (pmatch[n].rm_eo != -1)
subs[n - 2] = string(s, pmatch[n].rm_so, pmatch[n].rm_eo - pmatch[n].rm_so);
return true;
}
else if (err == REG_NOMATCH) return false;
throw Error(format("matching string %1%: %2%") % s % showError(err));
}
string Regex::showError(int err)
{
char buf[256];
regerror(err, &preg, buf, sizeof(buf));
return string(buf);
}
}

View file

@ -1,29 +0,0 @@
#pragma once
#include "types.hh"
#include <sys/types.h>
#include <regex.h>
#include <map>
namespace nix {
MakeError(RegexError, Error)
class Regex
{
public:
Regex(const string & pattern, bool subs = false);
~Regex();
bool matches(const string & s);
typedef std::map<unsigned int, string> Subs;
bool matches(const string & s, Subs & subs);
private:
unsigned nrParens;
regex_t preg;
string showError(int err);
};
}