Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qstringbuilder.h
Go to the documentation of this file.
1// Copyright (C) 2020 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#include <QtCore/qstring.h>
5
6#ifndef QSTRINGBUILDER_H
7#define QSTRINGBUILDER_H
8
9#if 0
10// syncqt can not handle the templates in this file, and it doesn't need to
11// process them anyway because they are internal.
12#pragma qt_class(QStringBuilder)
13#pragma qt_sync_stop_processing
14#endif
15
16#include <QtCore/qbytearray.h>
17
18#include <string.h>
19
21
22
24{
25protected:
26 static void convertFromUtf8(QByteArrayView in, QChar *&out) noexcept;
27 static inline void convertFromAscii(char a, QChar *&out) noexcept
28 {
29 *out++ = QLatin1Char(a);
30 }
31 static void appendLatin1To(QLatin1StringView in, QChar *out) noexcept;
32};
33
34template <typename T> struct QConcatenable;
35
36template <typename T>
37using QConcatenableEx = QConcatenable<q20::remove_cvref_t<T>>;
38
39namespace QtStringBuilder {
40 template <typename A, typename B> struct ConvertToTypeHelper
41 { typedef A ConvertTo; };
42 template <typename T> struct ConvertToTypeHelper<T, QString>
43 { typedef QString ConvertTo; };
44
45 template <typename T> using HasIsNull = decltype(std::declval<const T &>().isNull());
46 template <typename T> bool isNull(const T &t)
47 {
48 if constexpr (qxp::is_detected_v<HasIsNull, T>)
49 return t.isNull();
50 else
51 return false;
52 }
53}
54
55template<typename Builder, typename T>
57{
58 T toUpper() const { return resolved().toUpper(); }
59 T toLower() const { return resolved().toLower(); }
60
61protected:
62 T resolved() const { return *static_cast<const Builder*>(this); }
63};
64
65template<typename Builder, typename T>
66struct QStringBuilderBase : public QStringBuilderCommon<Builder, T>
67{
68};
69
70template<typename Builder>
71struct QStringBuilderBase<Builder, QString> : public QStringBuilderCommon<Builder, QString>
72{
73 QByteArray toLatin1() const { return this->resolved().toLatin1(); }
74 QByteArray toUtf8() const { return this->resolved().toUtf8(); }
75 QByteArray toLocal8Bit() const { return this->resolved().toLocal8Bit(); }
76};
77
78template <typename A, typename B>
81 typename QConcatenableEx<A>::ConvertTo,
82 typename QConcatenableEx<B>::ConvertTo
83 >::ConvertTo
84 >
85{
86public:
87 QStringBuilder(A &&a_, B &&b_) : a(std::forward<A>(a_)), b(std::forward<B>(b_)) {}
88
90 QStringBuilder(const QStringBuilder &) = default;
91 ~QStringBuilder() = default;
92
93private:
94 friend class QByteArray;
95 friend class QString;
96 template <typename T> T convertTo() const
97 {
98 if (isNull()) {
99 // appending two null strings must give back a null string,
100 // so we're special casing this one out, QTBUG-114206
101 return T();
102 }
103
104 const qsizetype len = Concatenable::size(*this);
105 T s(len, Qt::Uninitialized);
106
107 // Using data_ptr() here (private API) so we can bypass the
108 // isDetached() and the replacement of a null pointer with _empty in
109 // both QString and QByteArray's data() and constData(). The result is
110 // the same if len != 0.
111 auto d = reinterpret_cast<typename T::iterator>(s.data_ptr().data());
112 const auto start = d;
113 Concatenable::appendTo(*this, d);
114
115 if constexpr (Concatenable::ExactSize) {
116 Q_UNUSED(start)
117 } else {
118 if (len != d - start) {
119 // this resize is necessary since we allocate a bit too much
120 // when dealing with variable sized 8-bit encodings
121 s.resize(d - start);
122 }
123 }
124 return s;
125 }
126
127 typedef QConcatenable<QStringBuilder<A, B> > Concatenable;
128public:
129 typedef typename Concatenable::ConvertTo ConvertTo;
130 operator ConvertTo() const { return convertTo<ConvertTo>(); }
131
132 qsizetype size() const { return Concatenable::size(*this); }
133
134 bool isNull() const
135 {
136 return QtStringBuilder::isNull(a) && QtStringBuilder::isNull(b);
137 }
138
139 A a;
140 B b;
141
142private:
143 QStringBuilder &operator=(QStringBuilder &&) = delete;
144 QStringBuilder &operator=(const QStringBuilder &) = delete;
145};
146
147template <> struct QConcatenable<char> : private QAbstractConcatenable
148{
149 typedef char type;
151 enum { ExactSize = true };
152 static qsizetype size(const char) { return 1; }
153#ifndef QT_NO_CAST_FROM_ASCII
154 QT_ASCII_CAST_WARN static inline void appendTo(const char c, QChar *&out)
155 {
156 QAbstractConcatenable::convertFromAscii(c, out);
157 }
158#endif
159 static inline void appendTo(const char c, char *&out)
160 { *out++ = c; }
161};
162
163template <> struct QConcatenable<QByteArrayView> : private QAbstractConcatenable
164{
165 typedef QByteArrayView type;
166 typedef QByteArray ConvertTo;
167 enum { ExactSize = true };
168 static qsizetype size(QByteArrayView bav) { return bav.size(); }
169#ifndef QT_NO_CAST_FROM_ASCII
170 QT_ASCII_CAST_WARN static inline void appendTo(QByteArrayView bav, QChar *&out)
171 {
172 QAbstractConcatenable::convertFromUtf8(bav, out);
173 }
174#endif
175 static inline void appendTo(QByteArrayView bav, char *&out)
176 {
177 qsizetype n = bav.size();
178 if (n)
179 memcpy(out, bav.data(), n);
180 out += n;
181 }
182};
183
184template <> struct QConcatenable<char16_t> : private QAbstractConcatenable
185{
186 typedef char16_t type;
188 enum { ExactSize = true };
189 static constexpr qsizetype size(char16_t) { return 1; }
190 static inline void appendTo(char16_t c, QChar *&out)
191 { *out++ = c; }
192};
193
194template <> struct QConcatenable<QLatin1Char>
195{
196 typedef QLatin1Char type;
197 typedef QString ConvertTo;
198 enum { ExactSize = true };
199 static qsizetype size(const QLatin1Char) { return 1; }
200 static inline void appendTo(const QLatin1Char c, QChar *&out)
201 { *out++ = c; }
202 static inline void appendTo(const QLatin1Char c, char *&out)
203 { *out++ = c.toLatin1(); }
204};
205
206template <> struct QConcatenable<QChar> : private QAbstractConcatenable
207{
208 typedef QChar type;
209 typedef QString ConvertTo;
210 enum { ExactSize = true };
211 static qsizetype size(const QChar) { return 1; }
212 static inline void appendTo(const QChar c, QChar *&out)
213 { *out++ = c; }
214};
215
216template <> struct QConcatenable<QChar::SpecialCharacter> : private QAbstractConcatenable
217{
218 typedef QChar::SpecialCharacter type;
219 typedef QString ConvertTo;
220 enum { ExactSize = true };
221 static qsizetype size(const QChar::SpecialCharacter) { return 1; }
222 static inline void appendTo(const QChar::SpecialCharacter c, QChar *&out)
223 { *out++ = c; }
224};
225
226template <> struct QConcatenable<QLatin1StringView> : private QAbstractConcatenable
227{
228 typedef QLatin1StringView type;
229 typedef QString ConvertTo;
230 enum { ExactSize = true };
231 static qsizetype size(const QLatin1StringView a) { return a.size(); }
232 static inline void appendTo(const QLatin1StringView a, QChar *&out)
233 {
234 appendLatin1To(a, out);
235 out += a.size();
236 }
237 static inline void appendTo(const QLatin1StringView a, char *&out)
238 {
239 if (const char *data = a.data()) {
240 memcpy(out, data, a.size());
241 out += a.size();
242 }
243 }
244};
245
246template <> struct QConcatenable<QString> : private QAbstractConcatenable
247{
248 typedef QString type;
249 typedef QString ConvertTo;
250 enum { ExactSize = true };
251 static qsizetype size(const QString &a) { return a.size(); }
252 static inline void appendTo(const QString &a, QChar *&out)
253 {
254 const qsizetype n = a.size();
255 if (n)
256 memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
257 out += n;
258 }
259};
260
261template <> struct QConcatenable<QStringView> : private QAbstractConcatenable
262{
263 typedef QStringView type;
264 typedef QString ConvertTo;
265 enum { ExactSize = true };
266 static qsizetype size(QStringView a) { return a.size(); }
267 static inline void appendTo(QStringView a, QChar *&out)
268 {
269 const auto n = a.size();
270 if (n)
271 memcpy(out, a.data(), sizeof(QChar) * n);
272 out += n;
273 }
274};
275
276template <qsizetype N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
277{
278 typedef const char type[N];
280 enum { ExactSize = false };
281 static qsizetype size(const char[N]) { return N - 1; }
282#ifndef QT_NO_CAST_FROM_ASCII
283 QT_ASCII_CAST_WARN static inline void appendTo(const char a[N], QChar *&out)
284 {
285 QAbstractConcatenable::convertFromUtf8(QByteArrayView(a, N - 1), out);
286 }
287#endif
288 static inline void appendTo(const char a[N], char *&out)
289 {
290 while (*a)
291 *out++ = *a++;
292 }
293};
294
295template <qsizetype N> struct QConcatenable<char[N]> : QConcatenable<const char[N]>
296{
297 typedef char type[N];
298};
299
300template <> struct QConcatenable<const char *> : private QAbstractConcatenable
301{
302 typedef const char *type;
304 enum { ExactSize = false };
305 static qsizetype size(const char *a) { return qstrlen(a); }
306#ifndef QT_NO_CAST_FROM_ASCII
307 QT_ASCII_CAST_WARN static inline void appendTo(const char *a, QChar *&out)
308 { QAbstractConcatenable::convertFromUtf8(QByteArrayView(a), out); }
309#endif
310 static inline void appendTo(const char *a, char *&out)
311 {
312 if (!a)
313 return;
314 while (*a)
315 *out++ = *a++;
316 }
317};
318
319template <> struct QConcatenable<char *> : QConcatenable<const char*>
320{
321 typedef char *type;
322};
323
324template <qsizetype N> struct QConcatenable<const char16_t[N]> : private QAbstractConcatenable
325{
326 using type = const char16_t[N];
327 using ConvertTo = QString;
328 enum { ExactSize = true };
329 static qsizetype size(const char16_t[N]) { return N - 1; }
330 static void appendTo(const char16_t a[N], QChar *&out)
331 {
332 memcpy(static_cast<void *>(out), a, (N - 1) * sizeof(char16_t));
333 out += N - 1;
334 }
335};
336
337template <qsizetype N> struct QConcatenable<char16_t[N]> : QConcatenable<const char16_t[N]>
338{
339 using type = char16_t[N];
340};
341
342template <> struct QConcatenable<const char16_t *> : private QAbstractConcatenable
343{
344 using type = const char16_t *;
345 using ConvertTo = QString;
346 enum { ExactSize = true };
347 static qsizetype size(const char16_t *a) { return QStringView(a).size(); }
348 QT_ASCII_CAST_WARN static inline void appendTo(const char16_t *a, QChar *&out)
349 {
350 if (!a)
351 return;
352 while (*a)
353 *out++ = *a++;
354 }
355};
356
357template <> struct QConcatenable<char16_t *> : QConcatenable<const char16_t*>
358{
359 typedef char16_t *type;
360};
361
362template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
363{
364 typedef QByteArray type;
365 typedef QByteArray ConvertTo;
366 enum { ExactSize = false };
367 static qsizetype size(const QByteArray &ba) { return ba.size(); }
368#ifndef QT_NO_CAST_FROM_ASCII
369 QT_ASCII_CAST_WARN static inline void appendTo(const QByteArray &ba, QChar *&out)
370 {
371 QAbstractConcatenable::convertFromUtf8(ba, out);
372 }
373#endif
374 static inline void appendTo(const QByteArray &ba, char *&out)
375 {
376 const qsizetype n = ba.size();
377 if (n)
378 memcpy(out, ba.begin(), n);
379 out += n;
380 }
381};
382
383
384template <typename A, typename B>
385struct QConcatenable< QStringBuilder<A, B> >
386{
387 typedef QStringBuilder<A, B> type;
388 using ConvertTo = typename QtStringBuilder::ConvertToTypeHelper<
389 typename QConcatenableEx<A>::ConvertTo,
390 typename QConcatenableEx<B>::ConvertTo
391 >::ConvertTo;
392 enum { ExactSize = QConcatenableEx<A>::ExactSize && QConcatenableEx<B>::ExactSize };
393 static qsizetype size(const type &p)
394 {
395 return QConcatenableEx<A>::size(p.a) + QConcatenableEx<B>::size(p.b);
396 }
397 template<typename T> static inline void appendTo(const type &p, T *&out)
398 {
399 QConcatenableEx<A>::appendTo(p.a, out);
400 QConcatenableEx<B>::appendTo(p.b, out);
401 }
402};
403
404template <typename A, typename B,
405 typename = std::void_t<typename QConcatenableEx<A>::type, typename QConcatenableEx<B>::type>>
406auto operator%(A &&a, B &&b)
407{
408 return QStringBuilder<A, B>(std::forward<A>(a), std::forward<B>(b));
409}
410
411// QT_USE_FAST_OPERATOR_PLUS was introduced in 4.7, QT_USE_QSTRINGBUILDER is to be used from 4.8 onwards
412// QT_USE_FAST_OPERATOR_PLUS does not remove the normal operator+ for QByteArray
413#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
414template <typename A, typename B,
415 typename = std::void_t<typename QConcatenableEx<A>::type, typename QConcatenableEx<B>::type>>
416auto operator+(A &&a, B &&b)
417{
418 return std::forward<A>(a) % std::forward<B>(b);
419}
420#endif
421
422namespace QtStringBuilder {
423template <typename A, typename B>
424QByteArray &appendToByteArray(QByteArray &a, const QStringBuilder<A, B> &b, char)
425{
426 // append 8-bit data to a byte array
427 qsizetype len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
428 a.detach(); // a detach() in a.data() could reset a.capacity() to a.size()
429 if (len > a.data_ptr().freeSpaceAtEnd()) // capacity() was broken when prepend()-optimization landed
430 a.reserve(qMax(len, 2 * a.capacity()));
431 char *it = a.data() + a.size();
432 QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
433 a.resize(len); //we need to resize after the appendTo for the case str+=foo+str
434 return a;
435}
436
437#ifndef QT_NO_CAST_TO_ASCII
438template <typename A, typename B>
439QByteArray &appendToByteArray(QByteArray &a, const QStringBuilder<A, B> &b, QChar)
440{
441 return a += QString(b).toUtf8();
442}
443#endif
444}
445
446template <typename A, typename B>
447QByteArray &operator+=(QByteArray &a, const QStringBuilder<A, B> &b)
448{
449 return QtStringBuilder::appendToByteArray(a, b,
450 typename QConcatenable< QStringBuilder<A, B> >::ConvertTo::value_type());
451}
452
453template <typename A, typename B>
454QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
455{
456 qsizetype len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
457 a.detach(); // a detach() in a.data() could reset a.capacity() to a.size()
458 if (len > a.data_ptr().freeSpaceAtEnd()) // capacity() was broken when prepend()-optimization landed
459 a.reserve(qMax(len, 2 * a.capacity()));
460 QChar *it = a.data() + a.size();
461 QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
462 // we need to resize after the appendTo for the case str+=foo+str
463 a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
464 return a;
465}
466
467QT_END_NAMESPACE
468
469#endif // QSTRINGBUILDER_H
\inmodule QtCore\reentrant
Definition qdatastream.h:47
\inmodule QtCore
Definition qdirlisting.h:61
QDateTime birthTime(const QTimeZone &tz) const
Definition qdirlisting.h:86
QDateTime metadataChangeTime(const QTimeZone &tz) const
Definition qdirlisting.h:88
Q_CORE_EXPORT bool isReadable() const
Q_CORE_EXPORT bool isHidden() const
Q_CORE_EXPORT bool isWritable() const
Q_CORE_EXPORT bool isExecutable() const
Q_CORE_EXPORT bool isFile() const
Q_CORE_EXPORT bool exists() const
Q_CORE_EXPORT bool isSymLink() const
Q_CORE_EXPORT bool isDir() const
QDateTime lastRead(const QTimeZone &tz) const
See the QFileInfo methods with the same names.
Definition qdirlisting.h:92
QDateTime lastModified(const QTimeZone &tz) const
Definition qdirlisting.h:90
const_iterator(const_iterator &&) noexcept=default
reference operator*() const
Returns a {const QDirListing::DirEntry &} of the directory entry this iterator points to.
friend bool operator==(sentinel, const const_iterator &rhs) noexcept
const_iterator & operator=(const_iterator &&) noexcept=default
pointer operator->() const
Returns a {const QDirListing::DirEntry *} to the directory entry this iterator points to.
friend bool operator!=(sentinel, const const_iterator &rhs) noexcept
friend bool operator!=(const const_iterator &lhs, sentinel) noexcept
const_iterator & operator++()
Pre-increment operator.
friend bool operator==(const const_iterator &lhs, sentinel) noexcept
\typealias QDirListing::const_iterator::reference
Definition qdirlisting.h:98
friend constexpr bool operator==(sentinel, sentinel) noexcept
Definition qdirlisting.h:99
friend constexpr bool operator!=(sentinel, sentinel) noexcept
sentinel cend() const
IteratorFlag
This enum class describes flags that can be used to configure the behavior of QDirListing.
Definition qdirlisting.h:27
const_iterator cbegin() const
QDirListing(QDirListing &&other) noexcept
Definition qdirlisting.h:48
const_iterator constBegin() const
sentinel constEnd() const
sentinel end() const
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qpoint.h:217
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore
bool isNull() const
QStringBuilder(A &&a_, B &&b_)
Concatenable::ConvertTo ConvertTo
operator ConvertTo() const
QStringBuilder(QStringBuilder &&)=default
QStringBuilder(const QStringBuilder &)=default
qsizetype size() const
~QStringBuilder()=default
Emulated const pointer to QVariant based on a pointer.
Definition qvariant.h:859
QVariantPointer is a template class that emulates a pointer to QVariant based on a pointer.
Definition qvariant.h:872
QVariantPointer(const Pointer *pointer)
Constructs a QVariantPointer from the given pointer.
Definition qvariant.h:877
QVariantRef< Pointer > operator*() const
Dereferences the QVariantPointer to a QVariantRef.
Definition qvariant.h:878
Pointer operator->() const
Dereferences and returns the pointer.
Definition qvariant.h:879
The QVariantRef acts as a non-const reference to a QVariant.
Definition qvariant.h:835
operator QVariant() const
Resolves the QVariantRef to an actual QVariant.
QVariantRef & operator=(const QVariantRef &value)
Assigns a new value to the value pointed to by the pointer this QVariantRef refers to.
Definition qvariant.h:847
QVariantRef & operator=(const QVariant &value)
Assigns a new value to the value pointed to by the pointer this QVariantRef refers to.
~QVariantRef()=default
QVariantRef(const QVariantRef &)=default
QVariantRef(QVariantRef &&)=default
friend void swap(QVariantRef a, QVariantRef b)
Definition qvariant.h:850
QVariantRef & operator=(QVariantRef &&value)
Assigns a new value to the value pointed to by the pointer this QVariantRef refers to.
Definition qvariant.h:848
QVariantRef(const Pointer *reference)
Creates a QVariantRef from an pointer.
Definition qvariant.h:840
\inmodule QtCore
Definition qvariant.h:65
Combined button and popup list for selecting options.
\macro QT_NO_KEYWORDS >
Definition qcompare.h:24
bool isNull(const T &t)
QByteArray & appendToByteArray(QByteArray &a, const QStringBuilder< A, B > &b, QChar)
QByteArray & appendToByteArray(QByteArray &a, const QStringBuilder< A, B > &b, char)
static QString appendSlashIfNeeded(const QString &path)
QByteArray & operator+=(QByteArray &a, const QStringBuilder< A, B > &b)
#define Q_MK_GET(cvref)
Definition qvariant.h:647
T qvariant_cast(QVariant &&v)
Definition qvariant.h:770
T qvariant_cast(const QVariant &)
Definition qvariant.h:753
void swap(QVariant &value1, QVariant &value2) noexcept
Definition qvariant.h:748
static void appendTo(const type &p, T *&out)
static qsizetype size(const type &p)
static void appendTo(char16_t c, QChar *&out)
static constexpr qsizetype size(char16_t)
static QT_ASCII_CAST_WARN void appendTo(const char c, QChar *&out)
static qsizetype size(const char)
static void appendTo(const char c, char *&out)
static QT_ASCII_CAST_WARN void appendTo(const char16_t *a, QChar *&out)
static qsizetype size(const char16_t *a)
static qsizetype size(const char16_t[N])
static void appendTo(const char16_t a[N], QChar *&out)
static QT_ASCII_CAST_WARN void appendTo(const char *a, QChar *&out)
static void appendTo(const char *a, char *&out)
static qsizetype size(const char *a)
static void appendTo(const char a[N], char *&out)
static qsizetype size(const char[N])
static QT_ASCII_CAST_WARN void appendTo(const char a[N], QChar *&out)