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