vectorscan/src/nfagraph/ng_vacuous.cpp
2015-10-20 09:13:35 +11:00

142 lines
4.5 KiB
C++

/*
* Copyright (c) 2015, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/** \file
* \brief Build code for vacuous graphs.
*/
#include "ng_vacuous.h"
#include "grey.h"
#include "ng.h"
#include "ng_util.h"
using namespace std;
namespace ue2 {
static
ReportID getInternalId(ReportManager &rm, const NGWrapper &graph) {
Report ir = rm.getBasicInternalReport(graph);
// Apply any extended params.
if (graph.min_offset || graph.max_offset != MAX_OFFSET) {
ir.minOffset = graph.min_offset;
ir.maxOffset = graph.max_offset;
}
assert(!graph.min_length); // should be handled elsewhere.
return rm.getInternalId(ir);
}
static
void makeFirehose(BoundaryReports &boundary, ReportManager &rm, NGWrapper &g) {
const ReportID r = getInternalId(rm, g);
boundary.report_at_0_eod.insert(r);
boundary.report_at_0.insert(r);
// Replace the graph with a '.+'.
clear_graph(g);
clearReports(g);
remove_edge(g.start, g.accept, g);
remove_edge(g.start, g.acceptEod, g);
remove_edge(g.startDs, g.accept, g);
remove_edge(g.startDs, g.acceptEod, g);
NFAVertex v = add_vertex(g);
g[v].char_reach.setall();
g[v].reports.insert(r);
add_edge(v, v, g);
add_edge(g.start, v, g);
add_edge(g.startDs, v, g);
add_edge(v, g.accept, g);
}
static
void makeAnchoredAcceptor(BoundaryReports &boundary, ReportManager &rm,
NGWrapper &g) {
boundary.report_at_0.insert(getInternalId(rm, g));
remove_edge(g.start, g.accept, g);
remove_edge(g.start, g.acceptEod, g);
g[g.start].reports.clear();
}
static
void makeEndAnchoredAcceptor(BoundaryReports &boundary, ReportManager &rm,
NGWrapper &g) {
boundary.report_at_eod.insert(getInternalId(rm, g));
remove_edge(g.startDs, g.acceptEod, g);
remove_edge(g.start, g.acceptEod, g);
g[g.start].reports.clear();
g[g.startDs].reports.clear();
}
static
void makeNothingAcceptor(BoundaryReports &boundary, ReportManager &rm,
NGWrapper &g) {
boundary.report_at_0_eod.insert(getInternalId(rm, g));
remove_edge(g.start, g.acceptEod, g);
g[g.start].reports.clear();
}
bool splitOffVacuous(BoundaryReports &boundary, ReportManager &rm,
NGWrapper &g) {
if (edge(g.startDs, g.accept, g).second) {
// e.g. '.*'; match "between" every byte
DEBUG_PRINTF("graph is firehose\n");
makeFirehose(boundary, rm, g);
return true;
}
bool work_done = false;
if (edge(g.start, g.accept, g).second) {
DEBUG_PRINTF("creating anchored acceptor\n");
makeAnchoredAcceptor(boundary, rm, g);
work_done = true;
}
if (edge(g.startDs, g.acceptEod, g).second) {
DEBUG_PRINTF("creating end-anchored acceptor\n");
makeEndAnchoredAcceptor(boundary, rm, g);
work_done = true;
}
if (edge(g.start, g.acceptEod, g).second) {
DEBUG_PRINTF("creating nothing acceptor\n");
makeNothingAcceptor(boundary, rm, g);
work_done = true;
}
return work_done;
}
} // namespace ue2