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));
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));
* 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 */
}
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.
}
}
}
- } else if (!outfix.mpv.puffettes.empty()) {
- assert(0);
+ } else if (auto *mpv = outfix.mpv()) {
+ assert(mpv->puffettes.empty());
}
if (n && tbi.cc.grey.reverseAccelerate) {
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");
}
add_nfa_to_blob(bc, *nfa);
- *mpv_as_outfix = !mpv->mpv.puffettes.empty();
+ *mpv_as_outfix = !mpv->puffettes.empty();
}
static
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);
// 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");
#include <vector>
#include <boost/bimap.hpp>
#include <boost/functional/hash/hash.hpp>
+#include <boost/variant.hpp>
struct RoseEngine;
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);
}
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();
+ }
+
+ // 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);
}
- std::unique_ptr<NGHolder> holder;
- std::unique_ptr<raw_dfa> rdfa;
- std::unique_ptr<raw_som_dfa> haig;
- MpvProto mpv;
+ /**
+ * \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
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;
}
}
}
static void transfer(OutfixInfo &outfix, unique_ptr<raw_dfa> d) {
- outfix.rdfa = move(d);
+ outfix.proto = move(d);
}
private:
}
static void transfer(OutfixInfo &outfix, unique_ptr<raw_som_dfa> d) {
- outfix.haig = move(d);
+ outfix.proto = move(d);
}
private:
* 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;
}
}
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;
}
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++;
}
}
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;
}
}
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());
}
}
}
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);
}
}
}
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;
}
}
return queue;
}
-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));
+namespace {
+class OutfixAllReports : public boost::static_visitor<set<ReportID>> {
+public:
+ set<ReportID> operator()(const boost::blank &) const {
+ return {};
}
- for (const auto &puff : outfix.mpv.puffettes) {
- reports.insert(puff.report);
+ template<class T>
+ set<ReportID> operator()(const unique_ptr<T> &x) const {
+ return all_reports(*x);
}
- for (const auto &puff : outfix.mpv.triggered_puffettes) {
- reports.insert(puff.report);
+
+ 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) {
+ auto reports = boost::apply_visitor(OutfixAllReports(), outfix.proto);
assert(!reports.empty());
return reports;
}