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

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