rose: replace RoseLiteralMap use of bimap

This apoproach is simpler and more efficient for cases with large
numbers of literals.
This commit is contained in:
Justin Viiret 2017-04-26 15:12:27 +10:00 committed by Matthew Barr
parent a75b2ba2e5
commit 8b9328fe9e
15 changed files with 198 additions and 154 deletions

View File

@ -295,7 +295,7 @@ void createVertices(RoseBuildImpl *tbi,
if (bd.som && !g[w].left.haig) {
/* no prefix - som based on literal start */
assert(!prefix_graph);
g[w].som_adjust = tbi->literals.right.at(literalId).elength();
g[w].som_adjust = tbi->literals.at(literalId).elength();
DEBUG_PRINTF("set som_adjust to %u\n", g[w].som_adjust);
}
@ -333,7 +333,7 @@ void createVertices(RoseBuildImpl *tbi,
u32 ghostId = tbi->literal_info[literalId].undelayed_id;
DEBUG_PRINTF("creating delay ghost vertex, id=%u\n", ghostId);
assert(ghostId != literalId);
assert(tbi->literals.right.at(ghostId).delay == 0);
assert(tbi->literals.at(ghostId).delay == 0);
// Adjust offsets, removing delay.
u32 ghost_min = min_offset, ghost_max = max_offset;
@ -1907,16 +1907,20 @@ void removeAddedLiterals(RoseBuildImpl &tbi, const flat_set<u32> &lit_ids) {
return;
}
DEBUG_PRINTF("remove last %zu literals\n", lit_ids.size());
// lit_ids should be a contiguous range.
assert(lit_ids.size() == *lit_ids.rbegin() - *lit_ids.begin() + 1);
assert(*lit_ids.rbegin() == tbi.literals.size() - 1);
for (const u32 &lit_id : lit_ids) {
assert(lit_id < tbi.literal_info.size());
assert(tbi.literals.right.at(lit_id).table == ROSE_ANCHORED);
assert(tbi.literal_info[lit_id].vertices.empty());
assert(all_of_in(lit_ids, [&](u32 lit_id) {
return lit_id < tbi.literal_info.size() &&
tbi.literals.at(lit_id).table == ROSE_ANCHORED &&
tbi.literal_info[lit_id].vertices.empty();
}));
tbi.literals.right.erase(lit_id);
}
tbi.literals.erase_back(lit_ids.size());
assert(tbi.literals.size() == *lit_ids.begin());
// lit_ids should be at the end of tbi.literal_info.
assert(tbi.literal_info.size() == *lit_ids.rbegin() + 1);

View File

@ -746,8 +746,8 @@ void findTriggerSequences(const RoseBuildImpl &tbi,
const u32 top = e.first;
const set<u32> &lit_ids = e.second;
for (u32 id : lit_ids) {
const rose_literal_id &lit = tbi.literals.right.at(id);
for (u32 id : lit_ids) {
const rose_literal_id &lit = tbi.literals.at(id);
(*trigger_lits)[top].push_back(as_cr_seq(lit));
}
}
@ -905,8 +905,8 @@ u32 decreaseLag(const RoseBuildImpl &build, NGHolder &h,
for (RoseVertex v : succs) {
u32 lag = rg[v].left.lag;
for (u32 lit_id : rg[v].literals) {
u32 delay = build.literals.right.at(lit_id).delay;
const ue2_literal &literal = build.literals.right.at(lit_id).s;
u32 delay = build.literals.at(lit_id).delay;
const ue2_literal &literal = build.literals.at(lit_id).s;
assert(lag <= literal.length() + delay);
size_t base = literal.length() + delay - lag;
if (base >= literal.length()) {
@ -1134,7 +1134,7 @@ bool buildLeftfix(RoseBuildImpl &build, build_context &bc, bool prefix, u32 qi,
for (RoseVertex v : succs) {
for (auto u : inv_adjacent_vertices_range(v, g)) {
for (u32 lit_id : g[u].literals) {
lits.insert(build.literals.right.at(lit_id).s);
lits.insert(build.literals.at(lit_id).s);
}
}
}
@ -1315,7 +1315,7 @@ void updateExclusiveInfixProperties(const RoseBuildImpl &build,
set<ue2_literal> lits;
for (auto u : inv_adjacent_vertices_range(v, build.g)) {
for (u32 lit_id : build.g[u].literals) {
lits.insert(build.literals.right.at(lit_id).s);
lits.insert(build.literals.at(lit_id).s);
}
}
DEBUG_PRINTF("%zu literals\n", lits.size());
@ -2117,9 +2117,8 @@ u32 RoseBuildImpl::calcHistoryRequired() const {
}
// Delayed literals contribute to history requirement as well.
for (const auto &e : literals.right) {
const u32 id = e.first;
const auto &lit = e.second;
for (u32 id = 0; id < literals.size(); id++) {
const auto &lit = literals.at(id);
if (lit.delay) {
// If the literal is delayed _and_ has a mask that is longer than
// the literal, we need enough history to match the whole mask as
@ -2716,11 +2715,11 @@ void buildLeftInfoTable(const RoseBuildImpl &tbi, build_context &bc,
} else {
left.lagIndex = ROSE_OFFSET_INVALID;
}
DEBUG_PRINTF("rose %u is %s\n", left_index,
left.infix ? "infix" : "prefix");
}
DEBUG_PRINTF("rose %u is %s\n", left_index,
left.infix ? "infix" : "prefix");
// Update squash mask.
left.squash_mask &= lbi.squash_mask;
@ -2853,9 +2852,8 @@ vector<LitFragment> groupByFragment(const RoseBuildImpl &build) {
map<rose_literal_id, FragmentInfo> frag_info;
for (const auto &m : build.literals.right) {
const u32 lit_id = m.first;
const auto &lit = m.second;
for (u32 lit_id = 0; lit_id < build.literals.size(); lit_id++) {
const auto &lit = build.literals.at(lit_id);
const auto &info = build.literal_info.at(lit_id);
if (!isUsedLiteral(build, lit_id)) {
@ -2993,7 +2991,7 @@ pair<u32, u32> writeAnchoredPrograms(const RoseBuildImpl &build,
for (const auto &frag : fragments) {
for (const u32 lit_id : frag.lit_ids) {
const auto &lit = build.literals.right.at(lit_id);
const auto &lit = build.literals.at(lit_id);
if (lit.table != ROSE_ANCHORED) {
continue;
@ -3238,7 +3236,7 @@ void fillMatcherDistances(const RoseBuildImpl &build, RoseEngine *engine) {
assert(g[v].min_offset <= g[v].max_offset);
for (u32 lit_id : g[v].literals) {
const rose_literal_id &key = build.literals.right.at(lit_id);
const rose_literal_id &key = build.literals.at(lit_id);
u32 max_d = g[v].max_offset;
u32 min_d = g[v].min_offset;
@ -3371,9 +3369,8 @@ pair<size_t, size_t> floatingCountAndMaxLen(const RoseBuildImpl &build) {
size_t num = 0;
size_t max_len = 0;
for (const auto &e : build.literals.right) {
const u32 id = e.first;
const rose_literal_id &lit = e.second;
for (u32 id = 0; id < build.literals.size(); id++) {
const rose_literal_id &lit = build.literals.at(id);
if (lit.table != ROSE_FLOATING) {
continue;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2016, Intel Corporation
* Copyright (c) 2015-2017, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -131,7 +131,7 @@ vector<rose_literal_id> literals_for_vertex(const RoseBuildImpl &tbi,
vector<rose_literal_id> rv;
for (const u32 id : tbi.g[v].literals) {
rv.push_back(tbi.literals.right.at(id));
rv.push_back(tbi.literals.at(id));
}
return rv;
@ -366,7 +366,7 @@ bool triggerKillsRoseCastle(const RoseBuildImpl &tbi, const left_id &left,
/* check each pred literal to see if they all kill previous castle
* state */
for (u32 lit_id : tbi.g[source(e, tbi.g)].literals) {
const rose_literal_id &pred_lit = tbi.literals.right.at(lit_id);
const rose_literal_id &pred_lit = tbi.literals.at(lit_id);
const ue2_literal s = findNonOverlappingTail(all_lits, pred_lit.s);
const CharReach &cr = c.reach();

View File

@ -119,7 +119,7 @@ void removeLiteralFromGraph(RoseBuildImpl &build, u32 id) {
*/
static
void explodeLiteral(RoseBuildImpl &build, u32 id) {
const auto &lit = build.literals.right.at(id);
const auto &lit = build.literals.at(id);
auto &info = build.literal_info[id];
assert(!info.group_mask); // not set yet
@ -139,7 +139,7 @@ void explodeLiteral(RoseBuildImpl &build, u32 id) {
DEBUG_PRINTF("adding exploded lit %u: '%s'\n", new_id,
dumpString(new_str).c_str());
const auto &new_lit = build.literals.right.at(new_id);
const auto &new_lit = build.literals.at(new_id);
auto &new_info = build.literal_info.at(new_id);
insert(&new_info.vertices, info.vertices);
for (const auto &v : info.vertices) {
@ -150,7 +150,7 @@ void explodeLiteral(RoseBuildImpl &build, u32 id) {
if (!info.delayed_ids.empty()) {
flat_set<u32> &del_ids = new_info.delayed_ids;
for (u32 delay_id : info.delayed_ids) {
const auto &dlit = build.literals.right.at(delay_id);
const auto &dlit = build.literals.at(delay_id);
u32 new_delay_id =
build.getLiteralId(new_lit.s, new_lit.msk, new_lit.cmp,
dlit.delay, dlit.table);
@ -170,9 +170,8 @@ void explodeLiteral(RoseBuildImpl &build, u32 id) {
void RoseBuildImpl::handleMixedSensitivity(void) {
vector<u32> explode;
for (const auto &e : literals.right) {
u32 id = e.first;
const rose_literal_id &lit = e.second;
for (u32 id = 0; id < literals.size(); id++) {
const rose_literal_id &lit = literals.at(id);
if (lit.delay) {
continue; /* delay id's are virtual-ish */
@ -420,7 +419,7 @@ bool RoseBuildImpl::isDirectReport(u32 id) const {
}
}
if (literals.right.at(id).table == ROSE_ANCHORED) {
if (literals.at(id).table == ROSE_ANCHORED) {
/* in-edges are irrelevant for anchored region. */
continue;
}
@ -439,7 +438,7 @@ bool RoseBuildImpl::isDirectReport(u32 id) const {
}
DEBUG_PRINTF("literal %u ('%s') is a %s report\n", id,
dumpString(literals.right.at(id).s).c_str(),
dumpString(literals.at(id).s).c_str(),
info.vertices.size() > 1 ? "multi-direct" : "direct");
return true;
}
@ -511,8 +510,7 @@ bool checkEodStealFloating(const RoseBuildImpl &build,
// Collect a set of all floating literals.
unordered_set<ue2_literal> floating_lits;
for (auto &m : build.literals) {
const auto &lit = m.left;
for (auto &lit : build.literals) {
if (lit.table == ROSE_FLOATING) {
floating_lits.insert(lit.s);
}
@ -524,7 +522,7 @@ bool checkEodStealFloating(const RoseBuildImpl &build,
u32 new_floating_lits = 0;
for (u32 eod_id : eodLiteralsForFloating) {
const rose_literal_id &lit = build.literals.right.at(eod_id);
const rose_literal_id &lit = build.literals.at(eod_id);
DEBUG_PRINTF("checking '%s'\n", dumpString(lit.s).c_str());
if (contains(floating_lits, lit.s)) {
@ -558,12 +556,16 @@ bool checkEodStealFloating(const RoseBuildImpl &build,
static
void promoteEodToFloating(RoseBuildImpl &tbi, const vector<u32> &eodLiterals) {
DEBUG_PRINTF("promoting eod literals to floating table\n");
DEBUG_PRINTF("promoting %zu eod literals to floating table\n",
eodLiterals.size());
for (u32 eod_id : eodLiterals) {
const rose_literal_id &lit = tbi.literals.right.at(eod_id);
const rose_literal_id &lit = tbi.literals.at(eod_id);
DEBUG_PRINTF("eod_id=%u, lit=%s\n", eod_id, dumpString(lit.s).c_str());
u32 floating_id = tbi.getLiteralId(lit.s, lit.msk, lit.cmp, lit.delay,
ROSE_FLOATING);
DEBUG_PRINTF("floating_id=%u, lit=%s\n", floating_id,
dumpString(tbi.literals.at(floating_id).s).c_str());
auto &float_verts = tbi.literal_info[floating_id].vertices;
auto &eod_verts = tbi.literal_info[eod_id].vertices;
@ -588,7 +590,7 @@ bool promoteEodToAnchored(RoseBuildImpl &tbi, const vector<u32> &eodLiterals) {
bool rv = true;
for (u32 eod_id : eodLiterals) {
const rose_literal_id &lit = tbi.literals.right.at(eod_id);
const rose_literal_id &lit = tbi.literals.at(eod_id);
NGHolder h;
add_edge(h.start, h.accept, h);
@ -728,7 +730,7 @@ void stealEodVertices(RoseBuildImpl &tbi) {
continue; // skip unused literals
}
const rose_literal_id &lit = tbi.literals.right.at(i);
const rose_literal_id &lit = tbi.literals.at(i);
if (lit.table == ROSE_EOD_ANCHORED) {
if (suitableForAnchored(tbi, lit, info)) {
@ -770,7 +772,7 @@ bool RoseBuildImpl::isDelayed(u32 id) const {
bool RoseBuildImpl::hasDelayedLiteral(RoseVertex v) const {
for (u32 lit_id : g[v].literals) {
if (literals.right.at(lit_id).delay) {
if (literals.at(lit_id).delay) {
return true;
}
}
@ -1096,7 +1098,7 @@ bool triggerKillsRoseGraph(const RoseBuildImpl &build, const left_id &left,
/* check each pred literal to see if they all kill previous graph
* state */
for (u32 lit_id : build.g[source(e, build.g)].literals) {
const rose_literal_id &pred_lit = build.literals.right.at(lit_id);
const rose_literal_id &pred_lit = build.literals.at(lit_id);
const ue2_literal s = findNonOverlappingTail(all_lits, pred_lit.s);
DEBUG_PRINTF("running graph %zu\n", states.size());
@ -1170,7 +1172,7 @@ void findTopTriggerCancels(RoseBuildImpl &build) {
}
for (u32 lit_id : pred_lit_ids) {
const rose_literal_id &p_lit = build.literals.right.at(lit_id);
const rose_literal_id &p_lit = build.literals.at(lit_id);
if (p_lit.delay || p_lit.table == ROSE_ANCHORED) {
goto next_rose;
}
@ -1271,7 +1273,7 @@ void countFloatingLiterals(const RoseBuildImpl &tbi, u32 *total_count,
u32 *short_count) {
*total_count = 0;
*short_count = 0;
for (const rose_literal_id &lit : tbi.literals.right | map_values) {
for (const rose_literal_id &lit : tbi.literals) {
if (lit.delay) {
continue; /* delay id's are virtual-ish */
}

View File

@ -235,7 +235,7 @@ void convertFloodProneSuffix(RoseBuildImpl &tbi, RoseVertex v, u32 lit_id,
static
size_t findFloodProneSuffixLen(const RoseBuildImpl &tbi) {
size_t numLiterals = 0;
for (const rose_literal_id &lit : tbi.literals.right | map_values) {
for (const rose_literal_id &lit : tbi.literals) {
if (lit.delay) {
continue; // delay ids are virtual-ish
}
@ -293,7 +293,7 @@ void convertFloodProneSuffixes(RoseBuildImpl &tbi) {
}
u32 lit_id = *g[v].literals.begin();
const rose_literal_id &lit = tbi.literals.right.at(lit_id);
const rose_literal_id &lit = tbi.literals.at(lit_id);
// anchored or delayed literals need thought.
if (lit.table != ROSE_FLOATING || lit.delay) {

View File

@ -311,9 +311,9 @@ bool RoseDedupeAuxImpl::requiresDedupeSupport(
}
for (auto it = begin(lits); it != end(lits); ++it) {
const auto &lit1 = build.literals.right.at(it->first);
const auto &lit1 = build.literals.at(it->first);
for (auto jt = next(it); jt != end(lits); ++jt) {
const auto &lit2 = build.literals.right.at(jt->first);
const auto &lit2 = build.literals.at(jt->first);
if (literalsCouldRace(lit1, lit2)) {
DEBUG_PRINTF("literals could race\n");
return true;

View File

@ -257,17 +257,13 @@ private:
os << "/nofrag ";
}
if (contains(build.literals.right, id)) {
const auto &lit = build.literals.right.at(id);
os << '\'' << dotEscapeString(lit.s.get_string()) << '\'';
if (lit.s.any_nocase()) {
os << " (nocase)";
}
if (lit.delay) {
os << " +" << lit.delay;
}
} else {
os << "<unknown>";
const auto &lit = build.literals.at(id);
os << '\'' << dotEscapeString(lit.s.get_string()) << '\'';
if (lit.s.any_nocase()) {
os << " (nocase)";
}
if (lit.delay) {
os << " +" << lit.delay;
}
}
@ -358,15 +354,16 @@ void dumpRoseLiterals(const RoseBuildImpl &build,
DEBUG_PRINTF("dumping literals\n");
ofstream os(grey.dumpPath + "rose_literals.txt");
os << "ROSE LITERALS: a total of " << build.literals.right.size()
<< " literals and " << num_vertices(g) << " roles." << endl << endl;
os << "ROSE LITERALS: a total of " << build.literals.size()
<< " literals and " << num_vertices(g) << " roles." << endl
<< endl;
for (const auto &e : build.literals.right) {
u32 id = e.first;
const ue2_literal &s = e.second.s;
for (u32 id = 0; id < build.literals.size(); id++) {
const auto &lit = build.literals.at(id);
const ue2_literal &s = lit.s;
const rose_literal_info &lit_info = build.literal_info[id];
switch (e.second.table) {
switch (lit.table) {
case ROSE_ANCHORED:
os << "ANCHORED";
break;
@ -397,8 +394,8 @@ void dumpRoseLiterals(const RoseBuildImpl &build,
os << " benefits,";
}
if (e.second.delay) {
os << " delayed "<< e.second.delay << ",";
if (lit.delay) {
os << " delayed "<< lit.delay << ",";
}
os << " groups 0x" << hex << setw(16) << setfill('0')

View File

@ -238,9 +238,8 @@ void assignGroupsToLiterals(RoseBuildImpl &build) {
u32 group_always_on = 0;
// First pass: handle always on literals.
for (const auto &e : literals.right) {
u32 id = e.first;
const rose_literal_id &lit = e.second;
for (u32 id = 0; id < literals.size(); id++) {
const rose_literal_id &lit = literals.at(id);
rose_literal_info &info = literal_info[id];
if (!requires_group_assignment(lit, info)) {
@ -274,9 +273,8 @@ void assignGroupsToLiterals(RoseBuildImpl &build) {
priority_queue<tuple<s32, s32, u32>> pq;
// Second pass: the other literals.
for (const auto &e : literals.right) {
u32 id = e.first;
const rose_literal_id &lit = e.second;
for (u32 id = 0; id < literals.size(); id++) {
const rose_literal_id &lit = literals.at(id);
rose_literal_info &info = literal_info[id];
if (!requires_group_assignment(lit, info)) {
@ -290,7 +288,7 @@ void assignGroupsToLiterals(RoseBuildImpl &build) {
while (!pq.empty()) {
u32 id = get<2>(pq.top());
pq.pop();
UNUSED const rose_literal_id &lit = literals.right.at(id);
UNUSED const rose_literal_id &lit = literals.at(id);
DEBUG_PRINTF("assigning groups to lit %u (v %zu l %zu)\n", id,
literal_info[id].vertices.size(), lit.s.length());
@ -361,9 +359,8 @@ void assignGroupsToLiterals(RoseBuildImpl &build) {
}
}
/* assign delayed literals to the same group as their parent */
for (const auto &e : literals.right) {
u32 id = e.first;
const rose_literal_id &lit = e.second;
for (u32 id = 0; id < literals.size(); id++) {
const rose_literal_id &lit = literals.at(id);
if (!lit.delay) {
continue;
@ -378,7 +375,7 @@ void assignGroupsToLiterals(RoseBuildImpl &build) {
}
DEBUG_PRINTF("populate group to literal mapping\n");
for (const u32 id : literals.right | map_keys) {
for (u32 id = 0; id < literals.size(); id++) {
rose_group groups = literal_info[id].group_mask;
while (groups) {
u32 group_id = findAndClearLSB_64(&groups);
@ -561,10 +558,10 @@ bool isGroupSquasher(const RoseBuildImpl &build, const u32 id /* literal id */,
const rose_literal_info &lit_info = build.literal_info.at(id);
DEBUG_PRINTF("checking if %u '%s' is a group squasher %016llx\n", id,
dumpString(build.literals.right.at(id).s).c_str(),
lit_info.group_mask);
dumpString(build.literals.at(id).s).c_str(),
lit_info.group_mask);
if (build.literals.right.at(id).table == ROSE_EVENT) {
if (build.literals.at(id).table == ROSE_EVENT) {
DEBUG_PRINTF("event literal\n");
return false;
}
@ -693,9 +690,10 @@ bool isGroupSquasher(const RoseBuildImpl &build, const u32 id /* literal id */,
void findGroupSquashers(RoseBuildImpl &build) {
rose_group forbidden_squash_group = build.boundary_group_mask;
for (const auto &e : build.literals.right) {
if (e.second.delay) {
forbidden_squash_group |= build.literal_info[e.first].group_mask;
for (u32 id = 0; id < build.literals.size(); id++) {
const auto &lit = build.literals.at(id);
if (lit.delay) {
forbidden_squash_group |= build.literal_info[id].group_mask;
}
}

View File

@ -39,16 +39,17 @@
#include "nfagraph/ng_holder.h"
#include "nfagraph/ng_revacc.h"
#include "util/bytecode_ptr.h"
#include "util/hash.h"
#include "util/order_check.h"
#include "util/queue_index_factory.h"
#include "util/ue2_containers.h"
#include "util/ue2string.h"
#include "util/verify_types.h"
#include <deque>
#include <map>
#include <string>
#include <vector>
#include <boost/bimap.hpp>
#include <boost/functional/hash/hash.hpp>
#include <boost/variant.hpp>
struct RoseEngine;
@ -300,6 +301,11 @@ struct rose_literal_id {
}
return MAX(mask_len, s.length()) + delay;
}
bool operator==(const rose_literal_id &b) const {
return s == b.s && msk == b.msk && cmp == b.cmp && table == b.table &&
delay == b.delay && distinctiveness == b.distinctiveness;
}
};
static inline
@ -313,8 +319,60 @@ bool operator<(const rose_literal_id &a, const rose_literal_id &b) {
return 0;
}
// Literals are stored in a map from (string, nocase) -> ID
typedef boost::bimap<rose_literal_id, u32> RoseLiteralMap;
inline
size_t hash_value(const rose_literal_id &lit) {
return hash_all(lit.s, lit.msk, lit.cmp, lit.table, lit.delay,
lit.distinctiveness);
}
class RoseLiteralMap {
/**
* \brief Main storage for literals.
*
* Note that this cannot be a vector, as the present code relies on
* iterator stability when iterating over this list and adding to it inside
* the loop.
*/
std::deque<rose_literal_id> lits;
/** \brief Quick-lookup index from literal -> index in lits. */
unordered_map<rose_literal_id, u32> lits_index;
public:
std::pair<u32, bool> insert(const rose_literal_id &lit) {
auto it = lits_index.find(lit);
if (it != lits_index.end()) {
return {it->second, false};
}
u32 id = verify_u32(lits.size());
lits.push_back(lit);
lits_index.emplace(lit, id);
return {id, true};
}
// Erase the last num elements.
void erase_back(size_t num) {
assert(num <= lits.size());
for (size_t i = 0; i < num; i++) {
lits_index.erase(lits.back());
lits.pop_back();
}
assert(lits.size() == lits_index.size());
}
const rose_literal_id &at(u32 id) const {
assert(id < lits.size());
return lits.at(id);
}
using const_iterator = decltype(lits)::const_iterator;
const_iterator begin() const { return lits.begin(); }
const_iterator end() const { return lits.end(); }
size_t size() const {
return lits.size();
}
};
struct simple_anchored_info {
simple_anchored_info(u32 min_b, u32 max_b, const ue2_literal &lit)

View File

@ -447,7 +447,7 @@ static
void findFloodReach(const RoseBuildImpl &tbi, const RoseVertex v,
set<CharReach> &flood_reach) {
for (u32 lit_id : tbi.g[v].literals) {
const ue2_literal &s = tbi.literals.right.at(lit_id).s;
const ue2_literal &s = tbi.literals.at(lit_id).s;
if (s.empty()) {
continue;
}
@ -491,7 +491,7 @@ map<s32, CharReach> findLiteralReach(const RoseBuildImpl &build,
map<s32, CharReach> look;
for (u32 lit_id : build.g[v].literals) {
const rose_literal_id &lit = build.literals.right.at(lit_id);
const rose_literal_id &lit = build.literals.at(lit_id);
auto lit_look = findLiteralReach(lit);
if (first) {

View File

@ -211,7 +211,7 @@ bool maskFromPreds(const RoseBuildImpl &build, const rose_literal_id &id,
}
u32 u_lit_id = *(g[u].literals.begin());
const rose_literal_id &u_id = build.literals.right.at(u_lit_id);
const rose_literal_id &u_id = build.literals.at(u_lit_id);
DEBUG_PRINTF("u has lit: %s\n", escapeString(u_id.s).c_str());
// Number of characters to take from the back of u's literal.
@ -346,9 +346,8 @@ void findMoreLiteralMasks(RoseBuildImpl &build) {
}
vector<u32> candidates;
for (const auto &e : build.literals.right) {
const u32 id = e.first;
const auto &lit = e.second;
for (u32 id = 0; id < build.literals.size(); id++) {
const auto &lit = build.literals.at(id);
if (lit.delay || build.isDelayed(id)) {
continue;
@ -377,7 +376,7 @@ void findMoreLiteralMasks(RoseBuildImpl &build) {
}
for (const u32 &id : candidates) {
const auto &lit = build.literals.right.at(id);
const auto &lit = build.literals.at(id);
auto &lit_info = build.literal_info.at(id);
vector<u8> msk, cmp;
@ -492,7 +491,7 @@ bool isNoRunsLiteral(const RoseBuildImpl &build, const u32 id,
return false;
}
size_t len = build.literals.right.at(id).s.length();
size_t len = build.literals.at(id).s.length();
if (len > max_len) {
DEBUG_PRINTF("long literal, requires confirm\n");
return false;
@ -617,7 +616,7 @@ u64a literalMinReportOffset(const RoseBuildImpl &build,
// If this literal in the undelayed literal corresponding to some delayed
// literals, we must take their minimum offsets into account.
for (const u32 &delayed_id : info.delayed_ids) {
const auto &delayed_lit = build.literals.right.at(delayed_id);
const auto &delayed_lit = build.literals.at(delayed_id);
const auto &delayed_info = build.literal_info.at(delayed_id);
u64a delayed_min_offset = literalMinReportOffset(build, delayed_lit,
delayed_info);
@ -682,7 +681,7 @@ MatcherProto makeMatcherProto(const RoseBuildImpl &build,
for (const auto &f : fragments) {
for (u32 id : f.lit_ids) {
const rose_literal_id &lit = build.literals.right.at(id);
const rose_literal_id &lit = build.literals.at(id);
if (lit.table != table) {
continue; /* wrong table */

View File

@ -1054,14 +1054,14 @@ bool mergeableRoseVertices(const RoseBuildImpl &tbi, RoseVertex u,
vector<pair<const rose_literal_id *, u32>> ulits;
ulits.reserve(tbi.g[u].literals.size());
for (u32 id : tbi.g[u].literals) {
ulits.push_back(make_pair(&tbi.literals.right.at(id), ulag));
ulits.emplace_back(&tbi.literals.at(id), ulag);
}
u32 vlag = tbi.g[v].left.lag;
vector<pair<const rose_literal_id *, u32>> vlits;
vlits.reserve(tbi.g[v].literals.size());
for (u32 id : tbi.g[v].literals) {
vlits.push_back(make_pair(&tbi.literals.right.at(id), vlag));
vlits.emplace_back(&tbi.literals.at(id), vlag);
}
if (!compatibleLiteralsForMerge(ulits, vlits)) {
@ -1130,7 +1130,7 @@ bool checkPredDelays(const RoseBuildImpl &tbi, const deque<RoseVertex> &v1,
vector<const rose_literal_id *> pred_rose_lits;
pred_rose_lits.reserve(pred_lits.size());
for (const auto &p : pred_lits) {
pred_rose_lits.push_back(&tbi.literals.right.at(p));
pred_rose_lits.push_back(&tbi.literals.at(p));
}
for (auto v : v2) {
@ -1140,7 +1140,7 @@ bool checkPredDelays(const RoseBuildImpl &tbi, const deque<RoseVertex> &v1,
}
for (const u32 vlit : tbi.g[v].literals) {
const rose_literal_id &vl = tbi.literals.right.at(vlit);
const rose_literal_id &vl = tbi.literals.at(vlit);
assert(!vl.delay); // this should never have got this far?
for (const auto &ul : pred_rose_lits) {
assert(!ul->delay); // this should never have got this far?
@ -1195,7 +1195,7 @@ bool mergeableRoseVertices(const RoseBuildImpl &tbi,
u32 ulag = tbi.g[a].left.lag;
for (u32 id : tbi.g[a].literals) {
ulits.push_back(make_pair(&tbi.literals.right.at(id), ulag));
ulits.emplace_back(&tbi.literals.at(id), ulag);
}
}
@ -1207,7 +1207,7 @@ bool mergeableRoseVertices(const RoseBuildImpl &tbi,
u32 vlag = tbi.g[a].left.lag;
for (u32 id : tbi.g[a].literals) {
vlits.push_back(make_pair(&tbi.literals.right.at(id), vlag));
vlits.emplace_back(&tbi.literals.at(id), vlag);
}
}
@ -2730,7 +2730,7 @@ u32 allowedSquashDistance(const CharReach &cr, u32 min_width,
/* TODO: inspect further back in the pattern */
for (u32 lit_id : g[tv].literals) {
const rose_literal_id &lit = tbi.literals.right.at(lit_id);
const rose_literal_id &lit = tbi.literals.at(lit_id);
if (lit.delay) {
return 0; /* TODO: better */
}

View File

@ -154,14 +154,12 @@ bool isInTable(const RoseBuildImpl &tbi, RoseVertex v,
// All literals for a given vertex will be in the same table, so we need
// only inspect the first one.
const auto lit_table = tbi.literals.right.at(*lit_ids.begin()).table;
const auto lit_table = tbi.literals.at(*lit_ids.begin()).table;
#ifndef NDEBUG
// Verify that all literals for this vertex are in the same table.
for (auto lit_id : lit_ids) {
assert(tbi.literals.right.at(lit_id).table == lit_table);
}
#endif
assert(all_of_in(lit_ids, [&](u32 lit_id) {
return tbi.literals.at(lit_id).table == lit_table;
}));
return lit_table == table;
}
@ -211,7 +209,7 @@ size_t RoseBuildImpl::maxLiteralLen(RoseVertex v) const {
size_t maxlen = 0;
for (const auto &lit_id : lit_ids) {
maxlen = max(maxlen, literals.right.at(lit_id).elength());
maxlen = max(maxlen, literals.at(lit_id).elength());
}
return maxlen;
@ -224,7 +222,7 @@ size_t RoseBuildImpl::minLiteralLen(RoseVertex v) const {
size_t minlen = ROSE_BOUND_INF;
for (const auto &lit_id : lit_ids) {
minlen = min(minlen, literals.right.at(lit_id).elength());
minlen = min(minlen, literals.at(lit_id).elength());
}
return minlen;
@ -287,12 +285,11 @@ size_t maxOverlap(const rose_literal_id &a, const rose_literal_id &b) {
static
const rose_literal_id &getOverlapLiteral(const RoseBuildImpl &tbi,
u32 literal_id) {
map<u32, rose_literal_id>::const_iterator it =
tbi.anchoredLitSuffix.find(literal_id);
auto it = tbi.anchoredLitSuffix.find(literal_id);
if (it != tbi.anchoredLitSuffix.end()) {
return it->second;
}
return tbi.literals.right.at(literal_id);
return tbi.literals.at(literal_id);
}
ue2_literal findNonOverlappingTail(const set<ue2_literal> &lits,
@ -368,16 +365,14 @@ u32 RoseBuildImpl::calcSuccMaxBound(RoseVertex u) const {
u32 RoseBuildImpl::getLiteralId(const ue2_literal &s, u32 delay,
rose_literal_table table) {
DEBUG_PRINTF("getting id for %s\n", dumpString(s).c_str());
DEBUG_PRINTF("getting id for %s in table %d\n", dumpString(s).c_str(),
table);
assert(table != ROSE_ANCHORED);
rose_literal_id key(s, table, delay);
u32 numLiterals = verify_u32(literals.left.size());
RoseLiteralMap::iterator it;
bool inserted;
tie(it, inserted)
= literals.insert(RoseLiteralMap::value_type(key, numLiterals));
u32 id = it->right;
auto m = literals.insert(key);
u32 id = m.first;
bool inserted = m.second;
if (inserted) {
literal_info.push_back(rose_literal_info());
@ -457,19 +452,17 @@ rose_literal_id::rose_literal_id(const ue2_literal &s_in,
u32 RoseBuildImpl::getLiteralId(const ue2_literal &s, const vector<u8> &msk,
const vector<u8> &cmp, u32 delay,
rose_literal_table table) {
DEBUG_PRINTF("getting id for %s\n", dumpString(s).c_str());
DEBUG_PRINTF("getting id for %s in table %d\n", dumpString(s).c_str(),
table);
assert(table != ROSE_ANCHORED);
rose_literal_id key(s, msk, cmp, table, delay);
u32 numLiterals = verify_u32(literals.left.size());
/* ue2_literals are always uppercased if nocase and must have an
* alpha char */
RoseLiteralMap::iterator it;
bool inserted;
tie(it, inserted) = literals.insert(
RoseLiteralMap::value_type(key, numLiterals));
u32 id = it->right;
auto m = literals.insert(key);
u32 id = m.first;
bool inserted = m.second;
if (inserted) {
literal_info.push_back(rose_literal_info());
@ -488,16 +481,12 @@ u32 RoseBuildImpl::getLiteralId(const ue2_literal &s, const vector<u8> &msk,
u32 RoseBuildImpl::getNewLiteralId() {
rose_literal_id key(ue2_literal(), ROSE_ANCHORED, 0);
u32 numLiterals = verify_u32(literals.left.size());
u32 numLiterals = verify_u32(literals.size());
key.distinctiveness = numLiterals;
RoseLiteralMap::iterator it;
bool inserted;
tie(it, inserted)
= literals.insert(RoseLiteralMap::value_type(key, numLiterals));
u32 id = it->right;
assert(inserted);
auto m = literals.insert(key);
assert(m.second);
u32 id = m.first;
literal_info.push_back(rose_literal_info());
assert(literal_info.size() == id + 1);

View File

@ -349,7 +349,7 @@ void makeAnchoredLiteralDelay(const RoseBuildImpl &build,
const ProgramBuild &prog_build, u32 lit_id,
RoseProgram &program) {
// Only relevant for literals in the anchored table.
const rose_literal_id &lit = build.literals.right.at(lit_id);
const rose_literal_id &lit = build.literals.at(lit_id);
if (lit.table != ROSE_ANCHORED) {
return;
}
@ -686,7 +686,7 @@ void makePushDelayedInstructions(const RoseLiteralMap &literals,
DEBUG_PRINTF("delayed lit id %u\n", delayed_lit_id);
assert(contains(prog_build.delay_programs, delayed_lit_id));
u32 delay_id = prog_build.delay_programs.at(delayed_lit_id);
const auto &delay_lit = literals.right.at(delayed_lit_id);
const auto &delay_lit = literals.at(delayed_lit_id);
delay_instructions.emplace_back(verify_u8(delay_lit.delay), delay_id);
}
@ -1335,7 +1335,7 @@ void makeCheckLitMaskInstruction(const RoseBuildImpl &build,
vector<LookEntry> look;
const ue2_literal &s = build.literals.right.at(lit_id).s;
const ue2_literal &s = build.literals.at(lit_id).s;
DEBUG_PRINTF("building mask for lit %u: %s\n", lit_id,
dumpString(s).c_str());
assert(s.length() <= MAX_MASK2_WIDTH);
@ -1369,7 +1369,7 @@ void makeCheckLitEarlyInstruction(const RoseBuildImpl &build, u32 lit_id,
return;
}
const auto &lit = build.literals.right.at(lit_id);
const auto &lit = build.literals.at(lit_id);
size_t min_len = lit.elength();
u32 min_offset = findMinOffset(build, lit_id);
DEBUG_PRINTF("has min_len=%zu, min_offset=%u, global min is %u\n", min_len,
@ -1404,7 +1404,7 @@ void makeGroupCheckInstruction(const RoseBuildImpl &build, u32 lit_id,
static
bool hasDelayedLiteral(const RoseBuildImpl &build,
const vector<RoseEdge> &lit_edges) {
auto is_delayed = bind(&RoseBuildImpl::isDelayed, &build, _1);
auto is_delayed = [&build](u32 lit_id) { return build.isDelayed(lit_id); };
for (const auto &e : lit_edges) {
auto v = target(e, build.g);
const auto &lits = build.g[v].literals;
@ -1425,7 +1425,7 @@ RoseProgram makeLitInitialProgram(const RoseBuildImpl &build,
// Check long literal info.
if (!build.isDelayed(lit_id)) {
makeCheckLiteralInstruction(build.literals.right.at(lit_id),
makeCheckLiteralInstruction(build.literals.at(lit_id),
prog_build.longLitLengthThreshold,
program, build.cc);
}
@ -2121,7 +2121,7 @@ RoseProgram makeDelayRebuildProgram(const RoseBuildImpl &build,
RoseProgram prog;
if (!build.isDelayed(lit_id)) {
makeCheckLiteralInstruction(build.literals.right.at(lit_id),
makeCheckLiteralInstruction(build.literals.at(lit_id),
prog_build.longLitLengthThreshold, prog,
build.cc);
}

View File

@ -328,9 +328,9 @@ bool canMergeLiterals(RoseVertex a, RoseVertex b, const RoseBuildImpl &build) {
// Otherwise, all the literals involved must have the same length.
for (u32 a_id : lits_a) {
const rose_literal_id &la = build.literals.right.at(a_id);
const rose_literal_id &la = build.literals.at(a_id);
for (u32 b_id : lits_b) {
const rose_literal_id &lb = build.literals.right.at(b_id);
const rose_literal_id &lb = build.literals.at(b_id);
if (la.elength() != lb.elength()) {
DEBUG_PRINTF("bad merge %zu!=%zu '%s', '%s'\n", la.elength(),
@ -1483,7 +1483,7 @@ void splitByLiteralTable(const RoseBuildImpl &build,
auto make_split_key = [&](RoseVertex v) {
const auto &lits = g[v].literals;
assert(!lits.empty());
return build.literals.right.at(*lits.begin()).table;
return build.literals.at(*lits.begin()).table;
};
splitAndFilterBuckets(buckets, make_split_key);
}