mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
OutfixInfo: use boost::variant for engines
This commit is contained in:
parent
fa27025bcb
commit
32c866a8f9
@ -1776,11 +1776,13 @@ bool RoseBuildImpl::addOutfix(const NGHolder &h, const raw_som_dfa &haig) {
|
||||
|
||||
bool RoseBuildImpl::addOutfix(const raw_puff &rp) {
|
||||
if (!mpv_outfix) {
|
||||
mpv_outfix = make_unique<OutfixInfo>();
|
||||
mpv_outfix = make_unique<OutfixInfo>(MpvProto());
|
||||
mpv_outfix->chained = true;
|
||||
}
|
||||
|
||||
mpv_outfix->mpv.puffettes.push_back(rp);
|
||||
auto *mpv = mpv_outfix->mpv();
|
||||
assert(mpv);
|
||||
mpv->puffettes.push_back(rp);
|
||||
|
||||
mpv_outfix->maxBAWidth = ROSE_BOUND_INF; /* not ba */
|
||||
mpv_outfix->minWidth = min(mpv_outfix->minWidth, depth(rp.repeats));
|
||||
@ -1800,11 +1802,13 @@ bool RoseBuildImpl::addOutfix(const raw_puff &rp) {
|
||||
bool RoseBuildImpl::addChainTail(const raw_puff &rp, u32 *queue_out,
|
||||
u32 *event_out) {
|
||||
if (!mpv_outfix) {
|
||||
mpv_outfix = make_unique<OutfixInfo>();
|
||||
mpv_outfix = make_unique<OutfixInfo>(MpvProto());
|
||||
mpv_outfix->chained = true;
|
||||
}
|
||||
|
||||
mpv_outfix->mpv.triggered_puffettes.push_back(rp);
|
||||
auto *mpv = mpv_outfix->mpv();
|
||||
assert(mpv);
|
||||
mpv->triggered_puffettes.push_back(rp);
|
||||
|
||||
mpv_outfix->maxBAWidth = ROSE_BOUND_INF; /* not ba */
|
||||
mpv_outfix->minWidth = min(mpv_outfix->minWidth, depth(rp.repeats));
|
||||
@ -1816,7 +1820,7 @@ bool RoseBuildImpl::addChainTail(const raw_puff &rp, u32 *queue_out,
|
||||
* the caller */
|
||||
|
||||
*queue_out = mpv_outfix->get_queue(qif);
|
||||
*event_out = MQE_TOP_FIRST + mpv_outfix->mpv.triggered_puffettes.size() - 1;
|
||||
*event_out = MQE_TOP_FIRST + mpv->triggered_puffettes.size() - 1;
|
||||
|
||||
return true; /* failure is not yet an option */
|
||||
}
|
||||
|
@ -1264,14 +1264,14 @@ aligned_unique_ptr<NFA> buildOutfix(RoseBuildImpl &tbi, OutfixInfo &outfix) {
|
||||
const ReportManager &rm = tbi.rm;
|
||||
|
||||
aligned_unique_ptr<NFA> n;
|
||||
if (outfix.rdfa) {
|
||||
if (auto *rdfa = outfix.rdfa()) {
|
||||
// Unleash the McClellan!
|
||||
n = mcclellanCompile(*outfix.rdfa, cc);
|
||||
} else if (outfix.haig) {
|
||||
n = mcclellanCompile(*rdfa, cc);
|
||||
} else if (auto *haig = outfix.haig()) {
|
||||
// Unleash the Goughfish!
|
||||
n = goughCompile(*outfix.haig, tbi.ssm.somPrecision(), cc);
|
||||
} else if (outfix.holder) {
|
||||
NGHolder &h = *outfix.holder;
|
||||
n = goughCompile(*haig, tbi.ssm.somPrecision(), cc);
|
||||
} else if (auto *holder = outfix.holder()) {
|
||||
NGHolder &h = *holder;
|
||||
assert(h.kind == NFA_OUTFIX);
|
||||
|
||||
// Build NFA.
|
||||
@ -1294,8 +1294,8 @@ aligned_unique_ptr<NFA> buildOutfix(RoseBuildImpl &tbi, OutfixInfo &outfix) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!outfix.mpv.puffettes.empty()) {
|
||||
assert(0);
|
||||
} else if (auto *mpv = outfix.mpv()) {
|
||||
assert(mpv->puffettes.empty());
|
||||
}
|
||||
|
||||
if (n && tbi.cc.grey.reverseAccelerate) {
|
||||
@ -1310,34 +1310,36 @@ void prepMpv(RoseBuildImpl &tbi, build_context &bc, size_t *historyRequired,
|
||||
bool *mpv_as_outfix) {
|
||||
assert(bc.engineOffsets.empty()); // MPV should be first
|
||||
*mpv_as_outfix = false;
|
||||
OutfixInfo *mpv = nullptr;
|
||||
OutfixInfo *mpv_outfix = nullptr;
|
||||
|
||||
/* assume outfixes are just above chain tails in queue indices */
|
||||
for (auto &out : tbi.outfixes) {
|
||||
if (out.is_nonempty_mpv()) {
|
||||
assert(!mpv);
|
||||
mpv = &out;
|
||||
assert(!mpv_outfix);
|
||||
mpv_outfix = &out;
|
||||
} else {
|
||||
assert(!out.chained);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mpv) {
|
||||
if (!mpv_outfix) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(mpv->chained);
|
||||
auto nfa = mpvCompile(mpv->mpv.puffettes, mpv->mpv.triggered_puffettes);
|
||||
assert(mpv_outfix->chained);
|
||||
auto *mpv = mpv_outfix->mpv();
|
||||
auto nfa = mpvCompile(mpv->puffettes, mpv->triggered_puffettes);
|
||||
assert(nfa);
|
||||
if (!nfa) {
|
||||
throw CompileError("Unable to generate bytecode.");
|
||||
}
|
||||
|
||||
if (tbi.cc.grey.reverseAccelerate) {
|
||||
buildReverseAcceleration(nfa.get(), mpv->rev_info, mpv->minWidth);
|
||||
buildReverseAcceleration(nfa.get(), mpv_outfix->rev_info,
|
||||
mpv_outfix->minWidth);
|
||||
}
|
||||
|
||||
u32 qi = mpv->get_queue(tbi.qif);
|
||||
u32 qi = mpv_outfix->get_queue(tbi.qif);
|
||||
nfa->queueIndex = qi;
|
||||
|
||||
DEBUG_PRINTF("built mpv\n");
|
||||
@ -1347,7 +1349,7 @@ void prepMpv(RoseBuildImpl &tbi, build_context &bc, size_t *historyRequired,
|
||||
}
|
||||
|
||||
add_nfa_to_blob(bc, *nfa);
|
||||
*mpv_as_outfix = !mpv->mpv.puffettes.empty();
|
||||
*mpv_as_outfix = !mpv->puffettes.empty();
|
||||
}
|
||||
|
||||
static
|
||||
@ -1387,8 +1389,7 @@ bool prepOutfixes(RoseBuildImpl &tbi, build_context &bc,
|
||||
if (out.chained) {
|
||||
continue; /* already done */
|
||||
}
|
||||
DEBUG_PRINTF("building outfix %zd (holder %p rdfa %p)\n",
|
||||
&out - &tbi.outfixes[0], out.holder.get(), out.rdfa.get());
|
||||
DEBUG_PRINTF("building outfix %zd\n", &out - &tbi.outfixes[0]);
|
||||
auto n = buildOutfix(tbi, out);
|
||||
if (!n) {
|
||||
assert(0);
|
||||
|
@ -1904,8 +1904,8 @@ bool extractSEPLiterals(const OutfixInfo &outfix, const ReportManager &rm,
|
||||
// SEP cases should always become DFAs, so that's the only extract code we
|
||||
// have implemented here.
|
||||
|
||||
if (outfix.rdfa) {
|
||||
return extractSEPLiterals(*outfix.rdfa, lits_out);
|
||||
if (outfix.rdfa()) {
|
||||
return extractSEPLiterals(*outfix.rdfa(), lits_out);
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("cannot extract literals from outfix type\n");
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include <vector>
|
||||
#include <boost/bimap.hpp>
|
||||
#include <boost/functional/hash/hash.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
struct RoseEngine;
|
||||
|
||||
@ -302,17 +303,11 @@ struct MpvProto {
|
||||
std::vector<raw_puff> triggered_puffettes;
|
||||
};
|
||||
|
||||
struct OutfixInfo { /* TODO: poly */
|
||||
OutfixInfo() {}
|
||||
explicit OutfixInfo(std::unique_ptr<raw_dfa> r) : rdfa(std::move(r)) {
|
||||
assert(rdfa);
|
||||
}
|
||||
explicit OutfixInfo(std::unique_ptr<NGHolder> h) : holder(std::move(h)) {
|
||||
assert(holder);
|
||||
}
|
||||
explicit OutfixInfo(std::unique_ptr<raw_som_dfa> r) : haig(std::move(r)) {
|
||||
assert(haig);
|
||||
}
|
||||
struct OutfixInfo {
|
||||
template<class T>
|
||||
explicit OutfixInfo(std::unique_ptr<T> x) : proto(std::move(x)) {}
|
||||
|
||||
explicit OutfixInfo(MpvProto mpv) : proto(std::move(mpv)) {}
|
||||
|
||||
u32 get_queue(QueueIndexFactory &qif);
|
||||
|
||||
@ -322,25 +317,68 @@ struct OutfixInfo { /* TODO: poly */
|
||||
}
|
||||
|
||||
bool is_nonempty_mpv() const {
|
||||
return !mpv.empty();
|
||||
auto *mpv = boost::get<MpvProto>(&proto);
|
||||
return mpv && !mpv->empty();
|
||||
}
|
||||
|
||||
bool is_dead() const {
|
||||
return !holder && !rdfa && !haig && mpv.empty();
|
||||
auto *mpv = boost::get<MpvProto>(&proto);
|
||||
if (mpv) {
|
||||
return mpv->empty();
|
||||
}
|
||||
return boost::get<boost::blank>(&proto) != nullptr;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
holder.reset();
|
||||
rdfa.reset();
|
||||
haig.reset();
|
||||
mpv.reset();
|
||||
assert(is_dead());
|
||||
proto = boost::blank();
|
||||
}
|
||||
|
||||
std::unique_ptr<NGHolder> holder;
|
||||
std::unique_ptr<raw_dfa> rdfa;
|
||||
std::unique_ptr<raw_som_dfa> haig;
|
||||
MpvProto mpv;
|
||||
// Convenience accessor functions.
|
||||
|
||||
NGHolder *holder() {
|
||||
auto *up = boost::get<std::unique_ptr<NGHolder>>(&proto);
|
||||
return up ? up->get() : nullptr;
|
||||
}
|
||||
raw_dfa *rdfa() {
|
||||
auto *up = boost::get<std::unique_ptr<raw_dfa>>(&proto);
|
||||
return up ? up->get() : nullptr;
|
||||
}
|
||||
raw_som_dfa *haig() {
|
||||
auto *up = boost::get<std::unique_ptr<raw_som_dfa>>(&proto);
|
||||
return up ? up->get() : nullptr;
|
||||
}
|
||||
MpvProto *mpv() {
|
||||
return boost::get<MpvProto>(&proto);
|
||||
}
|
||||
|
||||
// Convenience const accessor functions.
|
||||
|
||||
const NGHolder *holder() const {
|
||||
auto *up = boost::get<std::unique_ptr<NGHolder>>(&proto);
|
||||
return up ? up->get() : nullptr;
|
||||
}
|
||||
const raw_dfa *rdfa() const {
|
||||
auto *up = boost::get<std::unique_ptr<raw_dfa>>(&proto);
|
||||
return up ? up->get() : nullptr;
|
||||
}
|
||||
const raw_som_dfa *haig() const {
|
||||
auto *up = boost::get<std::unique_ptr<raw_som_dfa>>(&proto);
|
||||
return up ? up->get() : nullptr;
|
||||
}
|
||||
const MpvProto *mpv() const {
|
||||
return boost::get<MpvProto>(&proto);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Variant wrapping the various engine types. If this is
|
||||
* boost::blank, it means that this outfix is unused (dead).
|
||||
*/
|
||||
boost::variant<
|
||||
boost::blank,
|
||||
std::unique_ptr<NGHolder>,
|
||||
std::unique_ptr<raw_dfa>,
|
||||
std::unique_ptr<raw_som_dfa>,
|
||||
MpvProto> proto = boost::blank();
|
||||
|
||||
RevAccInfo rev_info;
|
||||
u32 maxBAWidth = 0; //!< max bi-anchored width
|
||||
|
@ -2451,8 +2451,9 @@ void mergeOutfixNfas(RoseBuildImpl &tbi, vector<NGHolder *> &nfas) {
|
||||
|
||||
map<NGHolder *, size_t> nfa_mapping;
|
||||
for (size_t i = 0; i < outfixes.size(); i++) {
|
||||
if (outfixes[i].holder) {
|
||||
nfa_mapping[outfixes[i].holder.get()] = i;
|
||||
auto *holder = outfixes[i].holder();
|
||||
if (holder) {
|
||||
nfa_mapping[holder] = i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2485,7 +2486,7 @@ struct MergeMcClellan {
|
||||
}
|
||||
|
||||
static void transfer(OutfixInfo &outfix, unique_ptr<raw_dfa> d) {
|
||||
outfix.rdfa = move(d);
|
||||
outfix.proto = move(d);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -2503,7 +2504,7 @@ struct MergeHaig {
|
||||
}
|
||||
|
||||
static void transfer(OutfixInfo &outfix, unique_ptr<raw_som_dfa> d) {
|
||||
outfix.haig = move(d);
|
||||
outfix.proto = move(d);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -2602,8 +2603,9 @@ void mergeOutfixDfas(RoseBuildImpl &tbi, vector<raw_dfa *> &dfas) {
|
||||
* element addition. */
|
||||
ue2::unordered_map<raw_dfa *, size_t> dfa_mapping;
|
||||
for (size_t i = 0; i < outfixes.size(); i++) {
|
||||
if (outfixes[i].rdfa) {
|
||||
dfa_mapping[outfixes[i].rdfa.get()] = i;
|
||||
auto *rdfa = outfixes[i].rdfa();
|
||||
if (rdfa) {
|
||||
dfa_mapping[rdfa] = i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2624,10 +2626,10 @@ void mergeOutfixCombo(RoseBuildImpl &tbi, const ReportManager &rm,
|
||||
bool seen_dfa = false;
|
||||
u32 nfa_count = 0;
|
||||
for (const auto &outfix : tbi.outfixes) {
|
||||
if (outfix.holder) {
|
||||
if (outfix.holder()) {
|
||||
DEBUG_PRINTF("nfa\n");
|
||||
nfa_count++;
|
||||
} else if (outfix.rdfa) {
|
||||
} else if (outfix.rdfa()) {
|
||||
DEBUG_PRINTF("dfa\n");
|
||||
seen_dfa = true;
|
||||
}
|
||||
@ -2647,27 +2649,29 @@ void mergeOutfixCombo(RoseBuildImpl &tbi, const ReportManager &rm,
|
||||
vector<raw_dfa *> dfas;
|
||||
|
||||
for (auto it = tbi.outfixes.begin(); it != tbi.outfixes.end(); ++it) {
|
||||
assert(!it->is_dead());
|
||||
assert(!it->chained);
|
||||
if (it->rdfa) {
|
||||
dfas.push_back(it->rdfa.get());
|
||||
dfa_mapping[it->rdfa.get()] = it - tbi.outfixes.begin();
|
||||
auto &outfix = *it;
|
||||
assert(!outfix.is_dead());
|
||||
assert(!outfix.chained);
|
||||
|
||||
if (outfix.rdfa()) {
|
||||
auto *rdfa = outfix.rdfa();
|
||||
dfas.push_back(rdfa);
|
||||
dfa_mapping[rdfa] = it - tbi.outfixes.begin();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!it->holder) {
|
||||
if (!outfix.holder()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NGHolder *h = it->holder.get();
|
||||
NGHolder *h = outfix.holder();
|
||||
assert(h->kind == NFA_OUTFIX);
|
||||
auto rdfa = buildMcClellan(*h, &rm, grey);
|
||||
if (rdfa) {
|
||||
// Transform this outfix into a DFA and add it to the merge set.
|
||||
dfa_mapping[rdfa.get()] = it - tbi.outfixes.begin();
|
||||
dfas.push_back(rdfa.get());
|
||||
it->clear();
|
||||
it->rdfa = move(rdfa);
|
||||
outfix.proto = move(rdfa);
|
||||
new_dfas++;
|
||||
}
|
||||
}
|
||||
@ -2695,8 +2699,9 @@ void mergeOutfixHaigs(RoseBuildImpl &tbi, vector<raw_som_dfa *> &dfas,
|
||||
|
||||
ue2::unordered_map<raw_som_dfa *, size_t> dfa_mapping;
|
||||
for (size_t i = 0; i < outfixes.size(); i++) {
|
||||
if (outfixes[i].haig) {
|
||||
dfa_mapping[outfixes[i].haig.get()] = i;
|
||||
auto *haig = outfixes[i].haig();
|
||||
if (haig) {
|
||||
dfa_mapping[haig] = i;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2721,14 +2726,14 @@ void mergeOutfixes(RoseBuildImpl &tbi) {
|
||||
vector<raw_dfa *> dfas;
|
||||
vector<raw_som_dfa *> som_dfas;
|
||||
|
||||
for (const auto &outfix : tbi.outfixes) {
|
||||
for (auto &outfix : tbi.outfixes) {
|
||||
assert(!outfix.chained);
|
||||
if (outfix.rdfa) {
|
||||
dfas.push_back(outfix.rdfa.get());
|
||||
} else if (outfix.holder) {
|
||||
nfas.push_back(outfix.holder.get());
|
||||
} else if (outfix.haig) {
|
||||
som_dfas.push_back(outfix.haig.get());
|
||||
if (outfix.rdfa()) {
|
||||
dfas.push_back(outfix.rdfa());
|
||||
} else if (outfix.holder()) {
|
||||
nfas.push_back(outfix.holder());
|
||||
} else if (outfix.haig()) {
|
||||
som_dfas.push_back(outfix.haig());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -631,10 +631,11 @@ RoseDedupeAuxImpl::RoseDedupeAuxImpl(const RoseBuildImpl &tbi_in)
|
||||
}
|
||||
|
||||
if (tbi.mpv_outfix) {
|
||||
for (const auto &puff : tbi.mpv_outfix->mpv.puffettes) {
|
||||
auto *mpv = tbi.mpv_outfix->mpv();
|
||||
for (const auto &puff : mpv->puffettes) {
|
||||
puff_map[puff.report].insert(&puff);
|
||||
}
|
||||
for (const auto &puff : tbi.mpv_outfix->mpv.triggered_puffettes) {
|
||||
for (const auto &puff : mpv->triggered_puffettes) {
|
||||
puff_map[puff.report].insert(&puff);
|
||||
}
|
||||
}
|
||||
@ -785,12 +786,13 @@ bool RoseDedupeAuxImpl::requiresDedupeSupport(
|
||||
}
|
||||
has_outfix = true;
|
||||
|
||||
if (out.haig) {
|
||||
if (out.haig()) {
|
||||
return true; /* haig may report matches with different SOM at the
|
||||
same offset */
|
||||
}
|
||||
|
||||
if (out.holder && requiresDedupe(*out.holder, reports, tbi.cc.grey)) {
|
||||
if (out.holder() &&
|
||||
requiresDedupe(*out.holder(), reports, tbi.cc.grey)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -874,25 +876,33 @@ u32 OutfixInfo::get_queue(QueueIndexFactory &qif) {
|
||||
return queue;
|
||||
}
|
||||
|
||||
namespace {
|
||||
class OutfixAllReports : public boost::static_visitor<set<ReportID>> {
|
||||
public:
|
||||
set<ReportID> operator()(const boost::blank &) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
set<ReportID> operator()(const unique_ptr<T> &x) const {
|
||||
return all_reports(*x);
|
||||
}
|
||||
|
||||
set<ReportID> operator()(const MpvProto &mpv) const {
|
||||
set<ReportID> reports;
|
||||
for (const auto &puff : mpv.puffettes) {
|
||||
reports.insert(puff.report);
|
||||
}
|
||||
for (const auto &puff : mpv.triggered_puffettes) {
|
||||
reports.insert(puff.report);
|
||||
}
|
||||
return reports;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
set<ReportID> all_reports(const OutfixInfo &outfix) {
|
||||
set<ReportID> reports;
|
||||
if (outfix.holder) {
|
||||
insert(&reports, all_reports(*outfix.holder));
|
||||
}
|
||||
if (outfix.rdfa) {
|
||||
insert(&reports, all_reports(*outfix.rdfa));
|
||||
}
|
||||
if (outfix.haig) {
|
||||
insert(&reports, all_reports(*outfix.haig));
|
||||
}
|
||||
|
||||
for (const auto &puff : outfix.mpv.puffettes) {
|
||||
reports.insert(puff.report);
|
||||
}
|
||||
for (const auto &puff : outfix.mpv.triggered_puffettes) {
|
||||
reports.insert(puff.report);
|
||||
}
|
||||
|
||||
auto reports = boost::apply_visitor(OutfixAllReports(), outfix.proto);
|
||||
assert(!reports.empty());
|
||||
return reports;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user