mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
rose_build: reduce size/scope of context objects
This commit is contained in:
parent
a2b2940f85
commit
37cb93e60f
@ -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:
|
||||
@ -560,7 +560,7 @@ buildCastle(const CastleProto &proto,
|
||||
DEBUG_PRINTF("%zu subcastles may go stale\n", may_stale.size());
|
||||
vector<mmbit_sparse_iter> stale_iter;
|
||||
if (!may_stale.empty()) {
|
||||
mmbBuildSparseIterator(stale_iter, may_stale, numRepeats);
|
||||
stale_iter = mmbBuildSparseIterator(may_stale, numRepeats);
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "grey.h"
|
||||
#include "rose_build_impl.h"
|
||||
#include "rose_build_matchers.h"
|
||||
#include "rose_internal.h"
|
||||
#include "ue2common.h"
|
||||
#include "nfa/dfa_min.h"
|
||||
@ -71,6 +72,8 @@ namespace ue2 {
|
||||
|
||||
#define INIT_STATE (DEAD_STATE + 1)
|
||||
|
||||
#define NO_FRAG_ID (~0U)
|
||||
|
||||
// Adds a vertex with the given reach.
|
||||
static
|
||||
NFAVertex add_vertex(NGHolder &h, const CharReach &cr) {
|
||||
@ -173,7 +176,7 @@ void mergeAnchoredDfas(vector<unique_ptr<raw_dfa>> &dfas,
|
||||
}
|
||||
|
||||
static
|
||||
void remapAnchoredReports(raw_dfa &rdfa, const RoseBuildImpl &build) {
|
||||
void remapAnchoredReports(raw_dfa &rdfa, const vector<u32> &frag_map) {
|
||||
for (dstate &ds : rdfa.states) {
|
||||
assert(ds.reports_eod.empty()); // Not used in anchored matcher.
|
||||
if (ds.reports.empty()) {
|
||||
@ -182,8 +185,8 @@ void remapAnchoredReports(raw_dfa &rdfa, const RoseBuildImpl &build) {
|
||||
|
||||
flat_set<ReportID> new_reports;
|
||||
for (auto id : ds.reports) {
|
||||
assert(id < build.literal_info.size());
|
||||
new_reports.insert(build.literal_info.at(id).fragment_id);
|
||||
assert(id < frag_map.size());
|
||||
new_reports.insert(frag_map[id]);
|
||||
}
|
||||
ds.reports = std::move(new_reports);
|
||||
}
|
||||
@ -194,21 +197,37 @@ void remapAnchoredReports(raw_dfa &rdfa, const RoseBuildImpl &build) {
|
||||
* ids) with the fragment id for each literal.
|
||||
*/
|
||||
static
|
||||
void remapAnchoredReports(RoseBuildImpl &build) {
|
||||
void remapAnchoredReports(RoseBuildImpl &build, const vector<u32> &frag_map) {
|
||||
for (auto &m : build.anchored_nfas) {
|
||||
for (auto &rdfa : m.second) {
|
||||
assert(rdfa);
|
||||
remapAnchoredReports(*rdfa, build);
|
||||
remapAnchoredReports(*rdfa, frag_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns mapping from literal ids to fragment ids.
|
||||
*/
|
||||
static
|
||||
vector<u32> reverseFragMap(const RoseBuildImpl &build,
|
||||
const vector<LitFragment> &fragments) {
|
||||
vector<u32> rev(build.literal_info.size(), NO_FRAG_ID);
|
||||
for (const auto &f : fragments) {
|
||||
for (u32 lit_id : f.lit_ids) {
|
||||
assert(lit_id < rev.size());
|
||||
rev[lit_id] = f.fragment_id;
|
||||
}
|
||||
}
|
||||
return rev;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Replace the reports (which are literal final_ids) in the given
|
||||
* raw_dfa with program offsets.
|
||||
*/
|
||||
static
|
||||
void remapIdsToPrograms(const RoseBuildImpl &build, raw_dfa &rdfa) {
|
||||
void remapIdsToPrograms(const vector<LitFragment> &fragments, raw_dfa &rdfa) {
|
||||
for (dstate &ds : rdfa.states) {
|
||||
assert(ds.reports_eod.empty()); // Not used in anchored matcher.
|
||||
if (ds.reports.empty()) {
|
||||
@ -217,7 +236,7 @@ void remapIdsToPrograms(const RoseBuildImpl &build, raw_dfa &rdfa) {
|
||||
|
||||
flat_set<ReportID> new_reports;
|
||||
for (auto fragment_id : ds.reports) {
|
||||
auto &frag = build.fragments.at(fragment_id);
|
||||
const auto &frag = fragments.at(fragment_id);
|
||||
new_reports.insert(frag.lit_program_offset);
|
||||
}
|
||||
ds.reports = std::move(new_reports);
|
||||
@ -731,7 +750,7 @@ int addToAnchoredMatcher(RoseBuildImpl &build, const NGHolder &anchored,
|
||||
}
|
||||
|
||||
static
|
||||
void buildSimpleDfas(const RoseBuildImpl &build,
|
||||
void buildSimpleDfas(const RoseBuildImpl &build, const vector<u32> &frag_map,
|
||||
vector<unique_ptr<raw_dfa>> *anchored_dfas) {
|
||||
/* we should have determinised all of these before so there should be no
|
||||
* chance of failure. */
|
||||
@ -739,7 +758,8 @@ void buildSimpleDfas(const RoseBuildImpl &build,
|
||||
for (const auto &simple : build.anchored_simple) {
|
||||
exit_ids.clear();
|
||||
for (auto lit_id : simple.second) {
|
||||
exit_ids.insert(build.literal_info[lit_id].fragment_id);
|
||||
assert(lit_id < frag_map.size());
|
||||
exit_ids.insert(frag_map[lit_id]);
|
||||
}
|
||||
auto h = populate_holder(simple.first, exit_ids);
|
||||
Automaton_Holder autom(*h);
|
||||
@ -760,7 +780,8 @@ void buildSimpleDfas(const RoseBuildImpl &build,
|
||||
* from RoseBuildImpl.
|
||||
*/
|
||||
static
|
||||
vector<unique_ptr<raw_dfa>> getAnchoredDfas(RoseBuildImpl &build) {
|
||||
vector<unique_ptr<raw_dfa>> getAnchoredDfas(RoseBuildImpl &build,
|
||||
const vector<u32> &frag_map) {
|
||||
vector<unique_ptr<raw_dfa>> dfas;
|
||||
|
||||
// DFAs that already exist as raw_dfas.
|
||||
@ -773,7 +794,7 @@ vector<unique_ptr<raw_dfa>> getAnchoredDfas(RoseBuildImpl &build) {
|
||||
|
||||
// DFAs we currently have as simple literals.
|
||||
if (!build.anchored_simple.empty()) {
|
||||
buildSimpleDfas(build, &dfas);
|
||||
buildSimpleDfas(build, frag_map, &dfas);
|
||||
build.anchored_simple.clear();
|
||||
}
|
||||
|
||||
@ -825,7 +846,8 @@ size_t buildNfas(vector<raw_dfa> &anchored_dfas,
|
||||
return total_size;
|
||||
}
|
||||
|
||||
vector<raw_dfa> buildAnchoredDfas(RoseBuildImpl &build) {
|
||||
vector<raw_dfa> buildAnchoredDfas(RoseBuildImpl &build,
|
||||
const vector<LitFragment> &fragments) {
|
||||
vector<raw_dfa> dfas;
|
||||
|
||||
if (build.anchored_nfas.empty() && build.anchored_simple.empty()) {
|
||||
@ -833,9 +855,10 @@ vector<raw_dfa> buildAnchoredDfas(RoseBuildImpl &build) {
|
||||
return dfas;
|
||||
}
|
||||
|
||||
remapAnchoredReports(build);
|
||||
const auto frag_map = reverseFragMap(build, fragments);
|
||||
remapAnchoredReports(build, frag_map);
|
||||
|
||||
auto anch_dfas = getAnchoredDfas(build);
|
||||
auto anch_dfas = getAnchoredDfas(build, frag_map);
|
||||
mergeAnchoredDfas(anch_dfas, build);
|
||||
|
||||
dfas.reserve(anch_dfas.size());
|
||||
@ -847,8 +870,8 @@ vector<raw_dfa> buildAnchoredDfas(RoseBuildImpl &build) {
|
||||
}
|
||||
|
||||
aligned_unique_ptr<anchored_matcher_info>
|
||||
buildAnchoredMatcher(RoseBuildImpl &build, vector<raw_dfa> &dfas,
|
||||
size_t *asize) {
|
||||
buildAnchoredMatcher(RoseBuildImpl &build, const vector<LitFragment> &fragments,
|
||||
vector<raw_dfa> &dfas, size_t *asize) {
|
||||
const CompileContext &cc = build.cc;
|
||||
|
||||
if (dfas.empty()) {
|
||||
@ -858,7 +881,7 @@ buildAnchoredMatcher(RoseBuildImpl &build, vector<raw_dfa> &dfas,
|
||||
}
|
||||
|
||||
for (auto &rdfa : dfas) {
|
||||
remapIdsToPrograms(build, rdfa);
|
||||
remapIdsToPrograms(fragments, rdfa);
|
||||
}
|
||||
|
||||
vector<aligned_unique_ptr<NFA>> nfas;
|
||||
|
@ -44,11 +44,13 @@ namespace ue2 {
|
||||
|
||||
class RoseBuildImpl;
|
||||
struct raw_dfa;
|
||||
struct LitFragment;
|
||||
|
||||
/**
|
||||
* \brief Construct a set of anchored DFAs from our anchored literals/engines.
|
||||
*/
|
||||
std::vector<raw_dfa> buildAnchoredDfas(RoseBuildImpl &build);
|
||||
std::vector<raw_dfa> buildAnchoredDfas(RoseBuildImpl &build,
|
||||
const std::vector<LitFragment> &fragments);
|
||||
|
||||
/**
|
||||
* \brief Construct an anchored_matcher_info runtime structure from the given
|
||||
@ -58,8 +60,9 @@ std::vector<raw_dfa> buildAnchoredDfas(RoseBuildImpl &build);
|
||||
* given in litPrograms.
|
||||
*/
|
||||
aligned_unique_ptr<anchored_matcher_info>
|
||||
buildAnchoredMatcher(RoseBuildImpl &build, std::vector<raw_dfa> &dfas,
|
||||
size_t *asize);
|
||||
buildAnchoredMatcher(RoseBuildImpl &build,
|
||||
const std::vector<LitFragment> &fragments,
|
||||
std::vector<raw_dfa> &dfas, size_t *asize);
|
||||
|
||||
u32 anchoredStateSize(const anchored_matcher_info &atable);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1669,7 +1669,7 @@ bool roleOffsetsAreValid(const RoseGraph &g) {
|
||||
#endif // NDEBUG
|
||||
|
||||
aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildRose(u32 minWidth) {
|
||||
dumpRoseGraph(*this, nullptr, "rose_early.dot");
|
||||
dumpRoseGraph(*this, "rose_early.dot");
|
||||
|
||||
// Early check for Rose implementability.
|
||||
assert(canImplementGraphs(*this));
|
||||
@ -1780,7 +1780,7 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildRose(u32 minWidth) {
|
||||
assert(roleOffsetsAreValid(g));
|
||||
assert(historiesAreValid(g));
|
||||
|
||||
dumpRoseGraph(*this, nullptr, "rose_pre_norm.dot");
|
||||
dumpRoseGraph(*this, "rose_pre_norm.dot");
|
||||
|
||||
return buildFinalEngine(minWidth);
|
||||
}
|
||||
|
@ -112,8 +112,11 @@ string rose_off::str(void) const {
|
||||
|
||||
class RoseGraphWriter {
|
||||
public:
|
||||
RoseGraphWriter(const RoseBuildImpl &b_in, const RoseEngine *t_in) :
|
||||
build(b_in), t(t_in) {
|
||||
RoseGraphWriter(const RoseBuildImpl &b_in, const map<u32, u32> &frag_map_in,
|
||||
const map<left_id, u32> &lqm_in,
|
||||
const map<suffix_id, u32> &sqm_in, const RoseEngine *t_in)
|
||||
: frag_map(frag_map_in), leftfix_queue_map(lqm_in),
|
||||
suffix_queue_map(sqm_in), build(b_in), t(t_in) {
|
||||
for (const auto &m : build.ghost) {
|
||||
ghost.insert(m.second);
|
||||
}
|
||||
@ -160,8 +163,8 @@ public:
|
||||
if (g[v].suffix) {
|
||||
suffix_id suff(g[v].suffix);
|
||||
os << "\\n" << render_kind(suff) << " (top " << g[v].suffix.top;
|
||||
auto it = build.suffix_queue_map.find(suff);
|
||||
if (it != end(build.suffix_queue_map)) {
|
||||
auto it = suffix_queue_map.find(suff);
|
||||
if (it != end(suffix_queue_map)) {
|
||||
os << ", queue " << it->second;
|
||||
}
|
||||
os << ")";
|
||||
@ -174,8 +177,8 @@ public:
|
||||
if (g[v].left) {
|
||||
left_id left(g[v].left);
|
||||
os << "\\n" << render_kind(left) << " (queue ";
|
||||
auto it = build.leftfix_queue_map.find(left);
|
||||
if (it != end(build.leftfix_queue_map)) {
|
||||
auto it = leftfix_queue_map.find(left);
|
||||
if (it != end(leftfix_queue_map)) {
|
||||
os << it->second;
|
||||
} else {
|
||||
os << "??";
|
||||
@ -248,8 +251,8 @@ private:
|
||||
// Render the literal associated with a vertex.
|
||||
void writeLiteral(ostream &os, u32 id) const {
|
||||
os << "lit=" << id;
|
||||
if (id < build.literal_info.size()) {
|
||||
os << "/" << build.literal_info[id].fragment_id << " ";
|
||||
if (contains(frag_map, id)) {
|
||||
os << "/" << frag_map.at(id) << " ";
|
||||
} else {
|
||||
os << "/nofrag ";
|
||||
}
|
||||
@ -269,13 +272,32 @@ private:
|
||||
}
|
||||
|
||||
set<RoseVertex> ghost;
|
||||
const map<u32, u32> &frag_map;
|
||||
const map<left_id, u32> &leftfix_queue_map;
|
||||
const map<suffix_id, u32> &suffix_queue_map;
|
||||
const RoseBuildImpl &build;
|
||||
const RoseEngine *t;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
static
|
||||
map<u32, u32> makeFragMap(const vector<LitFragment> &fragments) {
|
||||
map<u32, u32> fm;
|
||||
for (const auto &f : fragments) {
|
||||
for (u32 id : f.lit_ids) {
|
||||
fm[id] = f.fragment_id;
|
||||
}
|
||||
}
|
||||
|
||||
return fm;
|
||||
}
|
||||
|
||||
static
|
||||
void dumpRoseGraph(const RoseBuildImpl &build, const RoseEngine *t,
|
||||
const vector<LitFragment> &fragments,
|
||||
const map<left_id, u32> &leftfix_queue_map,
|
||||
const map<suffix_id, u32> &suffix_queue_map,
|
||||
const char *filename) {
|
||||
const Grey &grey = build.cc.grey;
|
||||
|
||||
@ -293,10 +315,16 @@ void dumpRoseGraph(const RoseBuildImpl &build, const RoseEngine *t,
|
||||
DEBUG_PRINTF("dumping graph to %s\n", ss.str().c_str());
|
||||
ofstream os(ss.str());
|
||||
|
||||
RoseGraphWriter writer(build, t);
|
||||
auto frag_map = makeFragMap(fragments);
|
||||
RoseGraphWriter writer(build, frag_map, leftfix_queue_map, suffix_queue_map,
|
||||
t);
|
||||
writeGraphviz(os, build.g, writer, get(boost::vertex_index, build.g));
|
||||
}
|
||||
|
||||
void dumpRoseGraph(const RoseBuildImpl &build, const char *filename) {
|
||||
dumpRoseGraph(build, nullptr, {}, {}, {}, filename);
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct CompareVertexRole {
|
||||
explicit CompareVertexRole(const RoseGraph &g_in) : g(g_in) {}
|
||||
@ -321,11 +349,14 @@ void lit_graph_info(const RoseBuildImpl &build, const rose_literal_info &li,
|
||||
}
|
||||
|
||||
static
|
||||
void dumpRoseLiterals(const RoseBuildImpl &build, const char *filename) {
|
||||
void dumpRoseLiterals(const RoseBuildImpl &build,
|
||||
const vector<LitFragment> &fragments,
|
||||
const Grey &grey) {
|
||||
const RoseGraph &g = build.g;
|
||||
map<u32, u32> frag_map = makeFragMap(fragments);
|
||||
|
||||
DEBUG_PRINTF("dumping literals\n");
|
||||
ofstream os(filename);
|
||||
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;
|
||||
@ -353,8 +384,11 @@ void dumpRoseLiterals(const RoseBuildImpl &build, const char *filename) {
|
||||
break;
|
||||
}
|
||||
|
||||
os << " ID " << id << "/" << lit_info.fragment_id << ": \""
|
||||
<< escapeString(s.get_string()) << "\""
|
||||
os << " ID " << id;
|
||||
if (contains(frag_map, id)) {
|
||||
os << "/" << frag_map.at(id);
|
||||
}
|
||||
os << ": \"" << escapeString(s.get_string()) << "\""
|
||||
<< " (len " << s.length() << ",";
|
||||
if (s.any_nocase()) {
|
||||
os << " nocase,";
|
||||
@ -833,7 +867,7 @@ void dumpMultipathShufti(ofstream &os, u32 len, const u8 *lo, const u8 *hi,
|
||||
#define PROGRAM_CASE(name) \
|
||||
case ROSE_INSTR_##name: { \
|
||||
os << " " << std::setw(4) << std::setfill('0') << (pc - pc_base) \
|
||||
<< ": " #name " (" << (int)ROSE_INSTR_##name << ")" << endl; \
|
||||
<< ": " #name "\n"; \
|
||||
const auto *ri = (const struct ROSE_STRUCT_##name *)pc;
|
||||
|
||||
#define PROGRAM_NEXT_INSTRUCTION \
|
||||
@ -1444,13 +1478,13 @@ void dumpProgram(ofstream &os, const RoseEngine *t, const char *pc) {
|
||||
#undef PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
static
|
||||
void dumpRoseLitPrograms(const RoseBuildImpl &build, const RoseEngine *t,
|
||||
const string &filename) {
|
||||
void dumpRoseLitPrograms(const vector<LitFragment> &fragments,
|
||||
const RoseEngine *t, const string &filename) {
|
||||
ofstream os(filename);
|
||||
|
||||
// Collect all programs referenced by a literal fragment.
|
||||
vector<u32> programs;
|
||||
for (const auto &frag : build.fragments) {
|
||||
for (const auto &frag : fragments) {
|
||||
if (frag.lit_program_offset) {
|
||||
programs.push_back(frag.lit_program_offset);
|
||||
}
|
||||
@ -2185,18 +2219,21 @@ void roseDumpComponents(const RoseEngine *t, bool dump_raw,
|
||||
}
|
||||
|
||||
static
|
||||
void roseDumpPrograms(const RoseBuildImpl &build, const RoseEngine *t,
|
||||
void roseDumpPrograms(const vector<LitFragment> &fragments, const RoseEngine *t,
|
||||
const string &base) {
|
||||
dumpRoseLitPrograms(build, t, base + "/rose_lit_programs.txt");
|
||||
dumpRoseLitPrograms(fragments, t, base + "/rose_lit_programs.txt");
|
||||
dumpRoseEodPrograms(t, base + "/rose_eod_programs.txt");
|
||||
dumpRoseReportPrograms(t, base + "/rose_report_programs.txt");
|
||||
dumpRoseAnchoredPrograms(t, base + "/rose_anchored_programs.txt");
|
||||
dumpRoseDelayPrograms(t, base + "/rose_delay_programs.txt");
|
||||
}
|
||||
|
||||
void dumpRose(const RoseBuildImpl &build, const RoseEngine *t) {
|
||||
void dumpRose(const RoseBuildImpl &build, const vector<LitFragment> &fragments,
|
||||
const map<left_id, u32> &leftfix_queue_map,
|
||||
const map<suffix_id, u32> &suffix_queue_map,
|
||||
const RoseEngine *t) {
|
||||
const Grey &grey = build.cc.grey;
|
||||
|
||||
|
||||
if (!grey.dumpFlags) {
|
||||
return;
|
||||
}
|
||||
@ -2218,16 +2255,14 @@ void dumpRose(const RoseBuildImpl &build, const RoseEngine *t) {
|
||||
fclose(f);
|
||||
|
||||
roseDumpComponents(t, false, grey.dumpPath);
|
||||
roseDumpPrograms(build, t, grey.dumpPath);
|
||||
roseDumpPrograms(fragments, t, grey.dumpPath);
|
||||
|
||||
// Graph.
|
||||
dumpRoseGraph(build, t, "rose.dot");
|
||||
dumpRoseGraph(build, t, fragments, leftfix_queue_map, suffix_queue_map,
|
||||
"rose.dot");
|
||||
|
||||
// Literals.
|
||||
ss.str("");
|
||||
ss.clear();
|
||||
ss << grey.dumpPath << "rose_literals.txt";
|
||||
dumpRoseLiterals(build, ss.str().c_str());
|
||||
// Literals
|
||||
dumpRoseLiterals(build, fragments, grey);
|
||||
|
||||
f = fopen((grey.dumpPath + "/rose_struct.txt").c_str(), "w");
|
||||
roseDumpStructRaw(t, f);
|
||||
|
@ -29,6 +29,9 @@
|
||||
#ifndef ROSE_BUILD_DUMP_H
|
||||
#define ROSE_BUILD_DUMP_H
|
||||
|
||||
#include "ue2common.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -39,30 +42,40 @@ namespace ue2 {
|
||||
class RoseBuildImpl;
|
||||
struct Grey;
|
||||
struct hwlmLiteral;
|
||||
struct LitFragment;
|
||||
struct left_id;
|
||||
struct suffix_id;
|
||||
|
||||
#ifdef DUMP_SUPPORT
|
||||
// Dump the Rose graph in graphviz representation.
|
||||
void dumpRoseGraph(const RoseBuildImpl &build, const RoseEngine *t,
|
||||
const char *filename);
|
||||
void dumpRoseGraph(const RoseBuildImpl &build, const char *filename);
|
||||
|
||||
void dumpRose(const RoseBuildImpl &build, const RoseEngine *t);
|
||||
void dumpRose(const RoseBuildImpl &build,
|
||||
const std::vector<LitFragment> &fragments,
|
||||
const std::map<left_id, u32> &leftfix_queue_map,
|
||||
const std::map<suffix_id, u32> &suffix_queue_map,
|
||||
const RoseEngine *t);
|
||||
|
||||
void dumpMatcherLiterals(const std::vector<hwlmLiteral> &lits,
|
||||
const std::string &name, const Grey &grey);
|
||||
|
||||
#else
|
||||
|
||||
static UNUSED
|
||||
void dumpRoseGraph(const RoseBuildImpl &, const RoseEngine *, const char *) {
|
||||
void dumpRoseGraph(const RoseBuildImpl &, const char *) {
|
||||
}
|
||||
|
||||
static UNUSED
|
||||
void dumpRose(const RoseBuildImpl &, const RoseEngine *) {
|
||||
void dumpRose(const RoseBuildImpl &, const std::vector<LitFragment> &,
|
||||
const std::map<left_id, u32> &, const std::map<suffix_id, u32> &,
|
||||
const RoseEngine *) {
|
||||
}
|
||||
|
||||
static UNUSED
|
||||
void dumpMatcherLiterals(const std::vector<hwlmLiteral> &, const std::string &,
|
||||
const Grey &) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace ue2
|
||||
|
@ -264,7 +264,6 @@ struct rose_literal_info {
|
||||
ue2::flat_set<RoseVertex> vertices;
|
||||
rose_group group_mask = 0;
|
||||
u32 undelayed_id = MO_INVALID_IDX;
|
||||
u32 fragment_id = MO_INVALID_IDX; //!< ID corresponding to literal prog.
|
||||
bool squash_group = false;
|
||||
bool requires_benefits = false;
|
||||
};
|
||||
@ -437,15 +436,6 @@ private:
|
||||
|
||||
std::set<ReportID> all_reports(const OutfixInfo &outfix);
|
||||
|
||||
struct LitFragment {
|
||||
LitFragment(u32 fragment_id_in, rose_group groups_in)
|
||||
: fragment_id(fragment_id_in), groups(groups_in) {}
|
||||
u32 fragment_id;
|
||||
rose_group groups;
|
||||
u32 lit_program_offset = ROSE_INVALID_PROG_OFFSET;
|
||||
u32 delay_program_offset = ROSE_INVALID_PROG_OFFSET;
|
||||
};
|
||||
|
||||
// Concrete impl class
|
||||
class RoseBuildImpl : public RoseBuild {
|
||||
public:
|
||||
@ -576,19 +566,11 @@ public:
|
||||
|
||||
u32 ematcher_region_size; /**< number of bytes the eod table runs over */
|
||||
|
||||
/** \brief Mapping from leftfix to queue ID (used in dump code). */
|
||||
unordered_map<left_id, u32> leftfix_queue_map;
|
||||
|
||||
/** \brief Mapping from suffix to queue ID (used in dump code). */
|
||||
unordered_map<suffix_id, u32> suffix_queue_map;
|
||||
|
||||
/** \brief Mapping from anchored literal ID to the original literal suffix
|
||||
* present when the literal was added to the literal matcher. Used for
|
||||
* overlap calculation in history assignment. */
|
||||
std::map<u32, rose_literal_id> anchoredLitSuffix;
|
||||
|
||||
std::vector<LitFragment> fragments;
|
||||
|
||||
unordered_set<left_id> transient;
|
||||
unordered_map<left_id, rose_group> rose_squash_masks;
|
||||
|
||||
|
@ -350,9 +350,6 @@ void findMoreLiteralMasks(RoseBuildImpl &build) {
|
||||
const u32 id = e.first;
|
||||
const auto &lit = e.second;
|
||||
|
||||
// This pass takes place before fragment IDs are assigned to literals.
|
||||
assert(build.literal_info.at(id).fragment_id == MO_INVALID_IDX);
|
||||
|
||||
if (lit.delay || build.isDelayed(id)) {
|
||||
continue;
|
||||
}
|
||||
@ -673,6 +670,7 @@ struct MatcherProto {
|
||||
*/
|
||||
static
|
||||
MatcherProto makeMatcherProto(const RoseBuildImpl &build,
|
||||
const vector<LitFragment> &fragments,
|
||||
rose_literal_table table, bool delay_rebuild,
|
||||
size_t max_len, u32 max_offset = ROSE_BOUND_INF) {
|
||||
MatcherProto mp;
|
||||
@ -682,92 +680,91 @@ MatcherProto makeMatcherProto(const RoseBuildImpl &build,
|
||||
assert(build.cc.streaming);
|
||||
}
|
||||
|
||||
for (const auto &e : build.literals.right) {
|
||||
const u32 id = e.first;
|
||||
if (build.literal_info.at(id).fragment_id == MO_INVALID_IDX) {
|
||||
continue;
|
||||
}
|
||||
for (const auto &f : fragments) {
|
||||
for (u32 id : f.lit_ids) {
|
||||
const rose_literal_id &lit = build.literals.right.at(id);
|
||||
|
||||
if (e.second.delay) {
|
||||
continue; /* delay id's are virtual-ish */
|
||||
}
|
||||
if (lit.table != table) {
|
||||
continue; /* wrong table */
|
||||
}
|
||||
|
||||
if (e.second.table != table) {
|
||||
continue; /* wrong table */
|
||||
}
|
||||
if (lit.delay) {
|
||||
continue; /* delay id's are virtual-ish */
|
||||
}
|
||||
|
||||
assert(id < build.literal_info.size());
|
||||
const rose_literal_info &info = build.literal_info[id];
|
||||
/* Note: requires_benefits are handled in the literal entries */
|
||||
const ue2_literal &lit = e.second.s;
|
||||
assert(id < build.literal_info.size());
|
||||
const auto &info = build.literal_info.at(id);
|
||||
|
||||
DEBUG_PRINTF("lit='%s' (len %zu)\n", escapeString(lit).c_str(),
|
||||
lit.length());
|
||||
/* Note: requires_benefits are handled in the literal entries */
|
||||
const ue2_literal &s = lit.s;
|
||||
|
||||
// When building the delay rebuild table, we only want to include
|
||||
// literals that have delayed variants.
|
||||
if (delay_rebuild && info.delayed_ids.empty()) {
|
||||
DEBUG_PRINTF("not needed for delay rebuild\n");
|
||||
continue;
|
||||
}
|
||||
DEBUG_PRINTF("lit='%s' (len %zu)\n", escapeString(s).c_str(),
|
||||
s.length());
|
||||
|
||||
if (max_offset != ROSE_BOUND_INF) {
|
||||
u64a min_report = literalMinReportOffset(build, e.second, info);
|
||||
if (min_report > max_offset) {
|
||||
DEBUG_PRINTF("min report offset=%llu exceeds max_offset=%u\n",
|
||||
min_report, max_offset);
|
||||
// When building the delay rebuild table, we only want to include
|
||||
// literals that have delayed variants.
|
||||
if (delay_rebuild && info.delayed_ids.empty()) {
|
||||
DEBUG_PRINTF("not needed for delay rebuild\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (max_offset != ROSE_BOUND_INF) {
|
||||
u64a min_report = literalMinReportOffset(build, lit, info);
|
||||
if (min_report > max_offset) {
|
||||
DEBUG_PRINTF("min report offset=%llu exceeds "
|
||||
"max_offset=%u\n", min_report, max_offset);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const vector<u8> &msk = lit.msk;
|
||||
const vector<u8> &cmp = lit.cmp;
|
||||
bool noruns = isNoRunsLiteral(build, id, info, max_len);
|
||||
|
||||
size_t lit_hist_len = 0;
|
||||
if (build.cc.streaming) {
|
||||
lit_hist_len = max(msk.size(), min(s.length(), max_len));
|
||||
lit_hist_len = lit_hist_len ? lit_hist_len - 1 : 0;
|
||||
}
|
||||
DEBUG_PRINTF("lit requires %zu bytes of history\n", lit_hist_len);
|
||||
assert(lit_hist_len <= build.cc.grey.maxHistoryAvailable);
|
||||
|
||||
auto lit_final = s; // copy
|
||||
|
||||
if (lit_final.length() > ROSE_SHORT_LITERAL_LEN_MAX) {
|
||||
DEBUG_PRINTF("truncating to tail of length %zu\n",
|
||||
size_t{ROSE_SHORT_LITERAL_LEN_MAX});
|
||||
lit_final.erase(0, lit_final.length()
|
||||
- ROSE_SHORT_LITERAL_LEN_MAX);
|
||||
// We shouldn't have set a threshold below 8 chars.
|
||||
assert(msk.size() <= ROSE_SHORT_LITERAL_LEN_MAX);
|
||||
assert(!noruns);
|
||||
}
|
||||
|
||||
const auto &s_final = lit_final.get_string();
|
||||
bool nocase = lit_final.any_nocase();
|
||||
|
||||
DEBUG_PRINTF("id=%u, s='%s', nocase=%d, noruns=%d, msk=%s, "
|
||||
"cmp=%s\n", f.fragment_id,
|
||||
escapeString(s_final).c_str(), (int)nocase, noruns,
|
||||
dumpMask(msk).c_str(), dumpMask(cmp).c_str());
|
||||
|
||||
if (!maskIsConsistent(s_final, nocase, msk, cmp)) {
|
||||
DEBUG_PRINTF("msk/cmp for literal can't match, skipping\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
mp.accel_lits.emplace_back(s.get_string(), s.any_nocase(), msk, cmp,
|
||||
info.group_mask);
|
||||
mp.history_required = max(mp.history_required, lit_hist_len);
|
||||
|
||||
u32 prog_offset = delay_rebuild ? f.delay_program_offset
|
||||
: f.lit_program_offset;
|
||||
const auto &groups = f.groups;
|
||||
|
||||
mp.lits.emplace_back(move(s_final), nocase, noruns, prog_offset,
|
||||
groups, msk, cmp);
|
||||
}
|
||||
|
||||
const vector<u8> &msk = e.second.msk;
|
||||
const vector<u8> &cmp = e.second.cmp;
|
||||
bool noruns = isNoRunsLiteral(build, id, info, max_len);
|
||||
|
||||
size_t lit_hist_len = 0;
|
||||
if (build.cc.streaming) {
|
||||
lit_hist_len = max(msk.size(), min(lit.length(), max_len));
|
||||
lit_hist_len = lit_hist_len ? lit_hist_len - 1 : 0;
|
||||
}
|
||||
DEBUG_PRINTF("lit requires %zu bytes of history\n", lit_hist_len);
|
||||
assert(lit_hist_len <= build.cc.grey.maxHistoryAvailable);
|
||||
|
||||
auto lit_final = lit; // copy
|
||||
|
||||
if (lit_final.length() > ROSE_SHORT_LITERAL_LEN_MAX) {
|
||||
DEBUG_PRINTF("truncating to tail of length %zu\n",
|
||||
size_t{ROSE_SHORT_LITERAL_LEN_MAX});
|
||||
lit_final.erase(0, lit_final.length() - ROSE_SHORT_LITERAL_LEN_MAX);
|
||||
// We shouldn't have set a threshold below 8 chars.
|
||||
assert(msk.size() <= ROSE_SHORT_LITERAL_LEN_MAX);
|
||||
assert(!noruns);
|
||||
}
|
||||
|
||||
const auto &s = lit_final.get_string();
|
||||
bool nocase = lit_final.any_nocase();
|
||||
|
||||
DEBUG_PRINTF("id=%u, s='%s', nocase=%d, noruns=%d, msk=%s, "
|
||||
"cmp=%s\n",
|
||||
info.fragment_id, escapeString(s).c_str(), (int)nocase,
|
||||
noruns, dumpMask(msk).c_str(), dumpMask(cmp).c_str());
|
||||
|
||||
if (!maskIsConsistent(s, nocase, msk, cmp)) {
|
||||
DEBUG_PRINTF("msk/cmp for literal can't match, skipping\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
mp.accel_lits.emplace_back(lit.get_string(), lit.any_nocase(), msk, cmp,
|
||||
info.group_mask);
|
||||
mp.history_required = max(mp.history_required, lit_hist_len);
|
||||
|
||||
assert(info.fragment_id < build.fragments.size());
|
||||
const auto &frag = build.fragments.at(info.fragment_id);
|
||||
u32 prog_offset =
|
||||
delay_rebuild ? frag.delay_program_offset : frag.lit_program_offset;
|
||||
const auto &groups = frag.groups;
|
||||
|
||||
mp.lits.emplace_back(move(s), nocase, noruns, prog_offset, groups, msk,
|
||||
cmp);
|
||||
}
|
||||
|
||||
sort_and_unique(mp.lits);
|
||||
@ -809,14 +806,15 @@ void buildAccel(const RoseBuildImpl &build, const MatcherProto &mp,
|
||||
}
|
||||
|
||||
aligned_unique_ptr<HWLM>
|
||||
buildFloatingMatcher(const RoseBuildImpl &build, size_t longLitLengthThreshold,
|
||||
rose_group *fgroups, size_t *fsize,
|
||||
size_t *historyRequired) {
|
||||
buildFloatingMatcher(const RoseBuildImpl &build,
|
||||
const vector<LitFragment> &fragments,
|
||||
size_t longLitLengthThreshold, rose_group *fgroups,
|
||||
size_t *fsize, size_t *historyRequired) {
|
||||
*fsize = 0;
|
||||
*fgroups = 0;
|
||||
|
||||
auto mp =
|
||||
makeMatcherProto(build, ROSE_FLOATING, false, longLitLengthThreshold);
|
||||
auto mp = makeMatcherProto(build, fragments, ROSE_FLOATING, false,
|
||||
longLitLengthThreshold);
|
||||
if (mp.lits.empty()) {
|
||||
DEBUG_PRINTF("empty floating matcher\n");
|
||||
return nullptr;
|
||||
@ -847,6 +845,7 @@ buildFloatingMatcher(const RoseBuildImpl &build, size_t longLitLengthThreshold,
|
||||
}
|
||||
|
||||
aligned_unique_ptr<HWLM> buildDelayRebuildMatcher(const RoseBuildImpl &build,
|
||||
const vector<LitFragment> &fragments,
|
||||
size_t longLitLengthThreshold,
|
||||
size_t *drsize) {
|
||||
*drsize = 0;
|
||||
@ -856,8 +855,8 @@ aligned_unique_ptr<HWLM> buildDelayRebuildMatcher(const RoseBuildImpl &build,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto mp =
|
||||
makeMatcherProto(build, ROSE_FLOATING, true, longLitLengthThreshold);
|
||||
auto mp = makeMatcherProto(build, fragments, ROSE_FLOATING, true,
|
||||
longLitLengthThreshold);
|
||||
if (mp.lits.empty()) {
|
||||
DEBUG_PRINTF("empty delay rebuild matcher\n");
|
||||
return nullptr;
|
||||
@ -877,8 +876,9 @@ aligned_unique_ptr<HWLM> buildDelayRebuildMatcher(const RoseBuildImpl &build,
|
||||
return hwlm;
|
||||
}
|
||||
|
||||
aligned_unique_ptr<HWLM> buildSmallBlockMatcher(const RoseBuildImpl &build,
|
||||
size_t *sbsize) {
|
||||
aligned_unique_ptr<HWLM>
|
||||
buildSmallBlockMatcher(const RoseBuildImpl &build,
|
||||
const vector<LitFragment> &fragments, size_t *sbsize) {
|
||||
*sbsize = 0;
|
||||
|
||||
if (build.cc.streaming) {
|
||||
@ -893,7 +893,7 @@ aligned_unique_ptr<HWLM> buildSmallBlockMatcher(const RoseBuildImpl &build,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto mp = makeMatcherProto(build, ROSE_FLOATING, false,
|
||||
auto mp = makeMatcherProto(build, fragments, ROSE_FLOATING, false,
|
||||
ROSE_SMALL_BLOCK_LEN, ROSE_SMALL_BLOCK_LEN);
|
||||
if (mp.lits.empty()) {
|
||||
DEBUG_PRINTF("no floating table\n");
|
||||
@ -903,9 +903,10 @@ aligned_unique_ptr<HWLM> buildSmallBlockMatcher(const RoseBuildImpl &build,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto mp_anchored =
|
||||
makeMatcherProto(build, ROSE_ANCHORED_SMALL_BLOCK, false,
|
||||
ROSE_SMALL_BLOCK_LEN, ROSE_SMALL_BLOCK_LEN);
|
||||
auto mp_anchored = makeMatcherProto(build, fragments,
|
||||
ROSE_ANCHORED_SMALL_BLOCK, false,
|
||||
ROSE_SMALL_BLOCK_LEN,
|
||||
ROSE_SMALL_BLOCK_LEN);
|
||||
if (mp_anchored.lits.empty()) {
|
||||
DEBUG_PRINTF("no small-block anchored literals\n");
|
||||
return nullptr;
|
||||
@ -937,11 +938,12 @@ aligned_unique_ptr<HWLM> buildSmallBlockMatcher(const RoseBuildImpl &build,
|
||||
return hwlm;
|
||||
}
|
||||
|
||||
aligned_unique_ptr<HWLM> buildEodAnchoredMatcher(const RoseBuildImpl &build,
|
||||
size_t *esize) {
|
||||
aligned_unique_ptr<HWLM>
|
||||
buildEodAnchoredMatcher(const RoseBuildImpl &build,
|
||||
const vector<LitFragment> &fragments, size_t *esize) {
|
||||
*esize = 0;
|
||||
|
||||
auto mp = makeMatcherProto(build, ROSE_EOD_ANCHORED, false,
|
||||
auto mp = makeMatcherProto(build, fragments, ROSE_EOD_ANCHORED, false,
|
||||
build.ematcher_region_size);
|
||||
|
||||
if (mp.lits.empty()) {
|
||||
|
@ -36,25 +36,45 @@
|
||||
|
||||
#include "rose_build_impl.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct Grey;
|
||||
struct HWLM;
|
||||
|
||||
namespace ue2 {
|
||||
|
||||
struct LitFragment {
|
||||
LitFragment(u32 fragment_id_in, rose_group groups_in, u32 lit_id)
|
||||
: fragment_id(fragment_id_in), groups(groups_in), lit_ids({lit_id}) {}
|
||||
LitFragment(u32 fragment_id_in, rose_group groups_in,
|
||||
std::vector<u32> lit_ids_in)
|
||||
: fragment_id(fragment_id_in), groups(groups_in),
|
||||
lit_ids(std::move(lit_ids_in)) {}
|
||||
u32 fragment_id;
|
||||
rose_group groups;
|
||||
std::vector<u32> lit_ids;
|
||||
u32 lit_program_offset = ROSE_INVALID_PROG_OFFSET;
|
||||
u32 delay_program_offset = ROSE_INVALID_PROG_OFFSET;
|
||||
};
|
||||
|
||||
aligned_unique_ptr<HWLM> buildFloatingMatcher(const RoseBuildImpl &build,
|
||||
const std::vector<LitFragment> &fragments,
|
||||
size_t longLitLengthThreshold,
|
||||
rose_group *fgroups,
|
||||
size_t *fsize,
|
||||
size_t *historyRequired);
|
||||
|
||||
aligned_unique_ptr<HWLM> buildDelayRebuildMatcher(const RoseBuildImpl &build,
|
||||
const std::vector<LitFragment> &fragments,
|
||||
size_t longLitLengthThreshold,
|
||||
size_t *drsize);
|
||||
|
||||
aligned_unique_ptr<HWLM> buildSmallBlockMatcher(const RoseBuildImpl &build,
|
||||
const std::vector<LitFragment> &fragments,
|
||||
size_t *sbsize);
|
||||
|
||||
aligned_unique_ptr<HWLM> buildEodAnchoredMatcher(const RoseBuildImpl &build,
|
||||
const std::vector<LitFragment> &fragments,
|
||||
size_t *esize);
|
||||
|
||||
void findMoreLiteralMasks(RoseBuildImpl &build);
|
||||
|
@ -450,8 +450,7 @@ void RoseInstrSparseIterBegin::write(void *dest, RoseEngineBlob &blob,
|
||||
jump_offsets.push_back(offset_map.at(jump.second));
|
||||
}
|
||||
|
||||
vector<mmbit_sparse_iter> iter;
|
||||
mmbBuildSparseIterator(iter, keys, num_keys);
|
||||
auto iter = mmbBuildSparseIterator(keys, num_keys);
|
||||
assert(!iter.empty());
|
||||
inst->iter_offset = blob.add_iterator(iter);
|
||||
inst->jump_table = blob.add(jump_offsets.begin(), jump_offsets.end());
|
||||
@ -485,8 +484,7 @@ void RoseInstrSparseIterAny::write(void *dest, RoseEngineBlob &blob,
|
||||
inst->fail_jump = calc_jump(offset_map, this, target);
|
||||
|
||||
// Write the multibit sparse iterator.
|
||||
vector<mmbit_sparse_iter> iter;
|
||||
mmbBuildSparseIterator(iter, keys, num_keys);
|
||||
auto iter = mmbBuildSparseIterator(keys, num_keys);
|
||||
assert(!iter.empty());
|
||||
inst->iter_offset = blob.add_iterator(iter);
|
||||
}
|
||||
|
@ -155,9 +155,9 @@ void bfs(vector<mmbit_sparse_iter> &out, const TreeNode &tree) {
|
||||
|
||||
/** \brief Construct a sparse iterator over the values in \a bits for a
|
||||
* multibit of size \a total_bits. */
|
||||
void mmbBuildSparseIterator(vector<mmbit_sparse_iter> &out,
|
||||
const vector<u32> &bits, u32 total_bits) {
|
||||
assert(out.empty());
|
||||
vector<mmbit_sparse_iter> mmbBuildSparseIterator(const vector<u32> &bits,
|
||||
u32 total_bits) {
|
||||
vector<mmbit_sparse_iter> out;
|
||||
assert(!bits.empty());
|
||||
assert(total_bits > 0);
|
||||
assert(total_bits <= MMB_MAX_BITS);
|
||||
@ -186,6 +186,7 @@ void mmbBuildSparseIterator(vector<mmbit_sparse_iter> &out,
|
||||
#endif
|
||||
|
||||
DEBUG_PRINTF("iter has %zu records\n", out.size());
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -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:
|
||||
@ -61,8 +61,8 @@ u32 mmbit_size(u32 total_bits);
|
||||
|
||||
/** \brief Construct a sparse iterator over the values in \a bits for a
|
||||
* multibit of size \a total_bits. */
|
||||
void mmbBuildSparseIterator(std::vector<mmbit_sparse_iter> &out,
|
||||
const std::vector<u32> &bits, u32 total_bits);
|
||||
std::vector<mmbit_sparse_iter>
|
||||
mmbBuildSparseIterator(const std::vector<u32> &bits, u32 total_bits);
|
||||
|
||||
struct scatter_plan_raw;
|
||||
|
||||
|
@ -782,7 +782,6 @@ TEST_P(MultiBitTest, InitRangePlanChunked) {
|
||||
|
||||
TEST(MultiBit, SparseIteratorBegin1) {
|
||||
const u32 test_size = 100;
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits;
|
||||
|
||||
bits.push_back(1);
|
||||
@ -791,7 +790,7 @@ TEST(MultiBit, SparseIteratorBegin1) {
|
||||
bits.push_back(35);
|
||||
bits.push_back(68);
|
||||
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
//ASSERT_EQ(4U, it.size());
|
||||
|
||||
// Trivial initial test: all bits in 'bits' are on, all others are off
|
||||
@ -820,7 +819,6 @@ TEST(MultiBit, SparseIteratorBegin1) {
|
||||
|
||||
TEST(MultiBit, SparseIteratorBegin2) {
|
||||
const u32 test_size = 40000;
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits;
|
||||
|
||||
bits.push_back(1);
|
||||
@ -830,7 +828,7 @@ TEST(MultiBit, SparseIteratorBegin2) {
|
||||
bits.push_back(8920);
|
||||
bits.push_back(37000);
|
||||
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
//ASSERT_EQ(12U, it.size());
|
||||
|
||||
// Trivial initial test: all bits in 'bits' are on, all others are off
|
||||
@ -859,7 +857,6 @@ TEST(MultiBit, SparseIteratorBegin2) {
|
||||
|
||||
TEST(MultiBit, SparseIteratorNext1) {
|
||||
const u32 test_size = 100;
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits;
|
||||
|
||||
bits.push_back(1);
|
||||
@ -868,7 +865,7 @@ TEST(MultiBit, SparseIteratorNext1) {
|
||||
bits.push_back(35);
|
||||
bits.push_back(68);
|
||||
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
|
||||
// Trivial initial test: all bits in 'bits' are on, all others are off
|
||||
mmbit_holder ba(test_size);
|
||||
@ -924,7 +921,6 @@ TEST(MultiBit, SparseIteratorNext1) {
|
||||
|
||||
TEST(MultiBit, SparseIteratorNext2) {
|
||||
const u32 test_size = 40000;
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits;
|
||||
|
||||
bits.push_back(1);
|
||||
@ -939,7 +935,7 @@ TEST(MultiBit, SparseIteratorNext2) {
|
||||
bits.push_back(37000);
|
||||
bits.push_back(39999);
|
||||
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
|
||||
// Trivial initial test: all bits in 'bits' are on, all others are off
|
||||
mmbit_holder ba(test_size);
|
||||
@ -995,7 +991,6 @@ TEST(MultiBit, SparseIteratorNext2) {
|
||||
|
||||
TEST(MultiBit, SparseIteratorNextSmall) {
|
||||
const u32 test_size = 15;
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits;
|
||||
|
||||
bits.push_back(1);
|
||||
@ -1005,7 +1000,7 @@ TEST(MultiBit, SparseIteratorNextSmall) {
|
||||
bits.push_back(12);
|
||||
bits.push_back(14);
|
||||
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
|
||||
// Trivial initial test: all bits in 'bits' are on, all others are off
|
||||
mmbit_holder ba(test_size);
|
||||
@ -1064,13 +1059,12 @@ TEST_P(MultiBitTest, SparseIteratorBeginAll) {
|
||||
ASSERT_TRUE(ba != nullptr);
|
||||
|
||||
// Put all our bits into the sparse iterator.
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits;
|
||||
bits.reserve(test_size / stride);
|
||||
for (u64a i = 0; i < test_size; i += stride) {
|
||||
bits.push_back(i);
|
||||
}
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
|
||||
// Switch all bits on in state.
|
||||
mmbit_clear(ba, test_size);
|
||||
@ -1104,12 +1098,11 @@ TEST_P(MultiBitTest, SparseIteratorBeginThirds) {
|
||||
}
|
||||
|
||||
// Put all our bits into the sparse iterator
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits(test_size);
|
||||
for (u32 i = 0; i != test_size; i++) {
|
||||
bits[i] = i;
|
||||
}
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
|
||||
// Switch every third bits on in state
|
||||
mmbit_clear(ba, test_size);
|
||||
@ -1139,13 +1132,12 @@ TEST_P(MultiBitTest, SparseIteratorNextAll) {
|
||||
ASSERT_TRUE(ba != nullptr);
|
||||
|
||||
// Put all our bits into the sparse iterator.
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits;
|
||||
bits.reserve(test_size / stride);
|
||||
for (u64a i = 0; i < test_size; i += stride) {
|
||||
bits.push_back(i);
|
||||
}
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
|
||||
// Switch all bits on in state
|
||||
mmbit_clear(ba, test_size);
|
||||
@ -1182,14 +1174,13 @@ TEST_P(MultiBitTest, SparseIteratorNextExactStrided) {
|
||||
// Put all our bits into the sparse iterator and switch them on in the
|
||||
// state.
|
||||
mmbit_clear(ba, test_size);
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits;
|
||||
bits.reserve(test_size / stride);
|
||||
for (u64a i = 0; i < test_size; i += stride) {
|
||||
bits.push_back(i);
|
||||
mmbit_set(ba, test_size, i);
|
||||
}
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
|
||||
// Iterate over all bits.
|
||||
vector<mmbit_sparse_state> state(mmbit_sparse_iter_state_size(test_size));
|
||||
@ -1214,13 +1205,12 @@ TEST_P(MultiBitTest, SparseIteratorNextNone) {
|
||||
ASSERT_TRUE(ba != nullptr);
|
||||
|
||||
// Put all our bits into the sparse iterator.
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits;
|
||||
bits.reserve(test_size / stride);
|
||||
for (u64a i = 0; i < test_size; i += stride) {
|
||||
bits.push_back(i);
|
||||
}
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
|
||||
// Switch only the first bit on
|
||||
mmbit_clear(ba, test_size);
|
||||
@ -1243,13 +1233,12 @@ TEST_P(MultiBitTest, SparseIteratorUnsetAll) {
|
||||
ASSERT_TRUE(ba != nullptr);
|
||||
|
||||
// Put all our bits into the sparse iterator
|
||||
vector<mmbit_sparse_iter> it;
|
||||
vector<u32> bits;
|
||||
bits.reserve(test_size / stride);
|
||||
for (u64a i = 0; i < test_size; i += stride) {
|
||||
bits.push_back(i);
|
||||
}
|
||||
mmbBuildSparseIterator(it, bits, test_size);
|
||||
auto it = mmbBuildSparseIterator(bits, test_size);
|
||||
|
||||
// Switch all bits on
|
||||
mmbit_clear(ba, test_size);
|
||||
@ -1283,9 +1272,8 @@ TEST_P(MultiBitTest, SparseIteratorUnsetHalves) {
|
||||
odd.push_back(i);
|
||||
}
|
||||
|
||||
vector<mmbit_sparse_iter> it_even, it_odd;
|
||||
mmbBuildSparseIterator(it_even, even, test_size);
|
||||
mmbBuildSparseIterator(it_odd, odd, test_size);
|
||||
auto it_even = mmbBuildSparseIterator(even, test_size);
|
||||
auto it_odd = mmbBuildSparseIterator(odd, test_size);
|
||||
|
||||
// Switch all bits on
|
||||
mmbit_clear(ba, test_size);
|
||||
|
Loading…
x
Reference in New Issue
Block a user