simpleperf: build regex support as a separate library.
Some regex patterns come from command line options, which may
contain error. Simpleperf aborts when it happens. Because Android
code is compiled with -fno-exceptions.
To report this error instead of aborting, this CL builds regex
support as a separate library with -fexceptions.
Bug: 187539381
Test: run simpleperf_unit_test
Change-Id: Ic4c735b14d86dbdac9df304939c5ff5002d3a7e1
diff --git a/simpleperf/RegEx.cpp b/simpleperf/RegEx.cpp
new file mode 100644
index 0000000..97bb45b
--- /dev/null
+++ b/simpleperf/RegEx.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include "RegEx.h"
+
+#include <regex>
+
+#include <android-base/logging.h>
+
+namespace simpleperf {
+
+RegExMatch::~RegExMatch() {}
+
+class RegExMatchImpl : public RegExMatch {
+ public:
+ RegExMatchImpl(std::string_view s, const std::regex& re)
+ : match_it_(s.data(), s.data() + s.size(), re) {}
+
+ bool IsValid() const override { return match_it_ != std::cregex_iterator(); }
+
+ std::string GetField(size_t index) const override { return match_it_->str(index); }
+
+ void MoveToNextMatch() override { ++match_it_; }
+
+ private:
+ std::cregex_iterator match_it_;
+};
+
+class RegExImpl : public RegEx {
+ public:
+ RegExImpl(std::string_view pattern)
+ : RegEx(pattern), re_(pattern_, std::regex::ECMAScript | std::regex::optimize) {}
+
+ bool Match(std::string_view s) const override {
+ return std::regex_match(s.begin(), s.end(), re_);
+ }
+ bool Search(std::string_view s) const override {
+ return std::regex_search(s.begin(), s.end(), re_);
+ }
+ std::unique_ptr<RegExMatch> SearchAll(std::string_view s) const override {
+ return std::unique_ptr<RegExMatch>(new RegExMatchImpl(s, re_));
+ }
+ std::optional<std::string> Replace(const std::string& s,
+ const std::string& format) const override {
+ try {
+ return {std::regex_replace(s, re_, format)};
+ } catch (std::regex_error& e) {
+ LOG(ERROR) << "regex_error: " << e.what() << ", pattern " << pattern_ << ", format "
+ << format;
+ return std::nullopt;
+ }
+ }
+
+ private:
+ std::regex re_;
+};
+
+std::unique_ptr<RegEx> RegEx::Create(std::string_view pattern) {
+ try {
+ return std::make_unique<RegExImpl>(pattern);
+ } catch (std::regex_error& e) {
+ LOG(ERROR) << "regex_error: " << e.what() << ", pattern " << pattern;
+ return nullptr;
+ }
+}
+
+} // namespace simpleperf