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