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, &regexps);
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, &regexps);
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