/***************************************************************************
- * Copyright (C) 2005-2018 by the Quassel Project *
+ * Copyright (C) 2005-2020 by the Quassel Project *
* devel@quassel-irc.org *
* *
* This program is free software; you can redistribute it and/or modify *
#include <QString>
#include <QStringList>
-#if QT_VERSION >= 0x050000
-#include <QRegularExpression>
-#else
-#include <QRegExp>
-#endif
-
-#include "logmessage.h"
-
-ExpressionMatch::ExpressionMatch(const QString &expression, MatchMode mode, bool caseSensitive)
+ExpressionMatch::ExpressionMatch(const QString& expression, MatchMode mode, bool caseSensitive)
{
// Store the original parameters for later reference
_sourceExpression = expression;
cacheRegEx();
}
-
-bool ExpressionMatch::match(const QString &string, bool matchEmpty) const
+bool ExpressionMatch::match(const QString& string, bool matchEmpty) const
{
// Handle empty expression strings
if (_sourceExpressionEmpty) {
// If specified, first check inverted rules
if (_matchInvertRegExActive && _matchInvertRegEx.isValid()) {
// Check inverted match rule
-
- // See _matchRegEx section below for explanations of QRegExp vs. QRegularExpression
- if (
-#if QT_VERSION >= 0x050000
- _matchInvertRegEx.match(string).hasMatch()
-#else
- _matchInvertRegEx.indexIn(string) != -1
-#endif
- ) {
+ if (_matchInvertRegEx.match(string).hasMatch()) {
// Inverted rule matched, the rest of the rule cannot match
return false;
}
if (_matchRegExActive && _matchRegEx.isValid()) {
// Check regular match rule
- #if QT_VERSION >= 0x050000
- // QRegularExpression does partial matching by default (exact matching requires anchoring
- // expressions to be added)
- // See https://doc.qt.io/qt-5/qregularexpression.html#porting-from-qregexp-exactmatch
return _matchRegEx.match(string).hasMatch();
- #else
- // QRegExp partial matching is done via indexIn
- // See https://doc.qt.io/qt-5/qregexp.html#indexIn
- return (_matchRegEx.indexIn(string) != -1);
- #endif
- } else {
+ }
+ else {
// If no valid regular rules exist, due to the isValid() check there must be valid inverted
// rules that did not match. Count this as properly matching (implicit wildcard).
return true;
}
}
-
-QString ExpressionMatch::trimMultiWildcardWhitespace(const QString &originalRule)
+QString ExpressionMatch::trimMultiWildcardWhitespace(const QString& originalRule)
{
// This gets handled in two steps:
//
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << rule << "resulted in rule component"
- << curString << "with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring" << curChar << "character!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << rule << "resulted in rule component" << curString
+ << "with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring" << curChar
+ << "character!";
break;
}
consecutiveSlashes = 0;
}
else if (consecutiveSlashes > 3) {
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << rule << "resulted in rule component"
- << curString << "with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring" << curChar << "character!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << rule << "resulted in rule component" << curString
+ << "with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring" << curChar
+ << "character!";
break;
}
break;
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << rule << "resulted in rule component"
- << curString << "with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), applying newline split anyways!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << rule << "resulted in rule component" << curString
+ << "with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), applying newline split anyways!";
break;
}
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << rule << "resulted in rule component"
- << curString << "with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring " << curChar << "char escape!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << rule << "resulted in rule component" << curString
+ << "with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring " << curChar
+ << "char escape!";
break;
}
consecutiveSlashes = 0;
return result.trimmed();
}
-
void ExpressionMatch::cacheRegEx()
{
_matchRegExActive = false;
// Match entire phrase, noninverted
// Don't trim whitespace for phrase matching as someone might want to match on " word ", a
// more-specific request than "word".
- _matchRegEx = regExFactory("(?:^|\\W)" + regExEscape(_sourceExpression) + "(?:\\W|$)",
- _sourceCaseSensitive);
+ _matchRegEx = regExFactory("(?:^|\\W)" + regExEscape(_sourceExpression) + "(?:\\W|$)", _sourceCaseSensitive);
_matchRegExActive = true;
break;
case MatchMode::MatchMultiPhrase:
if (_sourceExpression.startsWith("!")) {
// Inverted rule: take the remainder of the string
// "^" + invertComponents.at(0) + "$"
- _matchInvertRegEx = regExFactory("^" + wildcardToRegEx(_sourceExpression.mid(1)) + "$",
- _sourceCaseSensitive);
+ _matchInvertRegEx = regExFactory("^" + wildcardToRegEx(_sourceExpression.mid(1)) + "$", _sourceCaseSensitive);
_matchInvertRegExActive = true;
}
else {
// Normal rule: take the whole string
// Account for any escaped "!" (i.e. "\!") by skipping past the "\", but don't skip past
// escaped "\" (i.e. "\\!")
- _matchRegEx =
- regExFactory("^" + wildcardToRegEx(_sourceExpression.startsWith("\\!")
- ? _sourceExpression.mid(1)
- : _sourceExpression) + "$",
- _sourceCaseSensitive);
+ _matchRegEx = regExFactory("^" + wildcardToRegEx(_sourceExpression.startsWith("\\!") ? _sourceExpression.mid(1) : _sourceExpression)
+ + "$",
+ _sourceCaseSensitive);
_matchRegExActive = true;
}
break;
// Normal rule: take the whole string
// Account for any escaped "!" (i.e. "\!") by skipping past the "\", but don't skip past
// escaped "\" (i.e. "\\!")
- _matchRegEx =
- regExFactory(_sourceExpression.startsWith("\\!") ? _sourceExpression.mid(1)
- : _sourceExpression,
- _sourceCaseSensitive);
+ _matchRegEx = regExFactory(_sourceExpression.startsWith("\\!") ? _sourceExpression.mid(1) : _sourceExpression,
+ _sourceCaseSensitive);
_matchRegExActive = true;
}
break;
// level as ideally someone's not just going to leave a broken match rule around. For
// MatchRegEx, they probably need to fix their regex rule. For the other modes, there's
// probably a bug in the parsing routines (which should also be fixed).
- quInfo() << "Could not parse expression match rule"
- << _sourceExpression << "(match mode:" << (int)_sourceMode
+ qInfo() << "Could not parse expression match rule" << _sourceExpression << "(match mode:" << (int)_sourceMode
<< "), this rule will be ignored";
}
}
-
-#if QT_VERSION >= 0x050000
-QRegularExpression ExpressionMatch::regExFactory(const QString ®ExString,
- bool caseSensitive)
-#else
-QRegExp ExpressionMatch::regExFactory(const QString ®ExString, bool caseSensitive)
-#endif
+QRegularExpression ExpressionMatch::regExFactory(const QString& regExString, bool caseSensitive)
{
// Construct the regular expression object, setting case sensitivity as appropriate
-#if QT_VERSION >= 0x050000
- QRegularExpression newRegEx =
- QRegularExpression(regExString, caseSensitive ?
- QRegularExpression::PatternOption::NoPatternOption
- : QRegularExpression::PatternOption::CaseInsensitiveOption );
-#else
- QRegExp newRegEx = QRegExp(regExString, caseSensitive ?
- Qt::CaseSensitivity::CaseSensitive
- : Qt::CaseSensitivity::CaseInsensitive);
-#endif
+ QRegularExpression newRegEx = QRegularExpression(regExString,
+ caseSensitive ? QRegularExpression::PatternOption::NoPatternOption
+ : QRegularExpression::PatternOption::CaseInsensitiveOption);
// Check if rule is valid
if (!newRegEx.isValid()) {
// This can happen with invalid regex, so make it a bit more user-friendly. Keep this
// distinct from the main info-level message for easier debugging in case a regex component
// in Wildcard or Phrase mode breaks.
- qDebug() << "Internal regular expression component" << regExString
- << "is invalid and will be ignored";
+ qDebug() << "Internal regular expression component" << regExString << "is invalid and will be ignored";
}
- // Qt 5.4 (QT_VERSION >= 0x050400) offers explicit control over when QRegularExpression objects
- // get optimized. By default, patterns are only optimized after some number of uses as defined
+ // Qt offers explicit control over when QRegularExpression objects get optimized.
+ // By default, patterns are only optimized after some number of uses as defined
// within Qt internals.
//
// In the context of ExpressionMatch, some regular expressions might go unused, e.g. a highlight
//
// else {
// // Optimize regex now
- // #if QT_VERSION >= 0x050400
// newRegEx.optimize();
- // #endif
- //
// }
//
// NOTE: This should only be called if the expression is valid! Apply within an "else" of the
return newRegEx;
}
-
-QString ExpressionMatch::regExEscape(const QString &phrase)
+QString ExpressionMatch::regExEscape(const QString& phrase)
{
// Escape the given phrase of any special regular expression characters
-#if QT_VERSION >= 0x050000
return QRegularExpression::escape(phrase);
-#else
- return QRegExp::escape(phrase);
-#endif
}
-
-QString ExpressionMatch::convertFromMultiPhrase(const QString &originalRule)
+QString ExpressionMatch::convertFromMultiPhrase(const QString& originalRule)
{
// Convert the multi-phrase rule into regular expression format
// Split apart the original rule into components
// Use QStringList instead of std::vector<QString> to make use of Qt's built-in .join() method
QStringList components = {};
// Split on "\n"
- for (auto &&component : originalRule.split("\n", QString::SkipEmptyParts)) {
+ for (auto&& component : originalRule.split("\n", QString::SkipEmptyParts)) {
// Don't trim whitespace to maintain consistency with single phrase matching
// As trimming is not performed, empty components will already be skipped. This means " "
// is considered a valid matching phrase.
}
}
-
-void ExpressionMatch::generateFromMultiWildcard(const QString &originalRule, bool caseSensitive)
+void ExpressionMatch::generateFromMultiWildcard(const QString& originalRule, bool caseSensitive)
{
// Convert the wildcard rule into regular expression format
// First, reset the existing match expressions
// "\\" and "\" are not downconverted to allow for other escape codes to be detected in
// ExpressionMatch::wildcardToRegex
-
// Example:
//
// > Wildcard rule
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << rule << "resulted in rule component"
- << curString << "with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring" << curChar << "character!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << rule << "resulted in rule component" << curString
+ << "with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring" << curChar
+ << "character!";
isRuleStart = false;
break;
}
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << rule << "resulted in rule component"
- << curString << "with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring" << curChar << "character!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << rule << "resulted in rule component" << curString
+ << "with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring" << curChar
+ << "character!";
break;
}
}
break;
case 1:
case 2:
- // "\!" -> Elsewhere: keep as "\!"
- // "\\!" -> Elsewhere: keep as "\\!"
+ // "\!" -> Elsewhere: keep as "\!"
+ // "\\!" -> Elsewhere: keep as "\\!"
curString.append(QString(R"(\)").repeated(consecutiveSlashes) + "!");
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << rule << "resulted in rule component"
- << curString << "with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring" << curChar << "character!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << rule << "resulted in rule component" << curString
+ << "with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring" << curChar
+ << "character!";
break;
}
}
}
else if (consecutiveSlashes > 3) {
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << rule << "resulted in rule component"
- << curString << "with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring" << curChar << "character!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << rule << "resulted in rule component" << curString
+ << "with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring" << curChar
+ << "character!";
break;
}
// Don't set "isRuleStart" here as "\" is used in escape sequences
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << rule << "resulted in rule component"
- << curString << "with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), applying newline split anyways!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << rule << "resulted in rule component" << curString
+ << "with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), applying newline split anyways!";
break;
}
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << rule << "resulted in rule component"
- << curString << "with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring " << curChar << "char escape!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << rule << "resulted in rule component" << curString
+ << "with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring " << curChar
+ << "char escape!";
break;
}
// Don't mark as past rule start for whitespace (whitespace gets trimmed)
_matchInvertRegEx = regExFactory("^" + invertComponents.at(0) + "$", caseSensitive);
}
else {
- _matchInvertRegEx =
- regExFactory("^(?:" + invertComponents.join("|") + ")$", caseSensitive);
+ _matchInvertRegEx = regExFactory("^(?:" + invertComponents.join("|") + ")$", caseSensitive);
}
_matchInvertRegExActive = true;
}
}
-
-QString ExpressionMatch::wildcardToRegEx(const QString &expression)
+QString ExpressionMatch::wildcardToRegEx(const QString& expression)
{
// Convert the wildcard expression into regular expression format
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << expression << "resulted in escaped regular expression string"
- << regExEscaped << " with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring" << curChar << "character!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << expression << "resulted in escaped regular expression string"
+ << regExEscaped << " with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring"
+ << curChar << "character!";
break;
}
consecutiveSlashes = 0;
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << expression << "resulted in escaped regular expression string"
- << regExEscaped << " with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring" << curChar << "character!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << expression << "resulted in escaped regular expression string"
+ << regExEscaped << " with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring"
+ << curChar << "character!";
break;
}
consecutiveSlashes = 0;
break;
default:
// This shouldn't ever happen (even with invalid wildcard rules), log a warning
- qWarning() << Q_FUNC_INFO << "Wildcard rule"
- << expression << "resulted in escaped regular expression string"
- << regExEscaped << " with unexpected count of consecutive '\\' ("
- << consecutiveSlashes << "), ignoring" << curChar << "char escape!";
+ qWarning() << Q_FUNC_INFO << "Wildcard rule" << expression << "resulted in escaped regular expression string"
+ << regExEscaped << " with unexpected count of consecutive '\\' (" << consecutiveSlashes << "), ignoring"
+ << curChar << "char escape!";
break;
}
consecutiveSlashes = 0;