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 #include <utility>
10
11 #include "util/util.h"
12 #include "util/logging.h"
13 #include "re2/prefilter.h"
14 #include "re2/prefilter_tree.h"
15
16 namespace re2 {
17
FilteredRE2()18 FilteredRE2::FilteredRE2()
19 : compiled_(false),
20 prefilter_tree_(new PrefilterTree()) {
21 }
22
FilteredRE2(int min_atom_len)23 FilteredRE2::FilteredRE2(int min_atom_len)
24 : compiled_(false),
25 prefilter_tree_(new PrefilterTree(min_atom_len)) {
26 }
27
~FilteredRE2()28 FilteredRE2::~FilteredRE2() {
29 for (size_t i = 0; i < re2_vec_.size(); i++)
30 delete re2_vec_[i];
31 }
32
FilteredRE2(FilteredRE2 && other)33 FilteredRE2::FilteredRE2(FilteredRE2&& other)
34 : re2_vec_(std::move(other.re2_vec_)),
35 compiled_(other.compiled_),
36 prefilter_tree_(std::move(other.prefilter_tree_)) {
37 other.re2_vec_.clear();
38 other.re2_vec_.shrink_to_fit();
39 other.compiled_ = false;
40 other.prefilter_tree_.reset(new PrefilterTree());
41 }
42
operator =(FilteredRE2 && other)43 FilteredRE2& FilteredRE2::operator=(FilteredRE2&& other) {
44 this->~FilteredRE2();
45 (void) new (this) FilteredRE2(std::move(other));
46 return *this;
47 }
48
Add(const StringPiece & pattern,const RE2::Options & options,int * id)49 RE2::ErrorCode FilteredRE2::Add(const StringPiece& pattern,
50 const RE2::Options& options, int* id) {
51 RE2* re = new RE2(pattern, options);
52 RE2::ErrorCode code = re->error_code();
53
54 if (!re->ok()) {
55 if (options.log_errors()) {
56 LOG(ERROR) << "Couldn't compile regular expression, skipping: "
57 << pattern << " due to error " << re->error();
58 }
59 delete re;
60 } else {
61 *id = static_cast<int>(re2_vec_.size());
62 re2_vec_.push_back(re);
63 }
64
65 return code;
66 }
67
Compile(std::vector<std::string> * atoms)68 void FilteredRE2::Compile(std::vector<std::string>* atoms) {
69 if (compiled_) {
70 LOG(ERROR) << "Compile called already.";
71 return;
72 }
73
74 if (re2_vec_.empty()) {
75 LOG(ERROR) << "Compile called before Add.";
76 return;
77 }
78
79 for (size_t i = 0; i < re2_vec_.size(); i++) {
80 Prefilter* prefilter = Prefilter::FromRE2(re2_vec_[i]);
81 prefilter_tree_->Add(prefilter);
82 }
83 atoms->clear();
84 prefilter_tree_->Compile(atoms);
85 compiled_ = true;
86 }
87
SlowFirstMatch(const StringPiece & text) const88 int FilteredRE2::SlowFirstMatch(const StringPiece& text) const {
89 for (size_t i = 0; i < re2_vec_.size(); i++)
90 if (RE2::PartialMatch(text, *re2_vec_[i]))
91 return static_cast<int>(i);
92 return -1;
93 }
94
FirstMatch(const StringPiece & text,const std::vector<int> & atoms) const95 int FilteredRE2::FirstMatch(const StringPiece& text,
96 const std::vector<int>& atoms) const {
97 if (!compiled_) {
98 LOG(DFATAL) << "FirstMatch called before Compile.";
99 return -1;
100 }
101 std::vector<int> regexps;
102 prefilter_tree_->RegexpsGivenStrings(atoms, ®exps);
103 for (size_t i = 0; i < regexps.size(); i++)
104 if (RE2::PartialMatch(text, *re2_vec_[regexps[i]]))
105 return regexps[i];
106 return -1;
107 }
108
AllMatches(const StringPiece & text,const std::vector<int> & atoms,std::vector<int> * matching_regexps) const109 bool FilteredRE2::AllMatches(
110 const StringPiece& text,
111 const std::vector<int>& atoms,
112 std::vector<int>* matching_regexps) const {
113 matching_regexps->clear();
114 std::vector<int> regexps;
115 prefilter_tree_->RegexpsGivenStrings(atoms, ®exps);
116 for (size_t i = 0; i < regexps.size(); i++)
117 if (RE2::PartialMatch(text, *re2_vec_[regexps[i]]))
118 matching_regexps->push_back(regexps[i]);
119 return !matching_regexps->empty();
120 }
121
AllPotentials(const std::vector<int> & atoms,std::vector<int> * potential_regexps) const122 void FilteredRE2::AllPotentials(
123 const std::vector<int>& atoms,
124 std::vector<int>* potential_regexps) const {
125 prefilter_tree_->RegexpsGivenStrings(atoms, potential_regexps);
126 }
127
RegexpsGivenStrings(const std::vector<int> & matched_atoms,std::vector<int> * passed_regexps)128 void FilteredRE2::RegexpsGivenStrings(const std::vector<int>& matched_atoms,
129 std::vector<int>* passed_regexps) {
130 prefilter_tree_->RegexpsGivenStrings(matched_atoms, passed_regexps);
131 }
132
PrintPrefilter(int regexpid)133 void FilteredRE2::PrintPrefilter(int regexpid) {
134 prefilter_tree_->PrintPrefilter(regexpid);
135 }
136
137 } // namespace re2
138