diff --git a/src/compiler/compiler.cpp b/src/compiler/compiler.cpp index 49ed88f4..47bf514c 100644 --- a/src/compiler/compiler.cpp +++ b/src/compiler/compiler.cpp @@ -276,13 +276,12 @@ void addExpression(NG &ng, unsigned index, const char *expression, throw CompileError("Internal error."); } - auto &g = *built_expr.g; - if (!pe.expr.allow_vacuous && matches_everywhere(g)) { + if (!pe.expr.allow_vacuous && matches_everywhere(*built_expr.g)) { throw CompileError("Pattern matches empty buffer; use " "HS_FLAG_ALLOWEMPTY to enable support."); } - if (!ng.addGraph(built_expr.expr, g)) { + if (!ng.addGraph(built_expr.expr, std::move(built_expr.g))) { DEBUG_PRINTF("NFA addGraph failed on ID %u.\n", pe.expr.report); throw CompileError("Error compiling expression."); } diff --git a/src/nfagraph/ng.cpp b/src/nfagraph/ng.cpp index eded7af2..bdd767e9 100644 --- a/src/nfagraph/ng.cpp +++ b/src/nfagraph/ng.cpp @@ -315,7 +315,10 @@ bool processComponents(NG &ng, ExpressionInfo &expr, return false; } -bool NG::addGraph(ExpressionInfo &expr, NGHolder &g) { +bool NG::addGraph(ExpressionInfo &expr, unique_ptr g_ptr) { + assert(g_ptr); + NGHolder &g = *g_ptr; + // remove reports that aren't on vertices connected to accept. clearReports(g); @@ -431,15 +434,16 @@ bool NG::addGraph(ExpressionInfo &expr, NGHolder &g) { return true; } - // Split the graph into a set of connected components. + // Split the graph into a set of connected components and process those. + // Note: this invalidates g_ptr. - deque> g_comp = calcComponents(g); + auto g_comp = calcComponents(std::move(g_ptr)); assert(!g_comp.empty()); if (!som) { - for (u32 i = 0; i < g_comp.size(); i++) { - assert(g_comp[i]); - reformLeadingDots(*g_comp[i]); + for (auto &gc : g_comp) { + assert(gc); + reformLeadingDots(*gc); } recalcComponents(g_comp); @@ -453,12 +457,11 @@ bool NG::addGraph(ExpressionInfo &expr, NGHolder &g) { // have another shot at accepting the graph. if (cc.grey.prefilterReductions && expr.prefilter) { - for (u32 i = 0; i < g_comp.size(); i++) { - if (!g_comp[i]) { + for (auto &gc : g_comp) { + if (!gc) { continue; } - - prefilterReductions(*g_comp[i], cc); + prefilterReductions(*gc, cc); } if (processComponents(*this, expr, g_comp, som)) { diff --git a/src/nfagraph/ng.h b/src/nfagraph/ng.h index 6693773e..dc797acf 100644 --- a/src/nfagraph/ng.h +++ b/src/nfagraph/ng.h @@ -70,7 +70,7 @@ public: /** \brief Consumes a pattern, returns false or throws a CompileError * exception if the graph cannot be consumed. */ - bool addGraph(ExpressionInfo &expr, NGHolder &h); + bool addGraph(ExpressionInfo &expr, std::unique_ptr g_ptr); /** \brief Consumes a graph, cut-down version of addGraph for use by SOM * processing. */ diff --git a/src/nfagraph/ng_calc_components.cpp b/src/nfagraph/ng_calc_components.cpp index da6775e4..ff0d0fe1 100644 --- a/src/nfagraph/ng_calc_components.cpp +++ b/src/nfagraph/ng_calc_components.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: @@ -245,31 +245,33 @@ void renumberVertices(NFAUndirectedGraph &ug) { * one or more connected components, adding them to the comps deque. */ static -void splitIntoComponents(const NGHolder &g, deque> &comps, +void splitIntoComponents(unique_ptr g, + deque> &comps, const depth &max_head_depth, const depth &max_tail_depth, bool *shell_comp) { - DEBUG_PRINTF("graph has %zu vertices\n", num_vertices(g)); + DEBUG_PRINTF("graph has %zu vertices\n", num_vertices(*g)); assert(shell_comp); *shell_comp = false; // Compute "shell" head and tail subgraphs. vector depths; - calcDepths(g, depths); - auto head_shell = findHeadShell(g, depths, max_head_depth); - auto tail_shell = findTailShell(g, depths, max_tail_depth); + calcDepths(*g, depths); + auto head_shell = findHeadShell(*g, depths, max_head_depth); + auto tail_shell = findTailShell(*g, depths, max_tail_depth); for (auto v : head_shell) { tail_shell.erase(v); } - if (head_shell.size() + tail_shell.size() + N_SPECIALS >= num_vertices(g)) { + if (head_shell.size() + tail_shell.size() + N_SPECIALS >= + num_vertices(*g)) { DEBUG_PRINTF("all in shell component\n"); - comps.push_back(cloneHolder(g)); + comps.push_back(std::move(g)); *shell_comp = true; return; } - vector shell_edges = findShellEdges(g, head_shell, tail_shell); + vector shell_edges = findShellEdges(*g, head_shell, tail_shell); DEBUG_PRINTF("%zu vertices in head, %zu in tail, %zu shell edges\n", head_shell.size(), tail_shell.size(), shell_edges.size()); @@ -277,7 +279,7 @@ void splitIntoComponents(const NGHolder &g, deque> &comps, NFAUndirectedGraph ug; ue2::unordered_map old2new; - createUnGraph(g, true, true, ug, old2new); + createUnGraph(*g, true, true, ug, old2new); // Construct reverse mapping. ue2::unordered_map new2old; @@ -298,7 +300,7 @@ void splitIntoComponents(const NGHolder &g, deque> &comps, assert(num > 0); if (num == 1 && shell_edges.empty()) { DEBUG_PRINTF("single component\n"); - comps.push_back(cloneHolder(g)); + comps.push_back(std::move(g)); return; } @@ -313,7 +315,7 @@ void splitIntoComponents(const NGHolder &g, deque> &comps, assert(contains(new2old, uv)); NFAVertex v = new2old.at(uv); verts[c].push_back(v); - DEBUG_PRINTF("vertex %zu is in comp %u\n", g[v].index, c); + DEBUG_PRINTF("vertex %zu is in comp %u\n", (*g)[v].index, c); } ue2::unordered_map v_map; // temp map for fillHolder @@ -328,12 +330,12 @@ void splitIntoComponents(const NGHolder &g, deque> &comps, auto gc = ue2::make_unique(); v_map.clear(); - fillHolder(gc.get(), g, vv, &v_map); + fillHolder(gc.get(), *g, vv, &v_map); // Remove shell edges, which will get their own component. for (const auto &e : shell_edges) { - auto cu = v_map.at(source(e, g)); - auto cv = v_map.at(target(e, g)); + auto cu = v_map.at(source(e, *g)); + auto cv = v_map.at(target(e, *g)); assert(edge(cu, cv, *gc).second); remove_edge(cu, cv, *gc); } @@ -352,7 +354,7 @@ void splitIntoComponents(const NGHolder &g, deque> &comps, auto gc = ue2::make_unique(); v_map.clear(); - fillHolder(gc.get(), g, vv, &v_map); + fillHolder(gc.get(), *g, vv, &v_map); pruneUseless(*gc); DEBUG_PRINTF("shell edge component %zu has %zu vertices\n", @@ -374,26 +376,26 @@ void splitIntoComponents(const NGHolder &g, deque> &comps, })); } -deque> calcComponents(const NGHolder &g) { +deque> calcComponents(unique_ptr g) { deque> comps; // For trivial cases, we needn't bother running the full // connected_components algorithm. - if (isAlternationOfClasses(g)) { - comps.push_back(cloneHolder(g)); + if (isAlternationOfClasses(*g)) { + comps.push_back(std::move(g)); return comps; } bool shell_comp = false; - splitIntoComponents(g, comps, MAX_HEAD_SHELL_DEPTH, MAX_TAIL_SHELL_DEPTH, - &shell_comp); + splitIntoComponents(std::move(g), comps, MAX_HEAD_SHELL_DEPTH, + MAX_TAIL_SHELL_DEPTH, &shell_comp); if (shell_comp) { DEBUG_PRINTF("re-running on shell comp\n"); assert(!comps.empty()); - auto sc = move(comps.back()); + auto sc = std::move(comps.back()); comps.pop_back(); - splitIntoComponents(*sc, comps, 0, 0, &shell_comp); + splitIntoComponents(std::move(sc), comps, 0, 0, &shell_comp); } DEBUG_PRINTF("finished; split into %zu components\n", comps.size()); @@ -409,14 +411,13 @@ void recalcComponents(deque> &comps) { } if (isAlternationOfClasses(*gc)) { - out.push_back(move(gc)); + out.push_back(std::move(gc)); continue; } - auto gc_comps = calcComponents(*gc); - for (auto &elem : gc_comps) { - out.push_back(move(elem)); - } + auto gc_comps = calcComponents(std::move(gc)); + out.insert(end(out), std::make_move_iterator(begin(gc_comps)), + std::make_move_iterator(end(gc_comps))); } // Replace comps with our recalculated list. diff --git a/src/nfagraph/ng_calc_components.h b/src/nfagraph/ng_calc_components.h index e68c81fc..0359f4a0 100644 --- a/src/nfagraph/ng_calc_components.h +++ b/src/nfagraph/ng_calc_components.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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: @@ -42,7 +42,8 @@ class NGHolder; bool isAlternationOfClasses(const NGHolder &g); -std::deque> calcComponents(const NGHolder &g); +std::deque> +calcComponents(std::unique_ptr g); void recalcComponents(std::deque> &comps); diff --git a/unit/internal/nfagraph_comp.cpp b/unit/internal/nfagraph_comp.cpp index 41af3f0c..8aae9519 100644 --- a/unit/internal/nfagraph_comp.cpp +++ b/unit/internal/nfagraph_comp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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: @@ -33,13 +33,8 @@ #include "config.h" #include "gtest/gtest.h" #include "nfagraph_common.h" -#include "grey.h" -#include "hs.h" -#include "compiler/compiler.h" #include "nfagraph/ng.h" -#include "nfagraph/ng_builder.h" #include "nfagraph/ng_calc_components.h" -#include "util/target_info.h" using namespace std; using namespace ue2; @@ -48,7 +43,7 @@ TEST(NFAGraph, CalcComp1) { auto graph = constructGraph("abc|def|ghi", 0); ASSERT_TRUE(graph != nullptr); - deque> comps = calcComponents(*graph); + auto comps = calcComponents(std::move(graph)); ASSERT_EQ(3, comps.size()); } @@ -56,7 +51,7 @@ TEST(NFAGraph, CalcComp2) { auto graph = constructGraph("a|b|c|d|e|f|g|h|i", 0); ASSERT_TRUE(graph != nullptr); - deque> comps = calcComponents(*graph); + auto comps = calcComponents(std::move(graph)); // We should be identifying this as a trivial case and not splitting it. ASSERT_EQ(1, comps.size());