1// Copyright 2009 The RE2 Authors. All Rights Reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5#include "re2/filtered_re2.h"
6
7#include <stddef.h>
8#include <string>
9
10#include "util/util.h"
11#include "util/logging.h"
12#include "re2/prefilter.h"
13#include "re2/prefilter_tree.h"
14
15namespace re2 {
16
17FilteredRE2::FilteredRE2()
18 : compiled_(false),
19 prefilter_tree_(new PrefilterTree()) {
20}
21
22FilteredRE2::FilteredRE2(int min_atom_len)
23 : compiled_(false),
24 prefilter_tree_(new PrefilterTree(min_atom_len)) {
25}
26
27FilteredRE2::~FilteredRE2() {
28 for (size_t i = 0; i < re2_vec_.size(); i++)
29 delete re2_vec_[i];
30 delete prefilter_tree_;
31}
32
33RE2::ErrorCode FilteredRE2::Add(const StringPiece& pattern,
34 const RE2::Options& options, int* id) {
35 RE2* re = new RE2(pattern, options);
36 RE2::ErrorCode code = re->error_code();
37
38 if (!re->ok()) {
39 if (options.log_errors()) {
40 LOG(ERROR) << "Couldn't compile regular expression, skipping: "
41 << re << " due to error " << re->error();
42 }
43 delete re;
44 } else {
45 *id = static_cast<int>(re2_vec_.size());
46 re2_vec_.push_back(re);
47 }
48
49 return code;
50}
51
52void FilteredRE2::Compile(std::vector<std::string>* atoms) {
53 if (compiled_) {
54 LOG(ERROR) << "Compile called already.";
55 return;
56 }
57
58 if (re2_vec_.empty()) {
59 LOG(ERROR) << "Compile called before Add.";
60 return;
61 }
62
63 for (size_t i = 0; i < re2_vec_.size(); i++) {
64 Prefilter* prefilter = Prefilter::FromRE2(re2_vec_[i]);
65 prefilter_tree_->Add(prefilter);
66 }
67 atoms->clear();
68 prefilter_tree_->Compile(atoms);
69 compiled_ = true;
70}
71
72int FilteredRE2::SlowFirstMatch(const StringPiece& text) const {
73 for (size_t i = 0; i < re2_vec_.size(); i++)
74 if (RE2::PartialMatch(text, *re2_vec_[i]))
75 return static_cast<int>(i);
76 return -1;
77}
78
79int FilteredRE2::FirstMatch(const StringPiece& text,
80 const std::vector<int>& atoms) const {
81 if (!compiled_) {
82 LOG(DFATAL) << "FirstMatch called before Compile.";
83 return -1;
84 }
85 std::vector<int> regexps;
86 prefilter_tree_->RegexpsGivenStrings(atoms, &regexps);
87 for (size_t i = 0; i < regexps.size(); i++)
88 if (RE2::PartialMatch(text, *re2_vec_[regexps[i]]))
89 return regexps[i];
90 return -1;
91}
92
93bool FilteredRE2::AllMatches(
94 const StringPiece& text,
95 const std::vector<int>& atoms,
96 std::vector<int>* matching_regexps) const {
97 matching_regexps->clear();
98 std::vector<int> regexps;
99 prefilter_tree_->RegexpsGivenStrings(atoms, &regexps);
100 for (size_t i = 0; i < regexps.size(); i++)
101 if (RE2::PartialMatch(text, *re2_vec_[regexps[i]]))
102 matching_regexps->push_back(regexps[i]);
103 return !matching_regexps->empty();
104}
105
106void FilteredRE2::AllPotentials(
107 const std::vector<int>& atoms,
108 std::vector<int>* potential_regexps) const {
109 prefilter_tree_->RegexpsGivenStrings(atoms, potential_regexps);
110}
111
112void FilteredRE2::RegexpsGivenStrings(const std::vector<int>& matched_atoms,
113 std::vector<int>* passed_regexps) {
114 prefilter_tree_->RegexpsGivenStrings(matched_atoms, passed_regexps);
115}
116
117void FilteredRE2::PrintPrefilter(int regexpid) {
118 prefilter_tree_->PrintPrefilter(regexpid);
119}
120
121} // namespace re2
122