Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 25 additions & 93 deletions plugins/prefetch/pattern.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,13 @@ Pattern::Pattern() : _pattern(""), _replacement("") {}
bool
Pattern::init(const String &pattern, const String &replacement)
{
pcreFree();

_pattern.assign(pattern);
_replacement.assign(replacement);

_tokenCount = 0;

if (!compile()) {
PrefetchDebug("failed to initialize pattern:'%s', replacement:'%s'", pattern.c_str(), replacement.c_str());
pcreFree();
return false;
}

Expand Down Expand Up @@ -129,33 +126,13 @@ 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;
}
return _pattern.empty() || _regex.empty();
}

/**
* @brief Destructor, frees PCRE related resources.
*/
Pattern::~Pattern()
{
pcreFree();
}
Pattern::~Pattern() {}

/**
* @brief Capture or capture-and-replace depending on whether a replacement string is specified.
Expand Down Expand Up @@ -204,22 +181,13 @@ 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);
if (matchCount < 0) {
if (matchCount != PCRE_ERROR_NOMATCH) {
PrefetchError("matching error %d", matchCount);
}
return false;
}

return true;
return _regex.exec(subject);
}

/**
Expand All @@ -230,31 +198,23 @@ 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) {
PrefetchError("matching error %d", matchCount);
}
RegexMatches matches;
int matchCount = _regex.exec(subject, matches);

if (matchCount <= 0) {
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;
Expand All @@ -269,20 +229,16 @@ 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) {
PrefetchError("matching error %d", matchCount);
}
RegexMatches matches;
int matchCount = _regex.exec(subject, matches);

if (matchCount <= 0) {
return false;
}

Expand All @@ -296,17 +252,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<int>(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 */
}
Expand All @@ -325,30 +279,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;
}

Expand Down Expand Up @@ -384,10 +320,6 @@ Pattern::compile()
}
}

if (!success) {
pcreFree();
}

return success;
}

Expand Down
14 changes: 3 additions & 11 deletions plugins/prefetch/pattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,16 @@

#pragma once

#ifdef HAVE_PCRE_PCRE_H
#include <pcre/pcre.h>
#else
#include <pcre.h>
#endif

#include "common.h"
#include "tsutil/Regex.h"

/**
* @brief PCRE matching, capturing and replacing
*/
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();
Expand All @@ -54,10 +48,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 */
Expand Down