1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2019 Intel Corporation.
3// Copyright (C) 2019 Mail.ru Group.
4// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
5// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
6
7#ifndef QLATIN1STRINGVIEW_H
8#define QLATIN1STRINGVIEW_H
9
10#include <QtCore/qchar.h>
11#include <QtCore/qcompare.h>
12#include <QtCore/qcontainerfwd.h>
13#include <QtCore/qnamespace.h>
14#include <QtCore/qtversionchecks.h>
15#include <QtCore/qstringview.h>
16
17#if 0
18// Workaround for generating forward headers
19#pragma qt_class(QLatin1String)
20#pragma qt_class(QLatin1StringView)
21#endif
22
23QT_BEGIN_NAMESPACE
24
25class QString;
26
27#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || defined(Q_QDOC)
28# define Q_L1S_VIEW_IS_PRIMARY
29class QLatin1StringView
30#else
31class QLatin1String
32#endif
33{
34public:
35#ifdef Q_L1S_VIEW_IS_PRIMARY
36 constexpr QLatin1StringView() noexcept {}
37 constexpr QLatin1StringView(std::nullptr_t) noexcept : QLatin1StringView() {}
38 constexpr explicit QLatin1StringView(const char *s) noexcept
39 : QLatin1StringView(s, s ? qsizetype(QtPrivate::lengthHelperPointer(s)) : 0) {}
40 constexpr QLatin1StringView(const char *f, const char *l)
41 : QLatin1StringView(f, qsizetype(l - f)) {}
42 constexpr QLatin1StringView(const char *s, qsizetype sz) noexcept : m_data(s), m_size(sz) {}
43 explicit QLatin1StringView(const QByteArray &s) noexcept
44 : QLatin1StringView{s.begin(), s.size()} {}
45 constexpr explicit QLatin1StringView(QByteArrayView s) noexcept
46 : QLatin1StringView(s.constData(), s.size()) {}
47#else
48 constexpr QLatin1String() noexcept : m_size(0), m_data(nullptr) {}
49 Q_WEAK_OVERLOAD
50 constexpr QLatin1String(std::nullptr_t) noexcept : QLatin1String() {}
51 constexpr explicit QLatin1String(const char *s) noexcept
52 : m_size(s ? qsizetype(QtPrivate::lengthHelperPointer(data: s)) : 0), m_data(s) {}
53 constexpr QLatin1String(const char *f, const char *l)
54 : QLatin1String(f, qsizetype(l - f)) {}
55 constexpr QLatin1String(const char *s, qsizetype sz) noexcept : m_size(sz), m_data(s) {}
56 explicit QLatin1String(const QByteArray &s) noexcept : QLatin1String(s.begin(), s.size()) {}
57 constexpr explicit QLatin1String(QByteArrayView s) noexcept : m_size(s.size()), m_data(s.data()) {}
58#endif // !Q_L1S_VIEW_IS_PRIMARY
59
60 inline QString toString() const;
61
62 constexpr const char *latin1() const noexcept { return m_data; }
63 constexpr qsizetype size() const noexcept { return m_size; }
64 constexpr const char *data() const noexcept { return m_data; }
65 [[nodiscard]] constexpr const char *constData() const noexcept { return data(); }
66 [[nodiscard]] constexpr const char *constBegin() const noexcept { return begin(); }
67 [[nodiscard]] constexpr const char *constEnd() const noexcept { return end(); }
68
69 [[nodiscard]] constexpr QLatin1Char first() const { return front(); }
70 [[nodiscard]] constexpr QLatin1Char last() const { return back(); }
71
72 [[nodiscard]] constexpr qsizetype length() const noexcept { return size(); }
73
74 constexpr bool isNull() const noexcept { return !data(); }
75 constexpr bool isEmpty() const noexcept { return !size(); }
76
77 [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
78
79 template <typename...Args>
80 [[nodiscard]] inline QString arg(Args &&...args) const;
81
82 [[nodiscard]] constexpr QLatin1Char at(qsizetype i) const
83 {
84 Q_ASSERT(i >= 0);
85 Q_ASSERT(i < size());
86 return QLatin1Char(m_data[i]);
87 }
88 [[nodiscard]] constexpr QLatin1Char operator[](qsizetype i) const { return at(i); }
89
90 [[nodiscard]] constexpr QLatin1Char front() const { return at(i: 0); }
91 [[nodiscard]] constexpr QLatin1Char back() const { return at(i: size() - 1); }
92
93 [[nodiscard]] int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
94 { return QtPrivate::compareStrings(lhs: *this, rhs: other, cs); }
95 [[nodiscard]] int compare(QLatin1StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
96 { return QtPrivate::compareStrings(lhs: *this, rhs: other, cs); }
97 [[nodiscard]] inline int compare(QUtf8StringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
98 [[nodiscard]] constexpr int compare(QChar c) const noexcept
99 { return isEmpty() ? -1 : front() == c ? int(size() > 1) : uchar(m_data[0]) - c.unicode(); }
100 [[nodiscard]] int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
101 { return QtPrivate::compareStrings(lhs: *this, rhs: QStringView(&c, 1), cs); }
102
103 [[nodiscard]] bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
104 { return QtPrivate::startsWith(haystack: *this, needle: s, cs); }
105 [[nodiscard]] bool startsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
106 { return QtPrivate::startsWith(haystack: *this, needle: s, cs); }
107 [[nodiscard]] constexpr bool startsWith(QChar c) const noexcept
108 { return !isEmpty() && front() == c; }
109 [[nodiscard]] bool startsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
110 { return QtPrivate::startsWith(haystack: *this, needle: QStringView(&c, 1), cs); }
111
112 [[nodiscard]] bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
113 { return QtPrivate::endsWith(haystack: *this, needle: s, cs); }
114 [[nodiscard]] bool endsWith(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
115 { return QtPrivate::endsWith(haystack: *this, needle: s, cs); }
116 [[nodiscard]] constexpr bool endsWith(QChar c) const noexcept
117 { return !isEmpty() && back() == c; }
118 [[nodiscard]] bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
119 { return QtPrivate::endsWith(haystack: *this, needle: QStringView(&c, 1), cs); }
120
121 [[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
122 { return QtPrivate::findString(haystack: *this, from, needle: s, cs); }
123 [[nodiscard]] qsizetype indexOf(QLatin1StringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
124 { return QtPrivate::findString(haystack: *this, from, needle: s, cs); }
125 [[nodiscard]] qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
126 { return QtPrivate::findString(haystack: *this, from, needle: QStringView(&c, 1), cs); }
127
128 [[nodiscard]] bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
129 { return indexOf(s, from: 0, cs) != -1; }
130 [[nodiscard]] bool contains(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
131 { return indexOf(s, from: 0, cs) != -1; }
132 [[nodiscard]] bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
133 { return indexOf(s: QStringView(&c, 1), from: 0, cs) != -1; }
134
135 [[nodiscard]] qsizetype lastIndexOf(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
136 { return lastIndexOf(s, from: size(), cs); }
137 [[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
138 { return QtPrivate::lastIndexOf(haystack: *this, from, needle: s, cs); }
139 [[nodiscard]] qsizetype lastIndexOf(QLatin1StringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
140 { return lastIndexOf(s, from: size(), cs); }
141 [[nodiscard]] qsizetype lastIndexOf(QLatin1StringView s, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
142 { return QtPrivate::lastIndexOf(haystack: *this, from, needle: s, cs); }
143 [[nodiscard]] qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
144 { return lastIndexOf(c, from: -1, cs); }
145 [[nodiscard]] qsizetype lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
146 { return QtPrivate::lastIndexOf(haystack: *this, from, needle: QStringView(&c, 1), cs); }
147
148 [[nodiscard]] qsizetype count(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
149 { return QtPrivate::count(haystack: *this, needle: str, cs); }
150 [[nodiscard]] qsizetype count(QLatin1StringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
151 { return QtPrivate::count(haystack: *this, needle: str, cs); }
152 [[nodiscard]] qsizetype count(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
153 { return QtPrivate::count(haystack: *this, needle: ch, cs); }
154
155 [[nodiscard]] short toShort(bool *ok = nullptr, int base = 10) const
156 { return QtPrivate::toIntegral<short>(data: QByteArrayView(*this), ok, base); }
157 [[nodiscard]] ushort toUShort(bool *ok = nullptr, int base = 10) const
158 { return QtPrivate::toIntegral<ushort>(data: QByteArrayView(*this), ok, base); }
159 [[nodiscard]] int toInt(bool *ok = nullptr, int base = 10) const
160 { return QtPrivate::toIntegral<int>(data: QByteArrayView(*this), ok, base); }
161 [[nodiscard]] uint toUInt(bool *ok = nullptr, int base = 10) const
162 { return QtPrivate::toIntegral<uint>(data: QByteArrayView(*this), ok, base); }
163 [[nodiscard]] long toLong(bool *ok = nullptr, int base = 10) const
164 { return QtPrivate::toIntegral<long>(data: QByteArrayView(*this), ok, base); }
165 [[nodiscard]] ulong toULong(bool *ok = nullptr, int base = 10) const
166 { return QtPrivate::toIntegral<ulong>(data: QByteArrayView(*this), ok, base); }
167 [[nodiscard]] qlonglong toLongLong(bool *ok = nullptr, int base = 10) const
168 { return QtPrivate::toIntegral<qlonglong>(data: QByteArrayView(*this), ok, base); }
169 [[nodiscard]] qulonglong toULongLong(bool *ok = nullptr, int base = 10) const
170 { return QtPrivate::toIntegral<qulonglong>(data: QByteArrayView(*this), ok, base); }
171 [[nodiscard]] float toFloat(bool *ok = nullptr) const
172 {
173 const auto r = QtPrivate::toFloat(a: *this);
174 if (ok)
175 *ok = bool(r);
176 return r.value_or(u: 0.0f);
177 }
178 [[nodiscard]] double toDouble(bool *ok = nullptr) const
179 {
180 const auto r = QtPrivate::toDouble(a: *this);
181 if (ok)
182 *ok = bool(r);
183 return r.value_or(u: 0.0);
184 }
185
186 using value_type = const char;
187 using pointer = value_type*;
188 using const_pointer = pointer;
189 using reference = value_type&;
190 using const_reference = reference;
191 using iterator = value_type*;
192 using const_iterator = iterator;
193 using difference_type = qsizetype; // violates Container concept requirements
194 using size_type = qsizetype; // violates Container concept requirements
195
196 constexpr const_iterator begin() const noexcept { return data(); }
197 constexpr const_iterator cbegin() const noexcept { return data(); }
198 constexpr const_iterator end() const noexcept { return data() + size(); }
199 constexpr const_iterator cend() const noexcept { return data() + size(); }
200
201 using reverse_iterator = std::reverse_iterator<iterator>;
202 using const_reverse_iterator = reverse_iterator;
203
204 const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
205 const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
206 const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
207 const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
208
209 [[nodiscard]] constexpr qsizetype max_size() const noexcept { return maxSize(); }
210
211 [[nodiscard]] static constexpr qsizetype maxSize() noexcept
212 {
213 // -1 to deal with the pointer one-past-the-end;
214 return QtPrivate::MaxAllocSize - 1;
215 }
216
217 [[nodiscard]] constexpr QLatin1StringView mid(qsizetype pos, qsizetype n = -1) const
218 {
219 using namespace QtPrivate;
220 auto result = QContainerImplHelper::mid(originalLength: size(), position: &pos, length: &n);
221 return result == QContainerImplHelper::Null ? QLatin1StringView()
222 : QLatin1StringView(m_data + pos, n);
223 }
224 [[nodiscard]] constexpr QLatin1StringView left(qsizetype n) const
225 {
226 if (size_t(n) >= size_t(size()))
227 n = size();
228 return {m_data, n};
229 }
230 [[nodiscard]] constexpr QLatin1StringView right(qsizetype n) const
231 {
232 if (size_t(n) >= size_t(size()))
233 n = size();
234 return {m_data + m_size - n, n};
235 }
236
237 [[nodiscard]] constexpr QLatin1StringView sliced(qsizetype pos) const
238 { verify(pos, n: 0); return {m_data + pos, m_size - pos}; }
239 [[nodiscard]] constexpr QLatin1StringView sliced(qsizetype pos, qsizetype n) const
240 { verify(pos, n); return {m_data + pos, n}; }
241 [[nodiscard]] constexpr QLatin1StringView first(qsizetype n) const
242 { verify(pos: 0, n); return sliced(pos: 0, n); }
243 [[nodiscard]] constexpr QLatin1StringView last(qsizetype n) const
244 { verify(pos: 0, n); return sliced(pos: size() - n, n); }
245 [[nodiscard]] constexpr QLatin1StringView chopped(qsizetype n) const
246 { verify(pos: 0, n); return sliced(pos: 0, n: size() - n); }
247
248 constexpr QLatin1StringView &slice(qsizetype pos)
249 { *this = sliced(pos); return *this; }
250 constexpr QLatin1StringView &slice(qsizetype pos, qsizetype n)
251 { *this = sliced(pos, n); return *this; }
252
253 constexpr void chop(qsizetype n)
254 { verify(pos: 0, n); m_size -= n; }
255 constexpr void truncate(qsizetype n)
256 { verify(pos: 0, n); m_size = n; }
257
258 [[nodiscard]] QLatin1StringView trimmed() const noexcept { return QtPrivate::trimmed(s: *this); }
259
260 template <typename Needle, typename...Flags>
261 [[nodiscard]] constexpr auto tokenize(Needle &&needle, Flags...flags) const
262 noexcept(noexcept(qTokenize(std::declval<const QLatin1StringView &>(),
263 std::forward<Needle>(needle), flags...)))
264 -> decltype(qTokenize(*this, std::forward<Needle>(needle), flags...))
265 { return qTokenize(*this, std::forward<Needle>(needle), flags...); }
266
267 friend bool comparesEqual(const QLatin1StringView &s1, const QLatin1StringView &s2) noexcept
268 { return s1.size() == s2.size() && QtPrivate::equalStrings(lhs: s1, rhs: s2); }
269 friend Qt::strong_ordering
270 compareThreeWay(const QLatin1StringView &s1, const QLatin1StringView &s2) noexcept
271 {
272 const int res = QtPrivate::compareStrings(lhs: s1, rhs: s2);
273 return Qt::compareThreeWay(lhs: res, rhs: 0);
274 }
275 Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView)
276
277 // QChar <> QLatin1StringView
278 friend bool comparesEqual(const QLatin1StringView &lhs, QChar rhs) noexcept
279 { return lhs.size() == 1 && rhs == lhs.front(); }
280 friend Qt::strong_ordering
281 compareThreeWay(const QLatin1StringView &lhs, QChar rhs) noexcept
282 {
283 // negate, as the helper function expects QChar as lhs
284 const int res = -compare_helper(data1: &rhs, length1: 1, s2: lhs);
285 return Qt::compareThreeWay(lhs: res, rhs: 0);
286 }
287 Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView, QChar)
288
289 // QStringView <> QLatin1StringView
290 friend bool comparesEqual(const QLatin1StringView &lhs, const QStringView &rhs) noexcept
291 { return lhs.size() == rhs.size() && QtPrivate::equalStrings(lhs, rhs); }
292 friend Qt::strong_ordering
293 compareThreeWay(const QLatin1StringView &lhs, const QStringView &rhs) noexcept
294 {
295 const int res = QtPrivate::compareStrings(lhs, rhs);
296 return Qt::compareThreeWay(lhs: res, rhs: 0);
297 }
298 Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView, QStringView)
299
300 // Reversed helper methods for QStringView <> QLatin1StringView comparison.
301 // If we do not provide them explicitly, QStringView <> QByteArrayView
302 // overloads will be selected, which will provide wrong results, because
303 // they will convert from utf-8
304 friend bool comparesEqual(const QStringView &lhs, const QLatin1StringView &rhs) noexcept
305 { return comparesEqual(lhs: rhs, rhs: lhs); }
306 friend Qt::strong_ordering
307 compareThreeWay(const QStringView &lhs, const QLatin1StringView &rhs) noexcept
308 { return QtOrderingPrivate::reversed(o: compareThreeWay(lhs: rhs, rhs: lhs)); }
309
310private:
311 friend bool comparesEqual(const QLatin1StringView &lhs, const QByteArrayView &rhs) noexcept
312 { return equal_helper(s1: lhs, s2: rhs.data(), len: rhs.size()); }
313 friend Qt::strong_ordering
314 compareThreeWay(const QLatin1StringView &lhs, const QByteArrayView &rhs) noexcept
315 {
316 const int res = compare_helper(s1: lhs, s2: rhs.data(), len: rhs.size());
317 return Qt::compareThreeWay(lhs: res, rhs: 0);
318 }
319
320 // Reversed helper methods for QByteArrayView <> QLatin1StringView comparison.
321 // If we do not provide them explicitly, QByteArrayView <> QByteArrayView
322 // overloads will be selected, which will provide wrong results
323 friend bool comparesEqual(const QByteArrayView &lhs, const QLatin1StringView &rhs) noexcept
324 { return comparesEqual(lhs: rhs, rhs: lhs); }
325 friend Qt::strong_ordering
326 compareThreeWay(const QByteArrayView &lhs, const QLatin1StringView &rhs) noexcept
327 { return QtOrderingPrivate::reversed(o: compareThreeWay(lhs: rhs, rhs: lhs)); }
328
329public:
330#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
331 Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView, QByteArrayView, QT_ASCII_CAST_WARN)
332 Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView, QByteArray, QT_ASCII_CAST_WARN)
333 Q_DECLARE_STRONGLY_ORDERED(QLatin1StringView, const char *, QT_ASCII_CAST_WARN)
334#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
335
336private:
337 Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos,
338 [[maybe_unused]] qsizetype n = 1) const
339 {
340 Q_ASSERT(pos >= 0);
341 Q_ASSERT(pos <= size());
342 Q_ASSERT(n >= 0);
343 Q_ASSERT(n <= size() - pos);
344 }
345 static int compare_helper(const QLatin1StringView &s1, const char *s2) noexcept
346 { return compare_helper(s1, s2, len: qstrlen(str: s2)); }
347 Q_CORE_EXPORT static bool equal_helper(QLatin1StringView s1, const char *s2, qsizetype len) noexcept;
348 Q_CORE_EXPORT static int compare_helper(const QLatin1StringView &s1, const char *s2, qsizetype len) noexcept;
349 Q_CORE_EXPORT static int compare_helper(const QChar *data1, qsizetype length1,
350 QLatin1StringView s2,
351 Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
352#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
353 const char *m_data = nullptr;
354 qsizetype m_size = 0;
355#else
356 qsizetype m_size;
357 const char *m_data;
358#endif
359};
360#ifdef Q_L1S_VIEW_IS_PRIMARY
361Q_DECLARE_TYPEINFO(QLatin1StringView, Q_RELOCATABLE_TYPE);
362#else
363Q_DECLARE_TYPEINFO(QLatin1String, Q_RELOCATABLE_TYPE);
364#endif
365
366namespace Qt {
367inline namespace Literals {
368inline namespace StringLiterals {
369
370constexpr inline QLatin1StringView operator""_L1(const char *str, size_t size) noexcept
371{
372 return {str, qsizetype(size)};
373}
374
375} // StringLiterals
376} // Literals
377} // Qt
378
379QT_END_NAMESPACE
380
381#ifdef Q_L1S_VIEW_IS_PRIMARY
382# undef Q_L1S_VIEW_IS_PRIMARY
383#endif
384
385#endif // QLATIN1STRINGVIEW_H
386

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtbase/src/corelib/text/qlatin1stringview.h