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#include "qhashedstring_p.h"
41
42QT_BEGIN_NAMESPACE
43
44// Copy of QString's qMemCompare
45bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length)
46{
47 Q_ASSERT(lhs && rhs);
48 const quint16 *a = (const quint16 *)lhs;
49 const quint16 *b = (const quint16 *)rhs;
50
51 if (a == b || !length)
52 return true;
53
54 union {
55 const quint16 *w;
56 const quint32 *d;
57 quintptr value;
58 } sa, sb;
59 sa.w = a;
60 sb.w = b;
61
62 // check alignment
63 if ((sa.value & 2) == (sb.value & 2)) {
64 // both addresses have the same alignment
65 if (sa.value & 2) {
66 // both addresses are not aligned to 4-bytes boundaries
67 // compare the first character
68 if (*sa.w != *sb.w)
69 return false;
70 --length;
71 ++sa.w;
72 ++sb.w;
73
74 // now both addresses are 4-bytes aligned
75 }
76
77 // both addresses are 4-bytes aligned
78 // do a fast 32-bit comparison
79 const quint32 *e = sa.d + (length >> 1);
80 for ( ; sa.d != e; ++sa.d, ++sb.d) {
81 if (*sa.d != *sb.d)
82 return false;
83 }
84
85 // do we have a tail?
86 return (length & 1) ? *sa.w == *sb.w : true;
87 } else {
88 // one of the addresses isn't 4-byte aligned but the other is
89 const quint16 *e = sa.w + length;
90 for ( ; sa.w != e; ++sa.w, ++sb.w) {
91 if (*sa.w != *sb.w)
92 return false;
93 }
94 }
95 return true;
96}
97
98QHashedStringRef QHashedStringRef::mid(int offset, int length) const
99{
100 Q_ASSERT(offset < m_length);
101 return QHashedStringRef(m_data + offset,
102 (length == -1 || (offset + length) > m_length)?(m_length - offset):length);
103}
104
105QVector<QHashedStringRef> QHashedStringRef::split(const QChar sep) const
106{
107 QVector<QHashedStringRef> ret;
108 auto curLength = 0;
109 auto curOffset = m_data;
110 for (int offset = 0; offset < m_length; ++offset) {
111 if (*(m_data + offset) == sep) {
112 ret.push_back(t: {curOffset, curLength});
113 curOffset = m_data + offset + 1;
114 curLength = 0;
115 } else {
116 ++curLength;
117 }
118 }
119 if (curLength > 0)
120 ret.push_back(t: {curOffset, curLength});
121 return ret;
122}
123
124bool QHashedStringRef::endsWith(const QString &s) const
125{
126 return s.length() < m_length &&
127 QHashedString::compare(lhs: s.constData(), rhs: m_data + m_length - s.length(), length: s.length());
128}
129
130bool QHashedStringRef::startsWith(const QString &s) const
131{
132 return s.length() < m_length &&
133 QHashedString::compare(lhs: s.constData(), rhs: m_data, length: s.length());
134}
135
136static int findChar(const QChar *str, int len, QChar ch, int from)
137{
138 const ushort *s = (const ushort *)str;
139 ushort c = ch.unicode();
140 if (from < 0)
141 from = qMax(a: from + len, b: 0);
142 if (from < len) {
143 const ushort *n = s + from - 1;
144 const ushort *e = s + len;
145 while (++n != e)
146 if (*n == c)
147 return n - s;
148 }
149 return -1;
150}
151
152int QHashedStringRef::indexOf(const QChar &c, int from) const
153{
154 return findChar(str: m_data, len: m_length, ch: c, from);
155}
156
157QString QHashedStringRef::toString() const
158{
159 if (m_length == 0)
160 return QString();
161 return QString(m_data, m_length);
162}
163
164QString QHashedCStringRef::toUtf16() const
165{
166 if (m_length == 0)
167 return QString();
168
169 QString rv;
170 rv.resize(size: m_length);
171 writeUtf16(output: (quint16*)rv.data());
172 return rv;
173}
174
175QT_END_NAMESPACE
176

source code of qtdeclarative/src/qml/qml/ftw/qhashedstring.cpp