Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
23struct Q_CORE_EXPORT QAbstractConcatenable
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>
79class QStringBuilder : public QStringBuilderBase<QStringBuilder<A, B>,
80 typename QtStringBuilder::ConvertToTypeHelper<
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);
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;
114
115 if constexpr (Concatenable::ExactSize) {
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:
130 operator ConvertTo() const { return convertTo<ConvertTo>(); }
131
132 qsizetype size() const { return Concatenable::size(*this); }
133
134 bool isNull() const
135 {
137 }
138
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 {
157 }
158#endif
159 static inline void appendTo(const char c, char *&out)
160 { *out++ = c; }
161};
162
164{
167 enum { ExactSize = true };
168 static qsizetype size(QByteArrayView bav) { return bav.size(); }
169#ifndef QT_NO_CAST_FROM_ASCII
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{
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;
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;
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
227{
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;
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
262{
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 {
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
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];
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 *;
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{
366 enum { ExactSize = false };
367 static qsizetype size(const QByteArray &ba) { return ba.size(); }
368#ifndef QT_NO_CAST_FROM_ASCII
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>
386{
387 typedef QStringBuilder<A, B> type;
391 >::ConvertTo;
393 static qsizetype size(const type &p)
394 {
396 }
397 template<typename T> static inline void appendTo(const type &p, T *&out)
398 {
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{
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
468
469#endif // QSTRINGBUILDER_H
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:494
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first byte in the byte-array.
Definition qbytearray.h:443
\inmodule QtCore
qsizetype size() const
Definition qset.h:50
\inmodule QtCore
bool isNull() const
QStringBuilder(A &&a_, B &&b_)
QStringBuilder(QStringBuilder &&)=default
QStringBuilder(const QStringBuilder &)=default
qsizetype size() const
~QStringBuilder()=default
Concatenable::ConvertTo ConvertTo
\inmodule QtCore
Definition qstringview.h:78
constexpr qsizetype size() const noexcept
Returns the size of this string view, in UTF-16 code units (that is, surrogate pairs count as two for...
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:994
QByteArray toUtf8() const &
Definition qstring.h:634
QSet< QString >::iterator it
Combined button and popup list for selecting options.
decltype(std::declval< const T & >().isNull()) HasIsNull
bool isNull(const T &t)
QByteArray & appendToByteArray(QByteArray &a, const QStringBuilder< A, B > &b, char)
constexpr Initialization Uninitialized
size_t qstrlen(const char *str)
constexpr timespec operator+(const timespec &t1, const timespec &t2)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
n varying highp vec2 A
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLuint start
GLfloat n
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint in
GLfloat GLfloat p
[1]
GLenum GLsizei len
QConcatenable< q20::remove_cvref_t< T > > QConcatenableEx
QByteArray & operator+=(QByteArray &a, const QStringBuilder< A, B > &b)
auto operator%(A &&a, B &&b)
#define QT_ASCII_CAST_WARN
#define Q_UNUSED(x)
ptrdiff_t qsizetype
Definition qtypes.h:165
QByteArray ba
[0]
QTextStream out(stdout)
[7]
static void convertFromAscii(char a, QChar *&out) noexcept
static void convertFromUtf8(QByteArrayView in, QChar *&out) noexcept
static QT_ASCII_CAST_WARN void appendTo(QByteArrayView bav, QChar *&out)
static void appendTo(QByteArrayView bav, char *&out)
static qsizetype size(QByteArrayView bav)
static void appendTo(const QByteArray &ba, char *&out)
static QT_ASCII_CAST_WARN void appendTo(const QByteArray &ba, QChar *&out)
static qsizetype size(const QByteArray &ba)
static void appendTo(const QChar c, QChar *&out)
static qsizetype size(const QChar)
static qsizetype size(const QChar::SpecialCharacter)
static void appendTo(const QChar::SpecialCharacter c, QChar *&out)
static void appendTo(const QLatin1Char c, QChar *&out)
static qsizetype size(const QLatin1Char)
static void appendTo(const QLatin1Char c, char *&out)
static void appendTo(const QLatin1StringView a, QChar *&out)
static qsizetype size(const QLatin1StringView a)
static void appendTo(const QLatin1StringView a, char *&out)
static void appendTo(const type &p, T *&out)
static qsizetype size(const type &p)
typename QtStringBuilder::ConvertToTypeHelper< typename QConcatenableEx< A >::ConvertTo, typename QConcatenableEx< B >::ConvertTo >::ConvertTo ConvertTo
static qsizetype size(QStringView a)
static void appendTo(QStringView a, QChar *&out)
static qsizetype size(const QString &a)
static void appendTo(const QString &a, QChar *&out)
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)
\inmodule QtCore \reentrant
Definition qchar.h:18