diff --git a/src/rose/rose_build_add.cpp b/src/rose/rose_build_add.cpp index b53f7c8a..26f88445 100644 --- a/src/rose/rose_build_add.cpp +++ b/src/rose/rose_build_add.cpp @@ -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 &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); diff --git a/src/rose/rose_build_bytecode.cpp b/src/rose/rose_build_bytecode.cpp index 636af0a6..dfe4ff63 100644 --- a/src/rose/rose_build_bytecode.cpp +++ b/src/rose/rose_build_bytecode.cpp @@ -746,8 +746,8 @@ void findTriggerSequences(const RoseBuildImpl &tbi, const u32 top = e.first; const set &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 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 groupByFragment(const RoseBuildImpl &build) { map 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 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 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; diff --git a/src/rose/rose_build_castle.cpp b/src/rose/rose_build_castle.cpp index 7987b0f6..a85a784f 100644 --- a/src/rose/rose_build_castle.cpp +++ b/src/rose/rose_build_castle.cpp @@ -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 literals_for_vertex(const RoseBuildImpl &tbi, vector 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(); diff --git a/src/rose/rose_build_compile.cpp b/src/rose/rose_build_compile.cpp index f4c2613e..96241e39 100644 --- a/src/rose/rose_build_compile.cpp +++ b/src/rose/rose_build_compile.cpp @@ -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 &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 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 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 &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 &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 */ } diff --git a/src/rose/rose_build_convert.cpp b/src/rose/rose_build_convert.cpp index 89eac225..0c1f4338 100644 --- a/src/rose/rose_build_convert.cpp +++ b/src/rose/rose_build_convert.cpp @@ -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) { diff --git a/src/rose/rose_build_dedupe.cpp b/src/rose/rose_build_dedupe.cpp index dbff7aa7..d3e72313 100644 --- a/src/rose/rose_build_dedupe.cpp +++ b/src/rose/rose_build_dedupe.cpp @@ -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; diff --git a/src/rose/rose_build_dump.cpp b/src/rose/rose_build_dump.cpp index dfbbe116..7fd19d43 100644 --- a/src/rose/rose_build_dump.cpp +++ b/src/rose/rose_build_dump.cpp @@ -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 << ""; + 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') diff --git a/src/rose/rose_build_groups.cpp b/src/rose/rose_build_groups.cpp index f17e1ee4..c670e603 100644 --- a/src/rose/rose_build_groups.cpp +++ b/src/rose/rose_build_groups.cpp @@ -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> 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; } } diff --git a/src/rose/rose_build_impl.h b/src/rose/rose_build_impl.h index f4916604..13f1cfc9 100644 --- a/src/rose/rose_build_impl.h +++ b/src/rose/rose_build_impl.h @@ -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 #include #include #include -#include -#include #include 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 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 lits; + + /** \brief Quick-lookup index from literal -> index in lits. */ + unordered_map lits_index; + +public: + std::pair 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) diff --git a/src/rose/rose_build_lookaround.cpp b/src/rose/rose_build_lookaround.cpp index 07ab7c59..a46a1aeb 100644 --- a/src/rose/rose_build_lookaround.cpp +++ b/src/rose/rose_build_lookaround.cpp @@ -447,7 +447,7 @@ static void findFloodReach(const RoseBuildImpl &tbi, const RoseVertex v, set &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 findLiteralReach(const RoseBuildImpl &build, map 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) { diff --git a/src/rose/rose_build_matchers.cpp b/src/rose/rose_build_matchers.cpp index 64a1c919..682a87c3 100644 --- a/src/rose/rose_build_matchers.cpp +++ b/src/rose/rose_build_matchers.cpp @@ -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 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 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 */ diff --git a/src/rose/rose_build_merge.cpp b/src/rose/rose_build_merge.cpp index 685d1523..d638e589 100644 --- a/src/rose/rose_build_merge.cpp +++ b/src/rose/rose_build_merge.cpp @@ -1054,14 +1054,14 @@ bool mergeableRoseVertices(const RoseBuildImpl &tbi, RoseVertex u, vector> 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> 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 &v1, vector 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 &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 */ } diff --git a/src/rose/rose_build_misc.cpp b/src/rose/rose_build_misc.cpp index f5c5ce1a..01be11ef 100644 --- a/src/rose/rose_build_misc.cpp +++ b/src/rose/rose_build_misc.cpp @@ -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::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 &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 &msk, const vector &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 &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); diff --git a/src/rose/rose_build_program.cpp b/src/rose/rose_build_program.cpp index 8d0306ae..6dfe3507 100644 --- a/src/rose/rose_build_program.cpp +++ b/src/rose/rose_build_program.cpp @@ -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 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 &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); } diff --git a/src/rose/rose_build_role_aliasing.cpp b/src/rose/rose_build_role_aliasing.cpp index f8174d74..0e78ec7d 100644 --- a/src/rose/rose_build_role_aliasing.cpp +++ b/src/rose/rose_build_role_aliasing.cpp @@ -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); }