diff --git a/plugins/prefetch/pattern.cc b/plugins/prefetch/pattern.cc index c6c8ddd47b3..a03460ec868 100644 --- a/plugins/prefetch/pattern.cc +++ b/plugins/prefetch/pattern.cc @@ -23,6 +23,7 @@ */ #include "pattern.h" +#include "tsutil/Regex.h" static void replaceString(String &str, const String &from, const String &to) @@ -49,8 +50,6 @@ Pattern::Pattern() : _pattern(""), _replacement("") {} bool Pattern::init(const String &pattern, const String &replacement) { - pcreFree(); - _pattern.assign(pattern); _replacement.assign(replacement); @@ -58,7 +57,6 @@ Pattern::init(const String &pattern, const String &replacement) if (!compile()) { PrefetchDebug("failed to initialize pattern:'%s', replacement:'%s'", pattern.c_str(), replacement.c_str()); - pcreFree(); return false; } @@ -129,32 +127,7 @@ Pattern::init(const String &config) bool Pattern::empty() const { - return _pattern.empty() || nullptr == _re; -} - -/** - * @brief Frees PCRE library related resources. - */ -void -Pattern::pcreFree() -{ - if (_re) { - pcre_free(_re); - _re = nullptr; - } - - if (_extra) { - pcre_free(_extra); - _extra = nullptr; - } -} - -/** - * @brief Destructor, frees PCRE related resources. - */ -Pattern::~Pattern() -{ - pcreFree(); + return _pattern.empty() || _regex.empty(); } /** @@ -204,16 +177,16 @@ Pattern::process(const String &subject, StringVector &result) bool Pattern::match(const String &subject) { - int matchCount; PrefetchDebug("matching '%s' to '%s'", _pattern.c_str(), subject.c_str()); - if (!_re) { + if (_regex.empty()) { return false; } - matchCount = pcre_exec(_re, _extra, subject.c_str(), subject.length(), 0, PCRE_NOTEMPTY, nullptr, 0); + RegexMatches matches; + int matchCount = _regex.exec(subject, matches, RE_NOTEMPTY); if (matchCount < 0) { - if (matchCount != PCRE_ERROR_NOMATCH) { + if (matchCount != RE_ERROR_NOMATCH) { PrefetchError("matching error %d", matchCount); } return false; @@ -230,31 +203,26 @@ Pattern::match(const String &subject) bool Pattern::capture(const String &subject, StringVector &result) { - int matchCount; - int ovector[OVECOUNT]; - PrefetchDebug("matching '%s' to '%s'", _pattern.c_str(), subject.c_str()); - if (!_re) { + if (_regex.empty()) { return false; } - matchCount = pcre_exec(_re, nullptr, subject.c_str(), subject.length(), 0, PCRE_NOTEMPTY, ovector, OVECOUNT); - if (matchCount < 0) { - if (matchCount != PCRE_ERROR_NOMATCH) { + RegexMatches matches; + int matchCount = _regex.exec(subject, matches, RE_NOTEMPTY); + + if (matchCount <= 0) { + if (matchCount != RE_ERROR_NOMATCH) { PrefetchError("matching error %d", matchCount); } return false; } for (int i = 0; i < matchCount; i++) { - int start = ovector[2 * i]; - int length = ovector[2 * i + 1] - ovector[2 * i]; - - String dst(subject, start, length); - - PrefetchDebug("capturing '%s' %d[%d,%d]", dst.c_str(), i, ovector[2 * i], ovector[2 * i + 1]); - result.push_back(dst); + std::string_view match = matches[i]; + result.emplace_back(match.data(), match.length()); + PrefetchDebug("capturing '%s' %d", result.back().c_str(), i); } return true; @@ -269,18 +237,17 @@ Pattern::capture(const String &subject, StringVector &result) bool Pattern::replace(const String &subject, String &result) { - int matchCount; - int ovector[OVECOUNT]; - PrefetchDebug("matching '%s' to '%s'", _pattern.c_str(), subject.c_str()); - if (!_re) { + if (_regex.empty()) { return false; } - matchCount = pcre_exec(_re, nullptr, subject.c_str(), subject.length(), 0, PCRE_NOTEMPTY, ovector, OVECOUNT); - if (matchCount < 0) { - if (matchCount != PCRE_ERROR_NOMATCH) { + RegexMatches matches; + int matchCount = _regex.exec(subject, matches, RE_NOTEMPTY); + + if (matchCount <= 0) { + if (matchCount != RE_ERROR_NOMATCH) { PrefetchError("matching error %d", matchCount); } return false; @@ -296,17 +263,15 @@ Pattern::replace(const String &subject, String &result) int previous = 0; for (int i = 0; i < _tokenCount; i++) { - int replIndex = _tokens[i]; - int start = ovector[2 * replIndex]; - int length = ovector[2 * replIndex + 1] - ovector[2 * replIndex]; + int replIndex = _tokens[i]; + std::string_view dst = matches[replIndex]; String src(_replacement, _tokenOffset[i], 2); - String dst(subject, start, length); - PrefetchDebug("replacing '%s' with '%s'", src.c_str(), dst.c_str()); + PrefetchDebug("replacing '%s' with '%.*s'", src.c_str(), static_cast(dst.length()), dst.data()); result.append(_replacement, previous, _tokenOffset[i] - previous); - result.append(dst); + result.append(dst.data(), dst.length()); previous = _tokenOffset[i] + 2; /* 2 is the size of $0 or $1 or $2, ... or $9 */ } @@ -325,30 +290,12 @@ Pattern::replace(const String &subject, String &result) bool Pattern::compile() { - const char *errPtr; /* PCRE error */ - int errOffset; /* PCRE error offset */ - PrefetchDebug("compiling pattern:'%s', replacement:'%s'", _pattern.c_str(), _replacement.c_str()); - _re = pcre_compile(_pattern.c_str(), /* the pattern */ - 0, /* options */ - &errPtr, /* for error message */ - &errOffset, /* for error offset */ - nullptr); /* use default character tables */ - - if (nullptr == _re) { - PrefetchError("compile of regex '%s' at char %d: %s", _pattern.c_str(), errOffset, errPtr); - - return false; - } - - _extra = pcre_study(_re, 0, &errPtr); - - if ((nullptr == _extra) && (nullptr != errPtr) && (0 != *errPtr)) { - PrefetchError("failed to study regex '%s': %s", _pattern.c_str(), errPtr); - - pcre_free(_re); - _re = nullptr; + std::string error; + int erroffset; + if (!_regex.compile(_pattern, error, erroffset)) { + PrefetchError("compile of regex '%s' at char %d: %s", _pattern.c_str(), erroffset, error.c_str()); return false; } @@ -384,10 +331,6 @@ Pattern::compile() } } - if (!success) { - pcreFree(); - } - return success; } diff --git a/plugins/prefetch/pattern.h b/plugins/prefetch/pattern.h index 5ee58873912..1432cfbbfec 100644 --- a/plugins/prefetch/pattern.h +++ b/plugins/prefetch/pattern.h @@ -23,13 +23,8 @@ #pragma once -#ifdef HAVE_PCRE_PCRE_H -#include -#else -#include -#endif - #include "common.h" +#include "tsutil/Regex.h" /** * @brief PCRE matching, capturing and replacing @@ -37,11 +32,9 @@ class Pattern { public: - static const int TOKENCOUNT = 10; /**< @brief Capturing groups $0..$9 */ - static const int OVECOUNT = TOKENCOUNT * 3; /**< @brief pcre_exec() array count, handle 10 capture groups */ + static const int TOKENCOUNT = 10; /**< @brief Capturing groups $0..$9 */ Pattern(); - virtual ~Pattern(); bool init(const String &pattern, const String &replacement); bool init(const String &config); @@ -54,10 +47,8 @@ class Pattern private: bool compile(); bool failed(const String &subject) const; - void pcreFree(); - pcre *_re = nullptr; /**< @brief PCRE compiled info structure, computed during initialization */ - pcre_extra *_extra = nullptr; /**< @brief PCRE study data block, computed during initialization */ + Regex _regex; String _pattern; /**< @brief PCRE pattern string, containing PCRE patterns and capturing groups. */ String _replacement; /**< @brief PCRE replacement string, containing $0..$9 to be replaced with content of the capturing groups */