1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QHASHEDSTRING_P_H
41#define QHASHEDSTRING_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtCore/qglobal.h>
55#include <QtCore/qstring.h>
56#include <private/qv4string_p.h>
57
58#include <private/qflagpointer_p.h>
59
60#if defined(Q_OS_QNX)
61#include <stdlib.h>
62#endif
63
64QT_BEGIN_NAMESPACE
65
66class QHashedStringRef;
67class Q_QML_PRIVATE_EXPORT QHashedString : public QString
68{
69public:
70 inline QHashedString();
71 inline QHashedString(const QString &string);
72 inline QHashedString(const QString &string, quint32);
73 inline QHashedString(const QHashedString &string);
74
75 inline QHashedString &operator=(const QHashedString &string);
76 inline bool operator==(const QHashedString &string) const;
77 inline bool operator==(const QHashedStringRef &string) const;
78
79 inline quint32 hash() const;
80 inline quint32 existingHash() const;
81
82 static bool compare(const QChar *lhs, const QChar *rhs, int length);
83 static inline bool compare(const QChar *lhs, const char *rhs, int length);
84 static inline bool compare(const char *lhs, const char *rhs, int length);
85
86 static inline quint32 stringHash(const QChar* data, int length);
87 static inline quint32 stringHash(const char *data, int length);
88
89private:
90 friend class QHashedStringRef;
91 friend class QStringHashNode;
92
93 inline void computeHash() const;
94 mutable quint32 m_hash = 0;
95};
96
97class QHashedCStringRef;
98class Q_QML_PRIVATE_EXPORT QHashedStringRef
99{
100public:
101 inline QHashedStringRef();
102 inline QHashedStringRef(const QString &);
103 inline QHashedStringRef(const QStringRef &);
104 inline QHashedStringRef(const QChar *, int);
105 inline QHashedStringRef(const QChar *, int, quint32);
106 inline QHashedStringRef(const QHashedString &);
107 inline QHashedStringRef(const QHashedStringRef &);
108 inline QHashedStringRef &operator=(const QHashedStringRef &);
109
110 inline bool operator==(const QString &string) const;
111 inline bool operator==(const QHashedString &string) const;
112 inline bool operator==(const QHashedStringRef &string) const;
113 inline bool operator==(const QHashedCStringRef &string) const;
114 inline bool operator!=(const QString &string) const;
115 inline bool operator!=(const QHashedString &string) const;
116 inline bool operator!=(const QHashedStringRef &string) const;
117 inline bool operator!=(const QHashedCStringRef &string) const;
118
119 inline quint32 hash() const;
120
121 inline QChar *data();
122 inline const QChar &at(int) const;
123 inline const QChar *constData() const;
124 bool startsWith(const QString &) const;
125 bool endsWith(const QString &) const;
126 int indexOf(const QChar &, int from=0) const;
127 QHashedStringRef mid(int, int) const;
128 QVector<QHashedStringRef> split(const QChar sep) const;
129
130 inline bool isEmpty() const;
131 inline int length() const;
132 inline bool startsWithUpper() const;
133
134 QString toString() const;
135
136 inline bool isLatin1() const;
137
138private:
139 friend class QHashedString;
140
141 inline void computeHash() const;
142
143 const QChar *m_data = nullptr;
144 int m_length = 0;
145 mutable quint32 m_hash = 0;
146};
147
148class Q_AUTOTEST_EXPORT QHashedCStringRef
149{
150public:
151 inline QHashedCStringRef();
152 inline QHashedCStringRef(const char *, int);
153 inline QHashedCStringRef(const char *, int, quint32);
154 inline QHashedCStringRef(const QHashedCStringRef &);
155
156 inline quint32 hash() const;
157
158 inline const char *constData() const;
159 inline int length() const;
160
161 QString toUtf16() const;
162 inline int utf16length() const;
163 inline void writeUtf16(QChar *) const;
164 inline void writeUtf16(quint16 *) const;
165private:
166 friend class QHashedStringRef;
167
168 inline void computeHash() const;
169
170 const char *m_data = nullptr;
171 int m_length = 0;
172 mutable quint32 m_hash = 0;
173};
174
175inline uint qHash(const QHashedString &string)
176{
177 return uint(string.hash());
178}
179
180inline uint qHash(const QHashedStringRef &string)
181{
182 return uint(string.hash());
183}
184
185QHashedString::QHashedString()
186: QString()
187{
188}
189
190QHashedString::QHashedString(const QString &string)
191: QString(string), m_hash(0)
192{
193}
194
195QHashedString::QHashedString(const QString &string, quint32 hash)
196: QString(string), m_hash(hash)
197{
198}
199
200QHashedString::QHashedString(const QHashedString &string)
201: QString(string), m_hash(string.m_hash)
202{
203}
204
205QHashedString &QHashedString::operator=(const QHashedString &string)
206{
207 static_cast<QString &>(*this) = string;
208 m_hash = string.m_hash;
209 return *this;
210}
211
212bool QHashedString::operator==(const QHashedString &string) const
213{
214 return (string.m_hash == m_hash || !string.m_hash || !m_hash) &&
215 static_cast<const QString &>(*this) == static_cast<const QString &>(string);
216}
217
218bool QHashedString::operator==(const QHashedStringRef &string) const
219{
220 return length() == string.m_length &&
221 (string.m_hash == m_hash || !string.m_hash || !m_hash) &&
222 QHashedString::compare(lhs: constData(), rhs: string.m_data, length: string.m_length);
223}
224
225quint32 QHashedString::hash() const
226{
227 if (!m_hash) computeHash();
228 return m_hash;
229}
230
231quint32 QHashedString::existingHash() const
232{
233 return m_hash;
234}
235
236QHashedStringRef::QHashedStringRef()
237{
238}
239
240QHashedStringRef::QHashedStringRef(const QString &str)
241: m_data(str.constData()), m_length(str.length()), m_hash(0)
242{
243}
244
245QHashedStringRef::QHashedStringRef(const QStringRef &str)
246: m_data(str.constData()), m_length(str.length()), m_hash(0)
247{
248}
249
250QHashedStringRef::QHashedStringRef(const QChar *data, int length)
251: m_data(data), m_length(length), m_hash(0)
252{
253}
254
255QHashedStringRef::QHashedStringRef(const QChar *data, int length, quint32 hash)
256: m_data(data), m_length(length), m_hash(hash)
257{
258}
259
260QHashedStringRef::QHashedStringRef(const QHashedString &string)
261: m_data(string.constData()), m_length(string.length()), m_hash(string.m_hash)
262{
263}
264
265QHashedStringRef::QHashedStringRef(const QHashedStringRef &string)
266: m_data(string.m_data), m_length(string.m_length), m_hash(string.m_hash)
267{
268}
269
270QHashedStringRef &QHashedStringRef::operator=(const QHashedStringRef &o)
271{
272 m_data = o.m_data;
273 m_length = o.m_length;
274 m_hash = o.m_hash;
275 return *this;
276}
277
278bool QHashedStringRef::operator==(const QString &string) const
279{
280 return m_length == string.length() &&
281 QHashedString::compare(lhs: string.constData(), rhs: m_data, length: m_length);
282}
283
284bool QHashedStringRef::operator==(const QHashedString &string) const
285{
286 return m_length == string.length() &&
287 (m_hash == string.m_hash || !m_hash || !string.m_hash) &&
288 QHashedString::compare(lhs: string.constData(), rhs: m_data, length: m_length);
289}
290
291bool QHashedStringRef::operator==(const QHashedStringRef &string) const
292{
293 return m_length == string.m_length &&
294 (m_hash == string.m_hash || !m_hash || !string.m_hash) &&
295 QHashedString::compare(lhs: string.m_data, rhs: m_data, length: m_length);
296}
297
298bool QHashedStringRef::operator==(const QHashedCStringRef &string) const
299{
300 return m_length == string.m_length &&
301 (m_hash == string.m_hash || !m_hash || !string.m_hash) &&
302 QHashedString::compare(lhs: m_data, rhs: string.m_data, length: m_length);
303}
304
305bool QHashedStringRef::operator!=(const QString &string) const
306{
307 return m_length != string.length() ||
308 !QHashedString::compare(lhs: string.constData(), rhs: m_data, length: m_length);
309}
310
311bool QHashedStringRef::operator!=(const QHashedString &string) const
312{
313 return m_length != string.length() ||
314 (m_hash != string.m_hash && m_hash && string.m_hash) ||
315 !QHashedString::compare(lhs: string.constData(), rhs: m_data, length: m_length);
316}
317
318bool QHashedStringRef::operator!=(const QHashedStringRef &string) const
319{
320 return m_length != string.m_length ||
321 (m_hash != string.m_hash && m_hash && string.m_hash) ||
322 QHashedString::compare(lhs: string.m_data, rhs: m_data, length: m_length);
323}
324
325bool QHashedStringRef::operator!=(const QHashedCStringRef &string) const
326{
327 return m_length != string.m_length ||
328 (m_hash != string.m_hash && m_hash && string.m_hash) ||
329 QHashedString::compare(lhs: m_data, rhs: string.m_data, length: m_length);
330}
331
332QChar *QHashedStringRef::data()
333{
334 return const_cast<QChar *>(m_data);
335}
336
337const QChar &QHashedStringRef::at(int index) const
338{
339 Q_ASSERT(index < m_length);
340 return m_data[index];
341}
342
343const QChar *QHashedStringRef::constData() const
344{
345 return m_data;
346}
347
348bool QHashedStringRef::isEmpty() const
349{
350 return m_length == 0;
351}
352
353int QHashedStringRef::length() const
354{
355 return m_length;
356}
357
358bool QHashedStringRef::isLatin1() const
359{
360 for (int ii = 0; ii < m_length; ++ii)
361 if (m_data[ii].unicode() > 127) return false;
362 return true;
363}
364
365void QHashedStringRef::computeHash() const
366{
367 m_hash = QHashedString::stringHash(data: m_data, length: m_length);
368}
369
370bool QHashedStringRef::startsWithUpper() const
371{
372 if (m_length < 1) return false;
373 return m_data[0].isUpper();
374}
375
376quint32 QHashedStringRef::hash() const
377{
378 if (!m_hash) computeHash();
379 return m_hash;
380}
381
382QHashedCStringRef::QHashedCStringRef()
383{
384}
385
386QHashedCStringRef::QHashedCStringRef(const char *data, int length)
387: m_data(data), m_length(length), m_hash(0)
388{
389}
390
391QHashedCStringRef::QHashedCStringRef(const char *data, int length, quint32 hash)
392: m_data(data), m_length(length), m_hash(hash)
393{
394}
395
396QHashedCStringRef::QHashedCStringRef(const QHashedCStringRef &o)
397: m_data(o.m_data), m_length(o.m_length), m_hash(o.m_hash)
398{
399}
400
401quint32 QHashedCStringRef::hash() const
402{
403 if (!m_hash) computeHash();
404 return m_hash;
405}
406
407const char *QHashedCStringRef::constData() const
408{
409 return m_data;
410}
411
412int QHashedCStringRef::length() const
413{
414 return m_length;
415}
416
417int QHashedCStringRef::utf16length() const
418{
419 return m_length;
420}
421
422void QHashedCStringRef::writeUtf16(QChar *output) const
423{
424 writeUtf16((quint16 *)output);
425}
426
427void QHashedCStringRef::writeUtf16(quint16 *output) const
428{
429 int l = m_length;
430 const char *d = m_data;
431 while (l--)
432 *output++ = *d++;
433}
434
435void QHashedCStringRef::computeHash() const
436{
437 m_hash = QHashedString::stringHash(data: m_data, length: m_length);
438}
439
440bool QHashedString::compare(const QChar *lhs, const char *rhs, int length)
441{
442 Q_ASSERT(lhs && rhs);
443 const quint16 *l = (const quint16*)lhs;
444 while (length--)
445 if (*l++ != *rhs++) return false;
446 return true;
447}
448
449bool QHashedString::compare(const char *lhs, const char *rhs, int length)
450{
451 Q_ASSERT(lhs && rhs);
452 return 0 == ::memcmp(s1: lhs, s2: rhs, n: length);
453}
454
455quint32 QHashedString::stringHash(const QChar *data, int length)
456{
457 return QV4::String::createHashValue(ch: data, length, subtype: nullptr);
458}
459
460quint32 QHashedString::stringHash(const char *data, int length)
461{
462 return QV4::String::createHashValue(ch: data, length, subtype: nullptr);
463}
464
465void QHashedString::computeHash() const
466{
467 m_hash = stringHash(data: constData(), length: length());
468}
469
470QT_END_NAMESPACE
471
472#endif // QHASHEDSTRING_P_H
473

source code of qtdeclarative/src/qml/qml/ftw/qhashedstring_p.h