| 55 | using ::cel::checker_internal::BuiltinsArena; |
| 56 | |
| 57 | Value Extract(int regex_max_program_size, const StringValue& target, |
| 58 | const StringValue& regex, |
| 59 | const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool, |
| 60 | google::protobuf::MessageFactory* absl_nonnull message_factory, |
| 61 | google::protobuf::Arena* absl_nonnull arena) { |
| 62 | std::string target_scratch; |
| 63 | std::string regex_scratch; |
| 64 | absl::string_view target_view = target.ToStringView(&target_scratch); |
| 65 | absl::string_view regex_view = regex.ToStringView(®ex_scratch); |
| 66 | RE2 re2(regex_view, cel::internal::MakeRE2Options()); |
| 67 | CEL_RETURN_IF_ERROR(cel::internal::CheckRE2(re2, regex_max_program_size)) |
| 68 | .With(ErrorValueReturn()); |
| 69 | const int group_count = re2.NumberOfCapturingGroups(); |
| 70 | if (group_count > 1) { |
| 71 | return ErrorValue(absl::InvalidArgumentError(absl::StrFormat( |
| 72 | "regular expression has more than one capturing group: %s", |
| 73 | regex_view))); |
| 74 | } |
| 75 | |
| 76 | // Space for the full match (\0) and the first capture group (\1). |
| 77 | absl::string_view submatches[2]; |
| 78 | if (re2.Match(target_view, 0, target_view.length(), RE2::UNANCHORED, |
| 79 | submatches, 2)) { |
| 80 | // Return the capture group if it exists else return the full match. |
| 81 | const absl::string_view result_view = |
| 82 | (group_count == 1) ? submatches[1] : submatches[0]; |
| 83 | return OptionalValue::Of(StringValue::From(result_view, arena), arena); |
| 84 | } |
| 85 | |
| 86 | return OptionalValue::None(); |
| 87 | } |
| 88 | |
| 89 | Value ExtractAll(int regex_max_program_size, const StringValue& target, |
| 90 | const StringValue& regex, |
no test coverage detected