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 
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   delete prefilter_tree_;
31 }
32 
Add(const StringPiece & pattern,const RE2::Options & options,int * id)33 RE2::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 
Compile(std::vector<std::string> * atoms)52 void 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 
SlowFirstMatch(const StringPiece & text) const72 int 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 
FirstMatch(const StringPiece & text,const std::vector<int> & atoms) const79 int 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 
AllMatches(const StringPiece & text,const std::vector<int> & atoms,std::vector<int> * matching_regexps) const93 bool 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 
AllPotentials(const std::vector<int> & atoms,std::vector<int> * potential_regexps) const106 void FilteredRE2::AllPotentials(
107     const std::vector<int>& atoms,
108     std::vector<int>* potential_regexps) const {
109   prefilter_tree_->RegexpsGivenStrings(atoms, potential_regexps);
110 }
111 
RegexpsGivenStrings(const std::vector<int> & matched_atoms,std::vector<int> * passed_regexps)112 void FilteredRE2::RegexpsGivenStrings(const std::vector<int>& matched_atoms,
113                                       std::vector<int>* passed_regexps) {
114   prefilter_tree_->RegexpsGivenStrings(matched_atoms, passed_regexps);
115 }
116 
PrintPrefilter(int regexpid)117 void FilteredRE2::PrintPrefilter(int regexpid) {
118   prefilter_tree_->PrintPrefilter(regexpid);
119 }
120 
121 }  // namespace re2
122