mirror of
https://github.com/tnodir/fort
synced 2024-11-15 07:38:16 +00:00
RuleTextParser: Prepare lines parsing
This commit is contained in:
parent
da79ae6714
commit
e47ba8f627
@ -6,31 +6,36 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
RuleCharType processChar(const QChar c)
|
const char *const extraNameChars = "_";
|
||||||
|
const char *const extraValueChars = ".:-/]";
|
||||||
|
|
||||||
|
RuleCharType processChar(const QChar c, const char *extraChars = nullptr)
|
||||||
{
|
{
|
||||||
if (c.isLetter()) {
|
if (c.isLetter()) {
|
||||||
return CharNameBegin;
|
return CharLetter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.isDigit()) {
|
if (c.isDigit()) {
|
||||||
return CharValueBegin;
|
return CharDigit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const QHash<char, RuleCharType> charTypeMap = {
|
const char c1 = c.toLatin1();
|
||||||
{ '{', CharListBegin },
|
|
||||||
{ '}', CharListEnd },
|
|
||||||
{ '(', CharBracketBegin },
|
|
||||||
{ ')', CharBracketEnd },
|
|
||||||
{ '[', CharValueBegin },
|
|
||||||
{ ',', CharValueSeparator },
|
|
||||||
{ ':', CharColon },
|
|
||||||
{ '#', CharComment },
|
|
||||||
};
|
|
||||||
|
|
||||||
return charTypeMap.value(c.unicode(), CharNone);
|
if (extraChars && strchr(extraChars, c1)) {
|
||||||
|
return CharExtra;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char chars[] = "{}()[,:#!\n";
|
||||||
|
static const RuleCharType charTypes[] = { CharListBegin, CharListEnd, CharBracketBegin,
|
||||||
|
CharBracketEnd, CharValueBegin, CharValueSeparator, CharColon, CharComment, CharNot,
|
||||||
|
CharNewLine };
|
||||||
|
|
||||||
|
const char *cp = strchr(chars, c1);
|
||||||
|
|
||||||
|
return cp ? charTypes[cp - chars] : CharNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuleCharType processCharType(RuleCharType charType, const QChar c)
|
RuleCharType processCharType(RuleCharType charType, const QChar c, const char *extraChars = nullptr)
|
||||||
{
|
{
|
||||||
if (charType == CharComment) {
|
if (charType == CharComment) {
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
@ -40,7 +45,7 @@ RuleCharType processCharType(RuleCharType charType, const QChar c)
|
|||||||
return CharComment;
|
return CharComment;
|
||||||
}
|
}
|
||||||
|
|
||||||
return processChar(c);
|
return processChar(c, extraChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -58,21 +63,147 @@ void RuleTextParser::setupText(const QString &text)
|
|||||||
|
|
||||||
bool RuleTextParser::parse()
|
bool RuleTextParser::parse()
|
||||||
{
|
{
|
||||||
const auto charType = nextCharType();
|
return parseLines();
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RuleCharType RuleTextParser::nextCharType()
|
bool RuleTextParser::parseLines()
|
||||||
{
|
{
|
||||||
|
const int listIndex = pushListNode(FORT_RULE_EXPR_LIST_OR);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (!parseLine())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
popListNode(listIndex);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuleTextParser::parseLine()
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
const auto charType = nextCharType(CharAnyBegin);
|
||||||
|
|
||||||
|
switch (charType) {
|
||||||
|
case CharListBegin: {
|
||||||
|
ok = parseLines();
|
||||||
|
} break;
|
||||||
|
case CharBracketBegin: {
|
||||||
|
ok = parseBracketValues();
|
||||||
|
} break;
|
||||||
|
case CharLetter: {
|
||||||
|
ok = parseName();
|
||||||
|
} break;
|
||||||
|
case CharNot: {
|
||||||
|
m_isNot = !m_isNot;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuleTextParser::parseName()
|
||||||
|
{
|
||||||
|
const QChar *name = parsedCharPtr();
|
||||||
|
|
||||||
|
while (nextCharType(CharName, extraNameChars) != CharNone) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasError()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ungetChar();
|
||||||
|
|
||||||
|
const QStringView nameView(name, currentCharPtr() - name);
|
||||||
|
const auto nameLower = nameView.toString().toLower();
|
||||||
|
|
||||||
|
static const QHash<QString, qint8> exprTypesMap = {
|
||||||
|
{ "ip", FORT_RULE_EXPR_TYPE_ADDRESS },
|
||||||
|
{ "port", FORT_RULE_EXPR_TYPE_PORT },
|
||||||
|
{ "local_ip", FORT_RULE_EXPR_TYPE_LOCAL_ADDRESS },
|
||||||
|
{ "local_port", FORT_RULE_EXPR_TYPE_LOCAL_PORT },
|
||||||
|
{ "proto", FORT_RULE_EXPR_TYPE_PROTOCOL },
|
||||||
|
{ "protocol", FORT_RULE_EXPR_TYPE_PROTOCOL },
|
||||||
|
{ "dir", FORT_RULE_EXPR_TYPE_DIRECTION },
|
||||||
|
{ "direction", FORT_RULE_EXPR_TYPE_DIRECTION },
|
||||||
|
};
|
||||||
|
|
||||||
|
m_exprType = exprTypesMap.value(nameLower, -1);
|
||||||
|
|
||||||
|
if (m_exprType == -1) {
|
||||||
|
setErrorMessage(tr("Bad text: %1").arg(nameView));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuleTextParser::parseBracketValues()
|
||||||
|
{
|
||||||
|
const auto endCharType = parseValues();
|
||||||
|
|
||||||
|
return (endCharType == CharBracketEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
RuleCharType RuleTextParser::parseValues()
|
||||||
|
{
|
||||||
|
return CharNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RuleTextParser::pushListNode(int listType)
|
||||||
|
{
|
||||||
|
const int listIndex = m_ruleExprArray.size();
|
||||||
|
|
||||||
|
RuleExpr ruleExpr;
|
||||||
|
ruleExpr.flags = FORT_RULE_EXPR_FLAG_LIST;
|
||||||
|
ruleExpr.type = listType;
|
||||||
|
|
||||||
|
m_ruleExprArray.append(ruleExpr);
|
||||||
|
|
||||||
|
return listIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuleTextParser::popListNode(int listIndex)
|
||||||
|
{
|
||||||
|
const int curListIndex = m_ruleExprArray.size();
|
||||||
|
|
||||||
|
RuleExpr &ruleExpr = m_ruleExprArray[listIndex];
|
||||||
|
|
||||||
|
ruleExpr.listCount = curListIndex - listIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
RuleCharType RuleTextParser::nextCharType(quint32 expectedCharTypes, const char *extraChars)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!extraChars || (expectedCharTypes & CharExtra) != 0);
|
||||||
|
|
||||||
|
const auto cp = m_p;
|
||||||
|
|
||||||
RuleCharType charType = CharNone;
|
RuleCharType charType = CharNone;
|
||||||
|
|
||||||
while (m_p < m_end) {
|
while (m_p < m_end) {
|
||||||
const QChar c = *m_p++;
|
const QChar c = *m_p++;
|
||||||
|
|
||||||
charType = processCharType(charType, c);
|
charType = processCharType(charType, c, extraChars);
|
||||||
|
|
||||||
|
switch (charType) {
|
||||||
|
case CharNone: {
|
||||||
|
setErrorMessage(tr("Bad symbol: %1").arg(c));
|
||||||
|
return CharNone;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
if ((charType & expectedCharTypes) == 0) {
|
||||||
|
if (cp == m_p) {
|
||||||
|
setErrorMessage(tr("Unexpected symbol: %1").arg(c));
|
||||||
|
}
|
||||||
|
return CharNone;
|
||||||
|
}
|
||||||
|
|
||||||
if (charType != CharNone) {
|
|
||||||
return charType;
|
return charType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,19 +6,28 @@
|
|||||||
|
|
||||||
#include <util/util_types.h>
|
#include <util/util_types.h>
|
||||||
|
|
||||||
enum RuleCharType {
|
using RuleCharTypes = quint16;
|
||||||
|
|
||||||
|
enum RuleCharType : RuleCharTypes {
|
||||||
CharNone = 0,
|
CharNone = 0,
|
||||||
CharListBegin = (1 << 0), // {
|
CharListBegin = (1 << 0), // {
|
||||||
CharListEnd = (1 << 1), // }
|
CharListEnd = (1 << 1), // }
|
||||||
CharBracketBegin = (1 << 2), // (
|
CharBracketBegin = (1 << 2), // (
|
||||||
CharBracketEnd = (1 << 3), // )
|
CharBracketEnd = (1 << 3), // )
|
||||||
CharNameBegin = (1 << 4), // a-zA-Z
|
CharLetter = (1 << 4), // a-zA-Z
|
||||||
CharName = (1 << 5), // a-zA-Z0-9_-
|
CharDigit = (1 << 5), // 0-9
|
||||||
CharValueBegin = (1 << 6), // [0-9
|
CharValueBegin = (1 << 6), // [
|
||||||
CharValue = (1 << 7), // 0-9.:-/
|
CharValueSeparator = (1 << 7), // ,
|
||||||
CharValueSeparator = (1 << 8), // ,
|
CharColon = (1 << 8), // :
|
||||||
CharColon = (1 << 9), // :
|
CharComment = (1 << 9), // #
|
||||||
CharComment = (1 << 10), // #
|
CharNot = (1 << 10), // !
|
||||||
|
CharExtra = (1 << 11), // Name | Value
|
||||||
|
CharNewLine = (1 << 12), // \n
|
||||||
|
CharAnyBegin =
|
||||||
|
(CharListBegin | CharBracketBegin | CharLetter | CharDigit | CharValueBegin | CharNot),
|
||||||
|
CharName = (CharLetter | CharExtra), // a-zA-Z_
|
||||||
|
CharValue = (CharDigit | CharValueBegin | CharExtra), // 0-9.:-/]
|
||||||
|
CharAny = RuleCharTypes(-1),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RuleExpr
|
struct RuleExpr
|
||||||
@ -26,7 +35,6 @@ struct RuleExpr
|
|||||||
quint8 flags = 0;
|
quint8 flags = 0;
|
||||||
quint8 type = 0;
|
quint8 type = 0;
|
||||||
|
|
||||||
quint16 listIndex = 0;
|
|
||||||
quint16 listCount = 0;
|
quint16 listCount = 0;
|
||||||
|
|
||||||
StringViewList viewList;
|
StringViewList viewList;
|
||||||
@ -39,21 +47,49 @@ class RuleTextParser : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit RuleTextParser(const QString &text, QObject *parent = nullptr);
|
explicit RuleTextParser(const QString &text, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QString errorMessage() const { return m_errorMessage; }
|
||||||
|
|
||||||
|
bool hasError() const { return !errorMessage().isEmpty(); }
|
||||||
|
|
||||||
const QVector<RuleExpr> &ruleExprArray() const { return m_ruleExprArray; }
|
const QVector<RuleExpr> &ruleExprArray() const { return m_ruleExprArray; }
|
||||||
|
|
||||||
bool parse();
|
bool parse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setErrorMessage(const QString &errorMessage) { m_errorMessage = errorMessage; }
|
||||||
|
|
||||||
void setupText(const QString &text);
|
void setupText(const QString &text);
|
||||||
|
|
||||||
RuleCharType nextCharType();
|
bool parseLines();
|
||||||
|
bool parseLine();
|
||||||
|
|
||||||
|
bool parseName();
|
||||||
|
|
||||||
|
bool parseBracketValues();
|
||||||
|
RuleCharType parseValues();
|
||||||
|
|
||||||
|
int pushListNode(int listType);
|
||||||
|
void popListNode(int listIndex);
|
||||||
|
|
||||||
|
void ungetChar() { --m_p; }
|
||||||
|
|
||||||
|
const QChar *currentCharPtr() const { return m_p; }
|
||||||
|
const QChar *parsedCharPtr() const { return m_p - 1; }
|
||||||
|
|
||||||
|
RuleExpr &listNode(int listIndex) { return m_ruleExprArray[listIndex]; }
|
||||||
|
|
||||||
|
RuleCharType nextCharType(quint32 expectedCharTypes, const char *extraChars = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool m_isNot = false;
|
||||||
|
|
||||||
quint8 m_exprType = 0;
|
quint8 m_exprType = 0;
|
||||||
|
|
||||||
const QChar *m_p = nullptr;
|
const QChar *m_p = nullptr;
|
||||||
const QChar *m_end = nullptr;
|
const QChar *m_end = nullptr;
|
||||||
|
|
||||||
|
QString m_errorMessage;
|
||||||
|
|
||||||
QVector<RuleExpr> m_ruleExprArray;
|
QVector<RuleExpr> m_ruleExprArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user