1 /*
2     This file is part of the KDE libraries
3 
4     Copyright (C) 1999 Lars Knoll (knoll@mpi-hd.mpg.de)
5     Copyright (C) 2004 Apple Computer, Inc.
6 
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Library General Public
9     License as published by the Free Software Foundation; either
10     version 2 of the License, or (at your option) any later version.
11 
12     This library 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 GNU
15     Library General Public License for more details.
16 
17     You should have received a copy of the GNU Library General Public License
18     along with this library; see the file COPYING.LIB.  If not, write to
19     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20     Boston, MA 02110-1301, USA.
21 */
22 //----------------------------------------------------------------------------
23 //
24 // KDE HTML Widget -- String class
25 
26 #ifndef KHTMLSTRING_H
27 #define KHTMLSTRING_H
28 
29 #include "dom/dom_string.h"
30 
31 #include <QList>
32 #include <QString>
33 
34 #include <assert.h>
35 
36 using namespace DOM;
37 
38 namespace khtml
39 {
40 
41 class DOMStringIt
42 {
43 public:
DOMStringIt()44     DOMStringIt()
45     {
46         s = nullptr, l = 0;
47         lines = 0;
48     }
DOMStringIt(QChar * str,uint len)49     DOMStringIt(QChar *str, uint len)
50     {
51         s = str, l = len;
52         lines = 0;
53     }
DOMStringIt(const QString & str)54     DOMStringIt(const QString &str)
55     {
56         s = str.unicode();
57         l = str.length();
58         lines = 0;
59     }
60 
61     DOMStringIt *operator++()
62     {
63         if (!pushedChar.isNull()) {
64             pushedChar = 0;
65         } else if (l > 0) {
66             if (*s == QLatin1Char('\n')) {
67                 lines++;
68             }
69             s++, l--;
70         }
71         return this;
72     }
73 public:
push(const QChar & c)74     void push(const QChar &c)
75     {
76         /* assert(pushedChar.isNull());*/  pushedChar = c;
77     }
78 
79     const QChar &operator*() const
80     {
81         return pushedChar.isNull() ? *s : pushedChar;
82     }
83     const QChar *operator->() const
84     {
85         return pushedChar.isNull() ? s : &pushedChar;
86     }
87 
escaped()88     bool escaped() const
89     {
90         return !pushedChar.isNull();
91     }
length()92     uint length() const
93     {
94         return l + (!pushedChar.isNull());
95     }
96 
current()97     const QChar *current() const
98     {
99         return pushedChar.isNull() ? s : &pushedChar;
100     }
lineCount()101     int lineCount() const
102     {
103         return lines;
104     }
105 
106 protected:
107     QChar pushedChar;
108     const QChar *s;
109     int l;
110     int lines;
111 };
112 
113 class TokenizerString;
114 
115 class TokenizerSubstring
116 {
117     friend class TokenizerString;
118 public:
TokenizerSubstring()119     TokenizerSubstring() : m_length(0), m_current(nullptr) {}
TokenizerSubstring(const QString & str)120     TokenizerSubstring(const QString &str) : m_string(str), m_length(str.length()), m_current(m_length == 0 ? nullptr : str.unicode()) {}
TokenizerSubstring(const QChar * str,int length)121     TokenizerSubstring(const QChar *str, int length) : m_length(length), m_current(length == 0 ? nullptr : str) {}
122 
clear()123     void clear()
124     {
125         m_length = 0;
126         m_current = nullptr;
127     }
128 
appendTo(QString & str)129     void appendTo(QString &str) const
130     {
131         if (m_string.unicode() == m_current) {
132             if (str.isEmpty()) {
133                 str = m_string;
134             } else {
135                 str.append(m_string);
136             }
137         } else {
138             str.insert(str.length(), m_current, m_length);
139         }
140     }
141 private:
142     QString m_string;
143     int m_length;
144     const QChar *m_current;
145 };
146 
147 class TokenizerString
148 {
149 
150 public:
TokenizerString()151     TokenizerString() : m_currentChar(nullptr), m_lines(0), m_composite(false) {}
TokenizerString(const QChar * str,int length)152     TokenizerString(const QChar *str, int length) : m_currentString(str, length), m_currentChar(m_currentString.m_current), m_lines(0), m_composite(false) {}
TokenizerString(const QString & str)153     TokenizerString(const QString &str) : m_currentString(str), m_currentChar(m_currentString.m_current), m_lines(0), m_composite(false) {}
TokenizerString(const TokenizerString & o)154     TokenizerString(const TokenizerString &o) : m_pushedChar1(o.m_pushedChar1), m_pushedChar2(o.m_pushedChar2),
155         m_currentString(o.m_currentString), m_substrings(o.m_substrings),
156         m_lines(o.m_lines), m_composite(o.m_composite)
157     {
158         m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
159     }
160 
161     void clear();
162 
163     void append(const TokenizerString &);
164     void prepend(const TokenizerString &);
165 
push(QChar c)166     void push(QChar c)
167     {
168         if (m_pushedChar1.isNull()) {
169             m_pushedChar1 = c;
170             m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
171         } else {
172             assert(m_pushedChar2.isNull());
173             m_pushedChar2 = c;
174         }
175     }
176 
isEmpty()177     bool isEmpty() const
178     {
179         return !current();
180     }
181     uint length() const;
182 
advance()183     void advance()
184     {
185         if (!m_pushedChar1.isNull()) {
186             m_pushedChar1 = m_pushedChar2;
187             m_pushedChar2 = 0;
188         } else if (m_currentString.m_current) {
189             m_lines += *m_currentString.m_current++ == QLatin1Char('\n');
190             if (--m_currentString.m_length == 0) {
191                 advanceSubstring();
192             }
193         }
194         m_currentChar = m_pushedChar1.isNull() ? m_currentString.m_current : &m_pushedChar1;
195     }
count()196     uint count() const
197     {
198         return m_substrings.count();
199     }
200 
escaped()201     bool escaped() const
202     {
203         return !m_pushedChar1.isNull();
204     }
205 
lineCount()206     int lineCount() const
207     {
208         return m_lines;
209     }
resetLineCount()210     void resetLineCount()
211     {
212         m_lines = 0;
213     }
214 
215     QString toString() const;
216 
217     void operator++()
218     {
219         advance();
220     }
221     const QChar &operator*() const
222     {
223         return *current();
224     }
225     const QChar *operator->() const
226     {
227         return current();
228     }
229 
230 private:
231     void append(const TokenizerSubstring &);
232     void prepend(const TokenizerSubstring &);
233 
234     void advanceSubstring();
current()235     const QChar *current() const
236     {
237         return m_currentChar;
238     }
239 
240     QChar m_pushedChar1;
241     QChar m_pushedChar2;
242     TokenizerSubstring m_currentString;
243     const QChar *m_currentChar;
244     QList<TokenizerSubstring> m_substrings;
245     int m_lines;
246     bool m_composite;
247 
248 };
249 
250 class TokenizerQueue : public QList<TokenizerString>
251 {
252 
253 public:
TokenizerQueue()254     TokenizerQueue() {}
~TokenizerQueue()255     ~TokenizerQueue() {}
push(const TokenizerString & t)256     void  push(const TokenizerString &t)
257     {
258         prepend(t);
259     }
pop()260     TokenizerString pop()
261     {
262         if (isEmpty()) {
263             return TokenizerString();
264         }
265         TokenizerString t(first());
266         erase(begin());
267         return t;
268     }
top()269     TokenizerString &top()
270     {
271         return first();
272     }
bottom()273     TokenizerString &bottom()
274     {
275         return last();
276     }
277 };
278 
279 }
280 
281 #endif
282 
283