forked from Mudlet/Mudlet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMxpTag.h
170 lines (121 loc) · 5.82 KB
/
MxpTag.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#ifndef MUDLET_MXPTAG_H
#define MUDLET_MXPTAG_H
/***************************************************************************
* Copyright (C) 2020 by Gustavo Sousa - gustavocms@gmail.com *
* Copyright (C) 2020 by Stephen Lyons - slysven@virginmedia.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "pre_guard.h"
#include <QMap>
#include <QPair>
#include <QString>
#include <QStringList>
#include "post_guard.h"
#include <functional>
class MxpTagAttribute : public QPair<QString, QString>
{
public:
typedef std::function<MxpTagAttribute(const MxpTagAttribute&)> Transformation;
MxpTagAttribute();
explicit MxpTagAttribute(const QString&);
MxpTagAttribute(const QString&, const QString&);
// Because derived classes may (in fact do) have real destructors we must
// declare AND define a virtual one in this, the base one:
virtual ~MxpTagAttribute();
virtual const QString& getName() const { return first; }
inline const QString& getValue() const { return second; }
inline bool hasValue() const { return !second.isEmpty(); }
inline bool isNamed(const QString& name) const { return name.compare(first, Qt::CaseInsensitive) == 0; }
};
class MxpTag;
class MxpStartTag;
class MxpEndTag;
class MxpTextNode;
class MxpNode
{
public:
enum Type { MXP_NODE_TYPE_TEXT, MXP_NODE_TYPE_START_TAG, MXP_NODE_TYPE_END_TAG };
MxpNode::Type getType() const { return mType; }
MxpTag* asTag() { return mType != MXP_NODE_TYPE_TEXT ? reinterpret_cast<MxpTag*>(this) : nullptr; }
MxpStartTag* asStartTag() { return mType == MXP_NODE_TYPE_START_TAG ? reinterpret_cast<MxpStartTag*>(this) : nullptr; }
MxpEndTag* asEndTag() { return mType == MXP_NODE_TYPE_END_TAG ? reinterpret_cast<MxpEndTag*>(this) : nullptr; }
MxpTextNode* asText() { return mType == MXP_NODE_TYPE_TEXT ? reinterpret_cast<MxpTextNode*>(this) : nullptr; }
virtual QString toString() const = 0;
bool isTag() { return mType != MXP_NODE_TYPE_TEXT; }
bool isEndTag() { return mType == MXP_NODE_TYPE_END_TAG; }
bool isStartTag() { return mType == MXP_NODE_TYPE_START_TAG; }
virtual ~MxpNode() = default;
protected:
explicit MxpNode(MxpNode::Type type) : mType(type) {}
MxpNode::Type mType;
};
class MxpTextNode : public MxpNode
{
QString mContent;
public:
explicit MxpTextNode(const QString& content) : MxpNode(MXP_NODE_TYPE_TEXT), mContent(QString(content)) {}
inline const QString& getContent() const { return mContent; }
virtual QString toString() const { return mContent; }
};
class MxpTag : public MxpNode
{
friend class TMxpTagParser;
public:
virtual ~MxpTag() = default;
inline const QString& getName() const { return name; }
inline bool isStartTag() const { return mType == MXP_NODE_TYPE_START_TAG; }
inline bool isEndTag() const { return mType == MXP_NODE_TYPE_END_TAG; }
bool isNamed(const QString& tagName) const;
protected:
QString name;
explicit MxpTag(MxpNode::Type type, const QString& name) : MxpNode(type), name(name) {}
};
class MxpEndTag : public MxpTag
{
public:
explicit MxpEndTag(const QString& name) : MxpTag(MXP_NODE_TYPE_END_TAG, name) {}
QString toString() const override;
};
class MxpStartTag : public MxpTag
{
QMap<QString, MxpTagAttribute> mAttrsMap;
QStringList mAttrsNames;
bool mIsEmpty;
public:
explicit MxpStartTag(const QString& name) : MxpStartTag(name, QList<MxpTagAttribute>(), false) {}
MxpStartTag(const QString& name, const QList<MxpTagAttribute>& attributes, bool isEmpty) : MxpTag(MXP_NODE_TYPE_START_TAG, QString(name)), mIsEmpty(isEmpty)
{
for (const auto& attr : attributes) {
mAttrsNames.append(attr.getName());
mAttrsMap[attr.first.toUpper()] = attr;
}
}
MxpStartTag transform(const MxpTagAttribute::Transformation& transformation) const;
inline const QStringList& getAttributesNames() const { return mAttrsNames; }
inline int getAttributesCount() const { return mAttrsNames.size(); }
bool hasAttribute(const QString& attrName) const;
const MxpTagAttribute& getAttribute(int attrIndex) const;
const MxpTagAttribute& getAttribute(const QString& attrName) const;
const QString& getAttributeValue(int attrIndex) const;
const QString& getAttributeValue(const QString& attrName) const;
const QString& getAttributeByNameOrIndex(const QString& attrName, int attrIndex, const QString& defaultValue = QString()) const;
bool isAttributeAt(const char* attrName, int attrIndex);
inline bool isEmpty() const { return mIsEmpty; }
QString toString() const override;
const QString& getAttrName(int attrIndex) const;
};
#endif //MUDLET_MXPTAG_H