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