* @brief Replaces all replacements found in the replacement string with what matched in the PCRE capturing groups. * @param subject PCRE subject string * @param result reference to A string where the result of the replacement will be stored * @return true - success, false - nothing matched or failure. */
| 269 | * @return true - success, false - nothing matched or failure. |
| 270 | */ |
| 271 | bool |
| 272 | Pattern::replace(const String &subject, String &result) |
| 273 | { |
| 274 | int matchCount; |
| 275 | int ovector[OVECOUNT]; |
| 276 | |
| 277 | CacheKeyDebug("replacing:'%s' in pattern:'%s', subject:'%s'", _replacement.c_str(), _pattern.c_str(), subject.c_str()); |
| 278 | |
| 279 | if (!_re || !_replace) { |
| 280 | CacheKeyError("regular expression not initialized or not configured to replace"); |
| 281 | return false; |
| 282 | } |
| 283 | |
| 284 | matchCount = pcre_exec(_re, nullptr, subject.c_str(), subject.length(), 0, PCRE_NOTEMPTY, ovector, OVECOUNT); |
| 285 | if (matchCount < 0) { |
| 286 | if (matchCount != PCRE_ERROR_NOMATCH) { |
| 287 | CacheKeyError("matching error %d", matchCount); |
| 288 | } |
| 289 | return false; |
| 290 | } |
| 291 | |
| 292 | /* Verify the replacement has the right number of matching groups */ |
| 293 | for (int i = 0; i < _tokenCount; i++) { |
| 294 | if (_tokens[i] >= matchCount) { |
| 295 | CacheKeyError("invalid reference in replacement string: $%d", _tokens[i]); |
| 296 | return false; |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | int previous = 0; |
| 301 | for (int i = 0; i < _tokenCount; i++) { |
| 302 | int replIndex = _tokens[i]; |
| 303 | int start = ovector[2 * replIndex]; |
| 304 | int length = ovector[2 * replIndex + 1] - ovector[2 * replIndex]; |
| 305 | |
| 306 | /* Handle the case when no match / a group capture result in an empty string */ |
| 307 | if (start < 0) { |
| 308 | start = 0; |
| 309 | length = 0; |
| 310 | } |
| 311 | |
| 312 | String src(_replacement, _tokenOffset[i], 2); |
| 313 | String dst(subject, start, length); |
| 314 | |
| 315 | CacheKeyDebug("replacing '%s' with '%s'", src.c_str(), dst.c_str()); |
| 316 | |
| 317 | result.append(_replacement, previous, _tokenOffset[i] - previous); |
| 318 | result.append(dst); |
| 319 | |
| 320 | previous = _tokenOffset[i] + 2; /* 2 is the size of $0 or $1 or $2, ... or $9 */ |
| 321 | } |
| 322 | |
| 323 | result.append(_replacement, previous, _replacement.length() - previous); |
| 324 | |
| 325 | CacheKeyDebug("replacing '%s' resulted in '%s'", _replacement.c_str(), result.c_str()); |
| 326 | |
| 327 | return true; |
| 328 | } |