blob: 682359ccb4e1d2a0bfceec366be851b300f2f5bd [file] [edit]
/*
* Copyright (C) 2026 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SRC_BASE_REGEX_REGEX_RE2_H_
#define SRC_BASE_REGEX_REGEX_RE2_H_
#include "perfetto/base/build_config.h"
// Guarded because gen_amalgamated inlines the body even when the include
// site in regex.cc is preprocessed out. Also honor PERFETTO_REGEX_FORCE_STD:
// targets that define it opt out of the optional backends and must not pull in
// <re2/re2.h>, even when PERFETTO_RE2 is set.
#if PERFETTO_BUILDFLAG(PERFETTO_RE2) && !defined(PERFETTO_REGEX_FORCE_STD)
#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include "perfetto/ext/base/status_or.h"
// Using quotes instead of angle brackets because Bazel passes external repo
// paths via -iquote (not -isystem), which only covers quoted includes.
// See google/re2 commit baeed1c and bazelbuild/bazel#18974.
#include "re2/re2.h" // gen_amalgamated:keep
namespace perfetto {
namespace base {
// RE2 backend for Regex. Used on non-Android builds (standalone, Chromium).
// Header-only so the compiler can inline through unique_ptr<RegexImpl>.
class RegexRe2 {
public:
RegexRe2(RegexRe2&&) noexcept = default;
RegexRe2& operator=(RegexRe2&&) noexcept = default;
~RegexRe2() = default;
RegexRe2(const RegexRe2&) = delete;
RegexRe2& operator=(const RegexRe2&) = delete;
static StatusOr<RegexRe2> Create(std::string_view pattern,
bool case_insensitive) {
RegexRe2 result;
re2::RE2::Options options;
options.set_log_errors(false);
options.set_case_sensitive(!case_insensitive);
result.re_ = std::make_unique<re2::RE2>(std::string(pattern), options);
if (!result.re_->ok()) {
return ErrStatus("RE2 compile error: %s", result.re_->error().c_str());
}
result.groups_.resize(
static_cast<size_t>(result.re_->NumberOfCapturingGroups() + 1));
return std::move(result);
}
std::string GlobalReplace(std::string_view s,
std::string_view replacement) const {
std::string out(s);
re2::RE2::GlobalReplace(&out, *re_, replacement);
return out;
}
bool FullMatch(std::string_view s) const {
return re2::RE2::FullMatch(s, *re_);
}
bool FullMatchWithGroups(std::string_view s,
std::vector<std::string_view>& out) const {
out.clear();
int n = static_cast<int>(groups_.size());
if (!re_->Match(s, 0, s.size(), re2::RE2::ANCHOR_BOTH, groups_.data(), n))
return false;
out.assign(groups_.begin(), groups_.begin() + n);
return true;
}
bool PartialMatch(std::string_view s) const {
return re2::RE2::PartialMatch(s, *re_);
}
bool PartialMatchWithGroups(std::string_view s,
std::vector<std::string_view>& out) const {
out.clear();
int n = static_cast<int>(groups_.size());
if (!re_->Match(s, 0, s.size(), re2::RE2::UNANCHORED, groups_.data(), n))
return false;
out.assign(groups_.begin(), groups_.begin() + n);
return true;
}
bool SearchWithOffset(std::string_view s,
size_t start_offset,
std::vector<std::string_view>& out) const {
out.clear();
if (start_offset > s.size())
return false;
int n = static_cast<int>(groups_.size());
if (!re_->Match(s, start_offset, s.size(), re2::RE2::UNANCHORED,
groups_.data(), n))
return false;
out.assign(groups_.begin(), groups_.begin() + n);
return true;
}
private:
RegexRe2() = default;
std::unique_ptr<re2::RE2> re_;
// Must be absl::string_view, not std::string_view, to match RE2::Match()
// signature. These can be distinct types in different builds.
mutable std::vector<absl::string_view> groups_;
};
} // namespace base
} // namespace perfetto
#endif // PERFETTO_BUILDFLAG(PERFETTO_RE2) &&
// !defined(PERFETTO_REGEX_FORCE_STD)
#endif // SRC_BASE_REGEX_REGEX_RE2_H_