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