// Copyright 2009 The RE2 Authors. All Rights Reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "re2/filtered_re2.h" #include #include #include #include "util/util.h" #include "util/logging.h" #include "re2/prefilter.h" #include "re2/prefilter_tree.h" namespace re2 { FilteredRE2::FilteredRE2() : compiled_(false), prefilter_tree_(new PrefilterTree()) { } FilteredRE2::FilteredRE2(int min_atom_len) : compiled_(false), prefilter_tree_(new PrefilterTree(min_atom_len)) { } FilteredRE2::~FilteredRE2() { for (size_t i = 0; i < re2_vec_.size(); i++) delete re2_vec_[i]; } FilteredRE2::FilteredRE2(FilteredRE2&& other) : re2_vec_(std::move(other.re2_vec_)), compiled_(other.compiled_), prefilter_tree_(std::move(other.prefilter_tree_)) { other.re2_vec_.clear(); other.re2_vec_.shrink_to_fit(); other.compiled_ = false; other.prefilter_tree_.reset(new PrefilterTree()); } FilteredRE2& FilteredRE2::operator=(FilteredRE2&& other) { this->~FilteredRE2(); (void) new (this) FilteredRE2(std::move(other)); return *this; } RE2::ErrorCode FilteredRE2::Add(const StringPiece& pattern, const RE2::Options& options, int* id) { RE2* re = new RE2(pattern, options); RE2::ErrorCode code = re->error_code(); if (!re->ok()) { if (options.log_errors()) { LOG(ERROR) << "Couldn't compile regular expression, skipping: " << pattern << " due to error " << re->error(); } delete re; } else { *id = static_cast(re2_vec_.size()); re2_vec_.push_back(re); } return code; } void FilteredRE2::Compile(std::vector* atoms) { if (compiled_) { LOG(ERROR) << "Compile called already."; return; } if (re2_vec_.empty()) { LOG(ERROR) << "Compile called before Add."; return; } for (size_t i = 0; i < re2_vec_.size(); i++) { Prefilter* prefilter = Prefilter::FromRE2(re2_vec_[i]); prefilter_tree_->Add(prefilter); } atoms->clear(); prefilter_tree_->Compile(atoms); compiled_ = true; } int FilteredRE2::SlowFirstMatch(const StringPiece& text) const { for (size_t i = 0; i < re2_vec_.size(); i++) if (RE2::PartialMatch(text, *re2_vec_[i])) return static_cast(i); return -1; } int FilteredRE2::FirstMatch(const StringPiece& text, const std::vector& atoms) const { if (!compiled_) { LOG(DFATAL) << "FirstMatch called before Compile."; return -1; } std::vector regexps; prefilter_tree_->RegexpsGivenStrings(atoms, ®exps); for (size_t i = 0; i < regexps.size(); i++) if (RE2::PartialMatch(text, *re2_vec_[regexps[i]])) return regexps[i]; return -1; } bool FilteredRE2::AllMatches( const StringPiece& text, const std::vector& atoms, std::vector* matching_regexps) const { matching_regexps->clear(); std::vector regexps; prefilter_tree_->RegexpsGivenStrings(atoms, ®exps); for (size_t i = 0; i < regexps.size(); i++) if (RE2::PartialMatch(text, *re2_vec_[regexps[i]])) matching_regexps->push_back(regexps[i]); return !matching_regexps->empty(); } void FilteredRE2::AllPotentials( const std::vector& atoms, std::vector* potential_regexps) const { prefilter_tree_->RegexpsGivenStrings(atoms, potential_regexps); } void FilteredRE2::RegexpsGivenStrings(const std::vector& matched_atoms, std::vector* passed_regexps) { prefilter_tree_->RegexpsGivenStrings(matched_atoms, passed_regexps); } void FilteredRE2::PrintPrefilter(int regexpid) { prefilter_tree_->PrintPrefilter(regexpid); } } // namespace re2