MCPcopy Create free account
hub / github.com/cel-expr/cel-cpp / ExtractAll

Function ExtractAll

extensions/regex_ext.cc:89–145  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

87}
88
89Value ExtractAll(int regex_max_program_size, const StringValue& target,
90 const StringValue& regex,
91 const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
92 google::protobuf::MessageFactory* absl_nonnull message_factory,
93 google::protobuf::Arena* absl_nonnull arena) {
94 std::string target_scratch;
95 std::string regex_scratch;
96 absl::string_view target_view = target.ToStringView(&target_scratch);
97 absl::string_view regex_view = regex.ToStringView(&regex_scratch);
98 RE2 re2(regex_view, cel::internal::MakeRE2Options());
99 CEL_RETURN_IF_ERROR(cel::internal::CheckRE2(re2, regex_max_program_size))
100 .With(ErrorValueReturn());
101 const int group_count = re2.NumberOfCapturingGroups();
102 if (group_count > 1) {
103 return ErrorValue(absl::InvalidArgumentError(absl::StrFormat(
104 "regular expression has more than one capturing group: %s",
105 regex_view)));
106 }
107
108 auto builder = NewListValueBuilder(arena);
109 absl::string_view temp_target = target_view;
110
111 // Space for the full match (\0) and the first capture group (\1).
112 absl::string_view submatches[2];
113 const int group_to_extract = (group_count == 1) ? 1 : 0;
114
115 while (re2.Match(temp_target, 0, temp_target.length(), RE2::UNANCHORED,
116 submatches, group_count + 1)) {
117 const absl::string_view& full_match = submatches[0];
118 const absl::string_view& desired_capture = submatches[group_to_extract];
119
120 // Avoid infinite loops on zero-length matches
121 if (full_match.empty()) {
122 if (temp_target.empty()) {
123 break;
124 }
125 temp_target.remove_prefix(1);
126 continue;
127 }
128
129 if (group_count == 1 && desired_capture.empty()) {
130 temp_target.remove_prefix(full_match.data() - temp_target.data() +
131 full_match.length());
132 continue;
133 }
134
135 absl::Status status =
136 builder->Add(StringValue::From(desired_capture, arena));
137 if (!status.ok()) {
138 return ErrorValue(status);
139 }
140 temp_target.remove_prefix(full_match.data() - temp_target.data() +
141 full_match.length());
142 }
143
144 return std::move(*builder).Build();
145}
146

Callers

nothing calls this directly

Calls 11

MakeRE2OptionsFunction · 0.85
CheckRE2Function · 0.85
ErrorValueReturnClass · 0.85
ErrorValueFunction · 0.85
ToStringViewMethod · 0.80
WithMethod · 0.80
MatchMethod · 0.80
emptyMethod · 0.45
AddMethod · 0.45
okMethod · 0.45
BuildMethod · 0.45

Tested by

no test coverage detected