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 | |
17 | FilteredRE2::FilteredRE2() |
18 | : compiled_(false), |
19 | prefilter_tree_(new PrefilterTree()) { |
20 | } |
21 | |
22 | FilteredRE2::FilteredRE2(int min_atom_len) |
23 | : compiled_(false), |
24 | prefilter_tree_(new PrefilterTree(min_atom_len)) { |
25 | } |
26 | |
27 | FilteredRE2::~FilteredRE2() { |
28 | for (size_t i = 0; i < re2_vec_.size(); i++) |
29 | delete re2_vec_[i]; |
30 | } |
31 | |
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 | |
42 | FilteredRE2& FilteredRE2::operator=(FilteredRE2&& other) { |
43 | this->~FilteredRE2(); |
44 | (void) new (this) FilteredRE2(std::move(other)); |
45 | return *this; |
46 | } |
47 | |
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 | |
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 | |
87 | 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 | |
94 | 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 | |
108 | 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 | |
120 | void FilteredRE2::AllPotentials(const std::vector<int>& atoms, |
121 | std::vector<int>* potential_regexps) const { |
122 | prefilter_tree_->RegexpsGivenStrings(atoms, potential_regexps); |
123 | } |
124 | |
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 | |
130 | void FilteredRE2::PrintPrefilter(int regexpid) { |
131 | prefilter_tree_->PrintPrefilter(regexpid); |
132 | } |
133 | |
134 | } // namespace re2 |
135 | |