mirror of
https://github.com/tnodir/fort
synced 2024-11-15 04:45:59 +00:00
RuleTextParser: Prepare lines parsing
This commit is contained in:
parent
da79ae6714
commit
e47ba8f627
@ -6,31 +6,36 @@
|
||||
|
||||
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()) {
|
||||
return CharNameBegin;
|
||||
return CharLetter;
|
||||
}
|
||||
|
||||
if (c.isDigit()) {
|
||||
return CharValueBegin;
|
||||
return CharDigit;
|
||||
}
|
||||
|
||||
static const QHash<char, RuleCharType> charTypeMap = {
|
||||
{ '{', CharListBegin },
|
||||
{ '}', CharListEnd },
|
||||
{ '(', CharBracketBegin },
|
||||
{ ')', CharBracketEnd },
|
||||
{ '[', CharValueBegin },
|
||||
{ ',', CharValueSeparator },
|
||||
{ ':', CharColon },
|
||||
{ '#', CharComment },
|
||||
};
|
||||
const char c1 = c.toLatin1();
|
||||
|
||||
return charTypeMap.value(c.unicode(), CharNone);
|
||||
if (extraChars && strchr(extraChars, c1)) {
|
||||
return CharExtra;
|
||||
}
|
||||
|
||||
RuleCharType processCharType(RuleCharType charType, const QChar c)
|
||||
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, const char *extraChars = nullptr)
|
||||
{
|
||||
if (charType == CharComment) {
|
||||
if (c == '\n') {
|
||||
@ -40,7 +45,7 @@ RuleCharType processCharType(RuleCharType charType, const QChar c)
|
||||
return CharComment;
|
||||
}
|
||||
|
||||
return processChar(c);
|
||||
return processChar(c, extraChars);
|
||||
}
|
||||
|
||||
}
|
||||
@ -58,21 +63,147 @@ void RuleTextParser::setupText(const QString &text)
|
||||
|
||||
bool RuleTextParser::parse()
|
||||
{
|
||||
const auto charType = nextCharType();
|
||||
return parseLines();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
RuleCharType RuleTextParser::nextCharType()
|
||||
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;
|
||||
|
||||
while (m_p < m_end) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,28 @@
|
||||
|
||||
#include <util/util_types.h>
|
||||
|
||||
enum RuleCharType {
|
||||
using RuleCharTypes = quint16;
|
||||
|
||||
enum RuleCharType : RuleCharTypes {
|
||||
CharNone = 0,
|
||||
CharListBegin = (1 << 0), // {
|
||||
CharListEnd = (1 << 1), // }
|
||||
CharBracketBegin = (1 << 2), // (
|
||||
CharBracketEnd = (1 << 3), // )
|
||||
CharNameBegin = (1 << 4), // a-zA-Z
|
||||
CharName = (1 << 5), // a-zA-Z0-9_-
|
||||
CharValueBegin = (1 << 6), // [0-9
|
||||
CharValue = (1 << 7), // 0-9.:-/
|
||||
CharValueSeparator = (1 << 8), // ,
|
||||
CharColon = (1 << 9), // :
|
||||
CharComment = (1 << 10), // #
|
||||
CharLetter = (1 << 4), // a-zA-Z
|
||||
CharDigit = (1 << 5), // 0-9
|
||||
CharValueBegin = (1 << 6), // [
|
||||
CharValueSeparator = (1 << 7), // ,
|
||||
CharColon = (1 << 8), // :
|
||||
CharComment = (1 << 9), // #
|
||||
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
|
||||
@ -26,7 +35,6 @@ struct RuleExpr
|
||||
quint8 flags = 0;
|
||||
quint8 type = 0;
|
||||
|
||||
quint16 listIndex = 0;
|
||||
quint16 listCount = 0;
|
||||
|
||||
StringViewList viewList;
|
||||
@ -39,21 +47,49 @@ class RuleTextParser : public QObject
|
||||
public:
|
||||
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; }
|
||||
|
||||
bool parse();
|
||||
|
||||
private:
|
||||
void setErrorMessage(const QString &errorMessage) { m_errorMessage = errorMessage; }
|
||||
|
||||
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:
|
||||
bool m_isNot = false;
|
||||
|
||||
quint8 m_exprType = 0;
|
||||
|
||||
const QChar *m_p = nullptr;
|
||||
const QChar *m_end = nullptr;
|
||||
|
||||
QString m_errorMessage;
|
||||
|
||||
QVector<RuleExpr> m_ruleExprArray;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user