KHtml

dom_string.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright 1999 Lars Knoll ([email protected])
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #include "dom/dom_string.h"
23 #include "xml/dom_stringimpl.h"
24 
25 #include <wtf/Vector.h>
26 
27 using namespace DOM;
28 
29 DOMString::DOMString(const QChar *str, uint len)
30 {
31  if (!str) {
32  impl = nullptr;
33  return;
34  }
35  impl = new DOMStringImpl(str, len);
36  impl->ref();
37 }
38 
39 DOMString::DOMString(const QString &str)
40 {
41  if (str.isNull()) {
42  impl = nullptr;
43  return;
44  }
45 
46  impl = new DOMStringImpl(str.unicode(), str.length());
47  impl->ref();
48 }
49 
50 DOMString::DOMString(const char *str)
51 {
52  if (!str) {
53  impl = nullptr;
54  return;
55  }
56 
57  impl = new DOMStringImpl(str);
58  impl->ref();
59 }
60 
61 DOMString::DOMString(const char *str, uint len)
62 {
63  if (!str) {
64  impl = nullptr;
65  return;
66  }
67  impl = new DOMStringImpl(str, len);
68  impl->ref();
69 }
70 
71 DOMString::DOMString(DOMStringImpl *i)
72 {
73  impl = i;
74  if (impl) {
75  impl->ref();
76  }
77 }
78 
79 DOMString::DOMString(const DOMString &other)
80 {
81  impl = other.impl;
82  if (impl) {
83  impl->ref();
84  }
85 }
86 
87 DOMString::~DOMString()
88 {
89  if (impl) {
90  impl->deref();
91  }
92 }
93 
94 DOMString &DOMString::operator =(const DOMString &other)
95 {
96  if (impl != other.impl) {
97  if (impl) {
98  impl->deref();
99  }
100  impl = other.impl;
101  if (impl) {
102  impl->ref();
103  }
104  }
105  return *this;
106 }
107 
109 {
110  if (!impl) {
111  // ### FIXME!!!
112  impl = str.impl;
113  if (impl) {
114  impl->ref();
115  }
116  return *this;
117  }
118  if (str.impl) {
119  DOMStringImpl *i = impl->copy();
120  impl->deref();
121  impl = i;
122  impl->ref();
123  impl->append(str.impl);
124  }
125  return *this;
126 }
127 
129 {
130  if (!impl) {
131  return str.copy();
132  }
133  if (str.impl) {
134  DOMString s = copy();
135  s += str;
136  return s;
137  }
138 
139  return copy();
140 }
141 
142 void DOMString::insert(DOMString str, uint pos)
143 {
144  if (!impl) {
145  impl = str.impl->copy();
146  impl->ref();
147  } else {
148  impl->insert(str.impl, pos);
149  }
150 }
151 
152 const QChar &DOMString::operator [](unsigned int i) const
153 {
154  static const QChar nullChar = 0;
155 
156  if (!impl || i >= impl->l) {
157  return nullChar;
158  }
159 
160  return *(impl->s + i);
161 }
162 
163 int DOMString::find(const QChar c, int start) const
164 {
165  unsigned int l = start;
166  if (!impl || l >= impl->l) {
167  return -1;
168  }
169  while (l < impl->l) {
170  if (*(impl->s + l) == c) {
171  return l;
172  }
173  l++;
174  }
175  return -1;
176 }
177 
178 int DOMString::reverseFind(const QChar c, int start) const
179 {
180  unsigned int l = start;
181  if (!impl || l < -impl->l) {
182  return -1;
183  }
184  l += impl->l;
185  while (1) {
186  if (*(impl->s + l) == c) {
187  return l;
188  }
189  l--;
190  if (l == 0) {
191  return -1;
192  }
193  }
194  return -1;
195 }
196 
197 DOMString DOMString::substring(unsigned pos, unsigned len) const
198 {
199  return (impl) ? impl->substring(pos, len) : DOMString();
200 }
201 
202 uint DOMString::length() const
203 {
204  if (!impl) {
205  return 0;
206  }
207  return impl->l;
208 }
209 
210 void DOMString::truncate(unsigned int len)
211 {
212  if (impl) {
213  impl->truncate(len);
214  }
215 }
216 
217 void DOMString::remove(unsigned int pos, int len)
218 {
219  if (impl) {
220  impl->remove(pos, len);
221  }
222 }
223 
224 DOMString DOMString::split(unsigned int pos)
225 {
226  if (!impl) {
227  return DOMString();
228  }
229  return impl->split(pos);
230 }
231 
233 {
234  if (!impl) {
235  return DOMString();
236  }
237  return impl->lower();
238 }
239 
241 {
242  if (!impl) {
243  return DOMString();
244  }
245  return impl->upper();
246 }
247 
248 bool DOMString::percentage(int &_percentage) const
249 {
250  if (!impl || !impl->l) {
251  return false;
252  }
253 
254  if (*(impl->s + impl->l - 1) != QChar('%')) {
255  return false;
256  }
257 
258  _percentage = QString::fromRawData(impl->s, impl->l - 1).toInt();
259  return true;
260 }
261 
262 QChar *DOMString::unicode() const
263 {
264  if (!impl) {
265  return nullptr;
266  }
267  return impl->unicode();
268 }
269 
270 QString DOMString::string() const
271 {
272  if (!impl) {
273  return QString();
274  }
275 
276  return impl->string();
277 }
278 
279 int DOMString::toInt() const
280 {
281  if (!impl) {
282  return 0;
283  }
284 
285  return impl->toInt();
286 }
287 
288 int DOMString::toInt(bool *ok) const
289 {
290  if (!impl) {
291  *ok = false;
292  return 0;
293  }
294 
295  return impl->toInt(ok);
296 }
297 
298 float DOMString::toFloat(bool *ok) const
299 {
300  if (!impl) {
301  if (ok) {
302  *ok = false;
303  }
304  return 0;
305  }
306  return impl->toFloat(ok);
307 }
308 
309 DOMString DOMString::number(float f)
310 {
311  return DOMString(QString::number(f));
312 }
313 
314 DOMString DOMString::copy() const
315 {
316  if (!impl) {
317  return DOMString();
318  }
319  return impl->copy();
320 }
321 
322 bool DOMString::endsWith(const DOMString &str) const
323 {
324  if (str.length() > length()) {
325  return false;
326  }
327  return impl->endsWith(str.implementation());
328 }
329 
330 bool DOMString::startsWith(const DOMString &str) const
331 {
332  if (str.length() > length()) {
333  return false;
334  }
335  return impl->startsWith(str.implementation());
336 }
337 
338 static inline bool isSpaceCharacter(const ushort &c)
339 {
340  // https://dev.w3.org/html5/spec-LC/common-microsyntaxes.html#space-character
341  return ((c < 0x0021) &&
342  (c == 0x0020 || c == 0x0009 || c == 0x000A || c == 0x000C || c == 0x000D));
343 }
344 
346 {
347  if (!impl || !impl->l) {
348  return *this;
349  }
350 
351  const QChar *s = impl->s;
352  unsigned int start = 0;
353  unsigned int end = impl->l - 1;
354 
355  while ((start <= end) && isSpaceCharacter(s[start].unicode())) {
356  ++start;
357  }
358 
359  if (start > end) {
360  return DOMString("");
361  }
362 
363  while (end && isSpaceCharacter(s[end].unicode())) {
364  --end;
365  }
366 
367  const unsigned int len = end - start + 1;
368  DOMStringImpl *out = new DOMStringImpl(s + start, len);
369 
370  // remove garbage
371  unsigned int newLen = 0;
372  for (unsigned int k = 0; k < len; ++k) {
373  QChar ch = out->s[k];
374  if (ch.unicode() > '\r') {
375  out->s[newLen++] = ch;
376  }
377  }
378  out->l = newLen;
379 
380  return out;
381 }
382 
383 // ------------------------------------------------------------------------
384 
385 bool DOM::strcasecmp(const DOMString &as, const DOMString &bs)
386 {
387  return strcasecmp(as.implementation(), bs.implementation());
388 }
389 
390 bool DOM::strcasecmp(const DOMString &as, const char *bs)
391 {
392  const QChar *a = as.unicode();
393  int l = as.length();
394  if (!bs) {
395  return (l != 0);
396  }
397  while (l--) {
398  if (a->toLatin1() != *bs) {
399  char cc = ((*bs >= 'A') && (*bs <= 'Z')) ? ((*bs) + 'a' - 'A') : (*bs);
400  if (a->toLower().toLatin1() != cc) {
401  return true;
402  }
403  }
404  a++, bs++;
405  }
406  return (*bs != '\0');
407 }
408 
409 bool DOMString::isEmpty() const
410 {
411  return (!impl || impl->l == 0);
412 }
413 
414 DOMString DOMString::format(const char *format, ...)
415 {
416  va_list args;
417  va_start(args, format);
418 
419  Vector<char, 256> buffer;
420 
421  // Do the format once to get the length.
422 #if COMPILER(MSVC)
423  int result = _vscprintf(format, args);
424 #else
425  char ch;
426  int result = qvsnprintf(&ch, 1, format, args);
427  // We need to call va_end() and then va_start() again here, as the
428  // contents of args is undefined after the call to vsnprintf
429  // according to https://man.cx/snprintf(3)
430  //
431  // Not calling va_end/va_start here happens to work on lots of
432  // systems, but fails e.g. on 64bit Linux.
433  va_end(args);
434  va_start(args, format);
435 #endif
436 
437  if (result == 0) {
438  va_end(args);
439  return DOMString("");
440  }
441  if (result < 0) {
442  va_end(args);
443  return DOMString();
444  }
445  unsigned len = result;
446  buffer.grow(len + 1);
447 
448  // Now do the formatting again, guaranteed to fit.
449  qvsnprintf(buffer.data(), buffer.size(), format, args);
450 
451  va_end(args);
452 
453  buffer[len] = 0; // we don't really need this I guess
454  return new DOMStringImpl(buffer.data()/*, len*/);
455 }
456 
457 //-----------------------------------------------------------------------------
458 
459 bool DOM::operator==(const DOMString &a, const DOMString &b)
460 {
461  return !strcmp(a.implementation(), b.implementation());
462 }
463 
464 bool DOM::operator==(const DOMString &a, const QString &b)
465 {
466  int l = a.length();
467 
468  if (l != b.length()) {
469  return false;
470  }
471 
472  if (!memcmp(a.unicode(), b.unicode(), l * sizeof(QChar))) {
473  return true;
474  }
475  return false;
476 }
477 
478 bool DOM::operator==(const DOMString &a, const char *b)
479 {
480  DOMStringImpl *aimpl = a.impl;
481  if (!b) {
482  return !aimpl;
483  }
484 
485  if (aimpl) {
486  int alen = aimpl->l;
487  const QChar *aptr = aimpl->s;
488  while (alen--) {
489  unsigned char c = *b++;
490  if (!c || (*aptr++).unicode() != c) {
491  return false;
492  }
493  }
494  }
495 
496  return !*b;
497 }
DOMString()
default constructor.
Definition: dom_string.h:52
bool isNull() const const
DOMString trimSpaces() const
Returns a string with Space Characters removed from the start and the end.
Definition: dom_string.cpp:345
QString number(int n, int base)
QChar toLower() const const
DOMString & operator+=(const DOMString &str)
append str to this string
Definition: dom_string.cpp:108
This library provides a full-featured HTML parser and widget.
const QChar * unicode() const const
Q_SCRIPTABLE Q_NOREPLY void start()
int length() const const
int toInt(bool *ok, int base) const const
DOMString upper() const
Returns an uppercase version of the string.
Definition: dom_string.cpp:240
DOMString split(unsigned int pos)
Splits the string into two.
Definition: dom_string.cpp:224
const QChar & operator[](unsigned int i) const
The character at position i of the DOMString.
Definition: dom_string.cpp:152
This class implements the basic string we use in the DOM.
Definition: dom_string.h:44
DOMString operator+(const DOMString &str)
add two DOMString's
Definition: dom_string.cpp:128
QString fromRawData(const QChar *unicode, int size)
DOMString lower() const
Returns a lowercase version of the string.
Definition: dom_string.cpp:232
char toLatin1() const const
DOMStringImpl * implementation() const
Definition: dom_string.h:145
ushort unicode() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Sep 28 2023 03:53:39 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.