| 1092 | } |
| 1093 | |
| 1094 | StringVal StringFunctions::RegexpExtract(FunctionContext* context, const StringVal& str, |
| 1095 | const StringVal& pattern, const BigIntVal& index) { |
| 1096 | if (str.is_null || pattern.is_null || index.is_null) return StringVal::null(); |
| 1097 | if (index.val < 0) return StringVal(); |
| 1098 | |
| 1099 | re2::RE2* re = reinterpret_cast<re2::RE2*>( |
| 1100 | context->GetFunctionState(FunctionContext::THREAD_LOCAL)); |
| 1101 | scoped_ptr<re2::RE2> scoped_re; // destroys re if we have to locally compile it |
| 1102 | if (re == NULL) { |
| 1103 | DCHECK(!context->IsArgConstant(1)); |
| 1104 | string error_str; |
| 1105 | re = CompileRegex(pattern, &error_str, StringVal::null()); |
| 1106 | if (re == NULL) { |
| 1107 | context->AddWarning(error_str.c_str()); |
| 1108 | return StringVal::null(); |
| 1109 | } |
| 1110 | scoped_re.reset(re); |
| 1111 | } |
| 1112 | |
| 1113 | re2::StringPiece str_sp(reinterpret_cast<char*>(str.ptr), str.len); |
| 1114 | int max_matches = 1 + re->NumberOfCapturingGroups(); |
| 1115 | if (index.val >= max_matches) return StringVal(); |
| 1116 | // Use a vector because clang complains about non-POD varlen arrays |
| 1117 | // TODO: fix this |
| 1118 | vector<re2::StringPiece> matches(max_matches); |
| 1119 | bool success = |
| 1120 | re->Match(str_sp, 0, str.len, re2::RE2::UNANCHORED, matches.data(), max_matches); |
| 1121 | if (!success) return StringVal(); |
| 1122 | // matches[0] is the whole string, matches[1] the first group, etc. |
| 1123 | const re2::StringPiece& match = matches[index.val]; |
| 1124 | return AnyValUtil::FromBuffer(context, match.data(), match.size()); |
| 1125 | } |
| 1126 | |
| 1127 | StringVal StringFunctions::RegexpReplace(FunctionContext* context, const StringVal& str, |
| 1128 | const StringVal& pattern, const StringVal& replace) { |
nothing calls this directly
no test coverage detected