kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/common/regex.cc (about) 1 /* 2 * Copyright 2020 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "kythe/cxx/common/regex.h" 18 19 #include <memory> 20 #include <utility> 21 #include <vector> 22 23 #include "absl/base/no_destructor.h" 24 #include "absl/log/check.h" 25 #include "absl/log/log.h" 26 #include "absl/status/status.h" 27 #include "absl/status/statusor.h" 28 #include "absl/strings/string_view.h" 29 #include "re2/re2.h" 30 31 namespace kythe { 32 namespace { 33 34 std::shared_ptr<const RE2> DefaultRegex() { 35 static const absl::NoDestructor<std::shared_ptr<const RE2>> kEmpty{ 36 std::make_shared<RE2>("")}; 37 return *kEmpty; 38 } 39 40 std::shared_ptr<const RE2::Set> DefaultSet() { 41 static const absl::NoDestructor<std::shared_ptr<const RE2::Set>> kEmpty{[] { 42 auto set = std::make_shared<RE2::Set>(RE2::Options(), RE2::UNANCHORED); 43 set->Compile(); 44 return set; 45 }()}; 46 return *kEmpty; 47 } 48 49 RE2::Set CheckCompiled(RE2::Set set) { 50 RE2::Set::ErrorInfo error; 51 if (!set.Match("", nullptr, &error)) { 52 if (error.kind == RE2::Set::kNotCompiled) { 53 DLOG(FATAL) << "Uncompiled RE2::Set passed to RegexSet"; 54 CHECK(set.Compile()) << "Failed to compile RE2::Set"; 55 } 56 } 57 return set; 58 } 59 } // namespace 60 61 absl::StatusOr<Regex> Regex::Compile(absl::string_view pattern, 62 const RE2::Options& options) { 63 std::shared_ptr<const RE2> re = std::make_shared<RE2>(pattern, options); 64 if (!re->ok()) { 65 return absl::InvalidArgumentError(re->error()); 66 } 67 return Regex(std::move(re)); 68 } 69 70 Regex::Regex() : re_(DefaultRegex()) {} 71 72 Regex::Regex(const RE2& re) 73 : re_(std::make_shared<RE2>(re.pattern(), re.options())) { 74 CHECK(re_->ok()) << "Cannot initialize Regex from invalid RE2: " 75 << re_->error(); 76 } 77 78 Regex::Regex(Regex&& other) noexcept : re_(std::move(other.re_)) { 79 other.re_ = DefaultRegex(); 80 } 81 82 Regex& Regex::operator=(Regex&& other) noexcept { 83 re_ = std::move(other.re_); 84 other.re_ = DefaultRegex(); 85 return *this; 86 } 87 88 RegexSet::RegexSet() : set_(DefaultSet()) {} 89 RegexSet::RegexSet(RE2::Set set) 90 : set_(std::make_shared<RE2::Set>(CheckCompiled(std::move(set)))) {} 91 92 RegexSet::RegexSet(RegexSet&& other) noexcept : set_(std::move(other.set_)) { 93 other.set_ = DefaultSet(); 94 } 95 96 RegexSet& RegexSet::operator=(RegexSet&& other) noexcept { 97 set_ = std::move(other.set_); 98 other.set_ = DefaultSet(); 99 return *this; 100 } 101 102 absl::StatusOr<std::vector<int>> RegexSet::ExplainMatch( 103 absl::string_view value) const { 104 RE2::Set::ErrorInfo error; 105 std::vector<int> matches; 106 if (set_->Match(value, &matches, &error)) { 107 return matches; 108 } 109 matches.clear(); 110 switch (error.kind) { 111 case RE2::Set::kNoError: 112 return matches; // Empty match == no error, but no matches. 113 case RE2::Set::kNotCompiled: 114 // Shouldn't happen. 115 return absl::InternalError("Match() called on uncompiled Set"); 116 case RE2::Set::kOutOfMemory: 117 return absl::ResourceExhaustedError("Match() ran out of memory"); 118 case RE2::Set::kInconsistent: 119 return absl::InternalError("RE2::Match() had inconsistent result"); 120 } 121 return absl::UnknownError(""); 122 } 123 124 } // namespace kythe