1 /************************************************************************
2 **
3 **  Copyright (C) 2020-2021 Kevin B. Hendricks Stratford, ON, Canada
4 **
5 **  This file is part of Sigil.
6 **
7 **  Sigil is free software: you can redistribute it and/or modify
8 **  it under the terms of the GNU General Public License as published by
9 **  the Free Software Foundation, either version 3 of the License, or
10 **  (at your option) any later version.
11 **
12 **  Sigil is distributed in the hope that it will be useful,
13 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 **  GNU General Public License for more details.
16 **
17 **  You should have received a copy of the GNU General Public License
18 **  along with Sigil.  If not, see <http://www.gnu.org/licenses/>.
19 **
20 *************************************************************************/
21 
22 #ifndef TAG_LISTER
23 #define TAG_LISTER
24 
25 #include <QList>
26 
27 class QString;
28 class QStringRef;
29 class QStringList;
30 
31 class TagLister
32 {
33 public:
34 
35     struct TagInfo {
36         int     pos;      // position of tag in source
37         int     len;      // length of tag in source
38         QString tpath;    // path of tag names to this tag ("." joined)
39         QString tname;    // tag name, ?xml, ?, !--, !DOCTYPE, ![CDATA[
40         QString ttype;    // xmlheader, pi, comment, doctype, cdata, begin, single, end
41         int     open_pos; // set if end tag to position of its corresponding begin tag
42         int     open_len; // set if end tag to length of its corresponding begin tag
43     };
44 
45     struct AttInfo {
46         int     pos;      // position of attribute relative to tag start
47         int     len;      // length of attribute in tag
48         int     vpos;     // position of attribute value relative to tag start
49         int     vlen;     // length of attribute value
50         QString aname;    // attribute name
51         QString avalue;   // attribute value
52     };
53 
54 
55     TagLister();
56 
57     TagLister(const QString &source);
~TagLister()58     ~TagLister() {};
59 
60     void reloadLister(const QString &source);
61 
62     const TagInfo& at(int i);
63     size_t size();
64 
65     bool isPositionInBody(int pos);
66     bool isPositionInTag(int pos);
67     bool isPositionInOpenTag(int pos);
68     bool isPositionInCloseTag(int pos);
69 
70     int findLastTagOnOrBefore(int pos);
71     int findFirstTagOnOrAfter(int pos);
72     int findOpenTagForClose(int i);
73     int findCloseTagForOpen(int i);
74     int findBodyOpenTag();
75     int findBodyCloseTag();
76 
77     const QString& getSource();
78 
79     static void parseAttribute(const QStringRef &tagstring, const QString &attribute_name, AttInfo& ainfo);
80     static QString serializeAttribute(const QString &aname, const QString &avalue);
81     static QString extractAllAttributes(const QStringRef &tagstring);
82 
83 private:
84     TagInfo getNext();
85     void  buildTagList();
86 
87     QStringRef parseML();
88 
89     void parseTag(const QStringRef &tagstring, TagInfo &mi);
90 
91     int findTarget(const QString &tgt, int p, bool after=false);
92     static int skipAnyBlanks(const QStringRef &segment, int p);
93     static int stopWhenContains(const QStringRef &segment, const QString& stopchars, int p);
94 
95     QString        m_source;
96     int            m_pos;
97     int            m_next;
98     QStringList    m_TagPath;
99     QList<int>     m_TagPos;
100     QList<int>     m_TagLen;
101     QList<TagInfo> m_Tags;
102     int            m_bodyStartPos;
103     int            m_bodyEndPos;
104     int            m_bodyOpenTag;
105     int            m_bodyCloseTag;
106 };
107 
108 #endif
109