Qt 6.x
The Qt SDK
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#ifndef QSTRINGBUILDER_H
5#define QSTRINGBUILDER_H
6
7#if 0
8// syncqt can not handle the templates in this file, and it doesn't need to
9// process them anyway because they are internal.
10#pragma qt_class(QStringBuilder)
11#pragma qt_sync_stop_processing
12#endif
13
14#include <QtCore/qstring.h>
15#include <QtCore/qbytearray.h>
16
17#include <string.h>
18
20
21
22struct Q_CORE_EXPORT QAbstractConcatenable
23{
24protected:
25 static void convertFromUtf8(QByteArrayView in, QChar *&out) noexcept;
26 static inline void convertFromAscii(char a, QChar *&out) noexcept
27 {
28 *out++ = QLatin1Char(a);
29 }
30 static void appendLatin1To(QLatin1StringView in, QChar *out) noexcept;
31};
32
33template <typename T> struct QConcatenable;
34
35template <typename T>
37
38namespace QtStringBuilder {
39 template <typename A, typename B> struct ConvertToTypeHelper
40 { typedef A ConvertTo; };
41 template <typename T> struct ConvertToTypeHelper<T, QString>
42 { typedef QString ConvertTo; };
43
44 template <typename T> using HasIsNull = decltype(std::declval<const T &>().isNull());
45 template <typename T> bool isNull(const T &t)
46 {
47 if constexpr (qxp::is_detected_v<HasIsNull, T>)
48 return t.isNull();
49 else
50 return false;
51 }
52}
53
54template<typename Builder, typename T>
56{
57 T toUpper() const { return resolved().toUpper(); }
58 T toLower() const { return resolved().toLower(); }
59
60protected:
61 T resolved() const { return *static_cast<const Builder*>(this); }
62};
63
64template<typename Builder, typename T>
65struct QStringBuilderBase : public QStringBuilderCommon<Builder, T>
66{
67};
68
69template<typename Builder>
70struct QStringBuilderBase<Builder, QString> : public QStringBuilderCommon<Builder, QString>
71{
72 QByteArray toLatin1() const { return this->resolved().toLatin1(); }
73 QByteArray toUtf8() const { return this->resolved().toUtf8(); }
74 QByteArray toLocal8Bit() const { return this->resolved().toLocal8Bit(); }
75};
76
77template <typename A, typename B>
78class QStringBuilder : public QStringBuilderBase<QStringBuilder<A, B>,
79 typename QtStringBuilder::ConvertToTypeHelper<
80 typename QConcatenableEx<A>::ConvertTo,
81 typename QConcatenableEx<B>::ConvertTo
82 >::ConvertTo
83 >
84{
85public:
86 QStringBuilder(A &&a_, B &&b_) : a(std::forward<A>(a_)), b(std::forward<B>(b_)) {}
87
89 QStringBuilder(const QStringBuilder &) = default;
90 ~QStringBuilder() = default;
91
92private:
93 friend class QByteArray;
94 friend class QString;
95 template <typename T> T convertTo() const
96 {
97 if (isNull()) {
98 // appending two null strings must give back a null string,
99 // so we're special casing this one out, QTBUG-114206
100 return T();
101 }
102
105
106 // we abuse const_cast / constData here because we know we've just
107 // allocated the data and we're the only reference count
108 typename T::iterator d = const_cast<typename T::iterator>(s.constData());
109 typename T::const_iterator const start = d;
110 QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
111
112 if (!QConcatenable< QStringBuilder<A, B> >::ExactSize && len != d - start) {
113 // this resize is necessary since we allocate a bit too much
114 // when dealing with variable sized 8-bit encodings
115 s.resize(d - start);
116 }
117 return s;
118 }
119
120 typedef QConcatenable<QStringBuilder<A, B> > Concatenable;
121public:
123 operator ConvertTo() const { return convertTo<ConvertTo>(); }
124
125 qsizetype size() const { return Concatenable::size(*this); }
126
127 bool isNull() const
128 {
130 }
131
134
135private:
136 QStringBuilder &operator=(QStringBuilder &&) = delete;
137 QStringBuilder &operator=(const QStringBuilder &) = delete;
138};
139
140template <> struct QConcatenable<char> : private QAbstractConcatenable
141{
142 typedef char type;
144 enum { ExactSize = true };
145 static qsizetype size(const char) { return 1; }
146#ifndef QT_NO_CAST_FROM_ASCII
147 QT_ASCII_CAST_WARN static inline void appendTo(const char c, QChar *&out)
148 {
150 }
151#endif
152 static inline void appendTo(const char c, char *&out)
153 { *out++ = c; }
154};
155
157{
160 enum { ExactSize = true };
161 static qsizetype size(QByteArrayView bav) { return bav.size(); }
162#ifndef QT_NO_CAST_FROM_ASCII
164 {
166 }
167#endif
168 static inline void appendTo(QByteArrayView bav, char *&out)
169 {
170 qsizetype n = bav.size();
171 if (n)
172 memcpy(out, bav.data(), n);
173 out += n;
174 }
175};
176
177template <> struct QConcatenable<char16_t> : private QAbstractConcatenable
178{
179 typedef char16_t type;
181 enum { ExactSize = true };
182 static constexpr qsizetype size(char16_t) { return 1; }
183 static inline void appendTo(char16_t c, QChar *&out)
184 { *out++ = c; }
185};
186
187template <> struct QConcatenable<QLatin1Char>
188{
191 enum { ExactSize = true };
192 static qsizetype size(const QLatin1Char) { return 1; }
193 static inline void appendTo(const QLatin1Char c, QChar *&out)
194 { *out++ = c; }
195 static inline void appendTo(const QLatin1Char c, char *&out)
196 { *out++ = c.toLatin1(); }
197};
198
199template <> struct QConcatenable<QChar> : private QAbstractConcatenable
200{
201 typedef QChar type;
203 enum { ExactSize = true };
204 static qsizetype size(const QChar) { return 1; }
205 static inline void appendTo(const QChar c, QChar *&out)
206 { *out++ = c; }
207};
208
209template <> struct QConcatenable<QChar::SpecialCharacter> : private QAbstractConcatenable
210{
213 enum { ExactSize = true };
214 static qsizetype size(const QChar::SpecialCharacter) { return 1; }
215 static inline void appendTo(const QChar::SpecialCharacter c, QChar *&out)
216 { *out++ = c; }
217};
218
220{
223 enum { ExactSize = true };
224 static qsizetype size(const QLatin1StringView a) { return a.size(); }
225 static inline void appendTo(const QLatin1StringView a, QChar *&out)
226 {
227 appendLatin1To(a, out);
228 out += a.size();
229 }
230 static inline void appendTo(const QLatin1StringView a, char *&out)
231 {
232 if (const char *data = a.data()) {
233 memcpy(out, data, a.size());
234 out += a.size();
235 }
236 }
237};
238
239template <> struct QConcatenable<QString> : private QAbstractConcatenable
240{
241 typedef QString type;
243 enum { ExactSize = true };
244 static qsizetype size(const QString &a) { return a.size(); }
245 static inline void appendTo(const QString &a, QChar *&out)
246 {
247 const qsizetype n = a.size();
248 if (n)
249 memcpy(out, reinterpret_cast<const char*>(a.constData()), sizeof(QChar) * n);
250 out += n;
251 }
252};
253
255{
258 enum { ExactSize = true };
259 static qsizetype size(QStringView a) { return a.size(); }
260 static inline void appendTo(QStringView a, QChar *&out)
261 {
262 const auto n = a.size();
263 if (n)
264 memcpy(out, a.data(), sizeof(QChar) * n);
265 out += n;
266 }
267};
268
269template <qsizetype N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
270{
271 typedef const char type[N];
273 enum { ExactSize = false };
274 static qsizetype size(const char[N]) { return N - 1; }
275#ifndef QT_NO_CAST_FROM_ASCII
276 QT_ASCII_CAST_WARN static inline void appendTo(const char a[N], QChar *&out)
277 {
279 }
280#endif
281 static inline void appendTo(const char a[N], char *&out)
282 {
283 while (*a)
284 *out++ = *a++;
285 }
286};
287
288template <qsizetype N> struct QConcatenable<char[N]> : QConcatenable<const char[N]>
289{
290 typedef char type[N];
291};
292
293template <> struct QConcatenable<const char *> : private QAbstractConcatenable
294{
295 typedef const char *type;
297 enum { ExactSize = false };
298 static qsizetype size(const char *a) { return qstrlen(a); }
299#ifndef QT_NO_CAST_FROM_ASCII
300 QT_ASCII_CAST_WARN static inline void appendTo(const char *a, QChar *&out)
302#endif
303 static inline void appendTo(const char *a, char *&out)
304 {
305 if (!a)
306 return;
307 while (*a)
308 *out++ = *a++;
309 }
310};
311
312template <> struct QConcatenable<char *> : QConcatenable<const char*>
313{
314 typedef char *type;
315};
316
317template <qsizetype N> struct QConcatenable<const char16_t[N]> : private QAbstractConcatenable
318{
319 using type = const char16_t[N];
321 enum { ExactSize = true };
322 static qsizetype size(const char16_t[N]) { return N - 1; }
323 static void appendTo(const char16_t a[N], QChar *&out)
324 {
325 memcpy(static_cast<void *>(out), a, (N - 1) * sizeof(char16_t));
326 out += N - 1;
327 }
328};
329
330template <qsizetype N> struct QConcatenable<char16_t[N]> : QConcatenable<const char16_t[N]>
331{
332 using type = char16_t[N];
333};
334
335template <> struct QConcatenable<const char16_t *> : private QAbstractConcatenable
336{
337 using type = const char16_t *;
339 enum { ExactSize = true };
340 static qsizetype size(const char16_t *a) { return QStringView(a).size(); }
341 QT_ASCII_CAST_WARN static inline void appendTo(const char16_t *a, QChar *&out)
342 {
343 if (!a)
344 return;
345 while (*a)
346 *out++ = *a++;
347 }
348};
349
350template <> struct QConcatenable<char16_t *> : QConcatenable<const char16_t*>
351{
352 typedef char16_t *type;
353};
354
355template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
356{
359 enum { ExactSize = false };
360 static qsizetype size(const QByteArray &ba) { return ba.size(); }
361#ifndef QT_NO_CAST_FROM_ASCII
362 QT_ASCII_CAST_WARN static inline void appendTo(const QByteArray &ba, QChar *&out)
363 {
365 }
366#endif
367 static inline void appendTo(const QByteArray &ba, char *&out)
368 {
369 const char *a = ba.constData();
370 const char * const end = ba.end();
371 while (a != end)
372 *out++ = *a++;
373 }
374};
375
376
377template <typename A, typename B>
379{
384 >::ConvertTo;
386 static qsizetype size(const type &p)
387 {
389 }
390 template<typename T> static inline void appendTo(const type &p, T *&out)
391 {
394 }
395};
396
397template <typename A, typename B,
398 typename = std::void_t<typename QConcatenableEx<A>::type, typename QConcatenableEx<B>::type>>
399auto operator%(A &&a, B &&b)
400{
401 return QStringBuilder<A, B>(std::forward<A>(a), std::forward<B>(b));
402}
403
404// QT_USE_FAST_OPERATOR_PLUS was introduced in 4.7, QT_USE_QSTRINGBUILDER is to be used from 4.8 onwards
405// QT_USE_FAST_OPERATOR_PLUS does not remove the normal operator+ for QByteArray
406#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
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 std::forward<A>(a) % std::forward<B>(b);
412}
413#endif
414
415namespace QtStringBuilder {
416template <typename A, typename B>
418{
419 // append 8-bit data to a byte array
421 a.detach(); // a detach() in a.data() could reset a.capacity() to a.size()
422 if (len > a.data_ptr().freeSpaceAtEnd()) // capacity() was broken when prepend()-optimization landed
423 a.reserve(qMax(len, 2 * a.capacity()));
424 char *it = a.data() + a.size();
426 a.resize(len); //we need to resize after the appendTo for the case str+=foo+str
427 return a;
428}
429
430#ifndef QT_NO_CAST_TO_ASCII
431template <typename A, typename B>
433{
434 return a += QString(b).toUtf8();
435}
436#endif
437}
438
439template <typename A, typename B>
441{
443 typename QConcatenable< QStringBuilder<A, B> >::ConvertTo::value_type());
444}
445
446template <typename A, typename B>
448{
450 a.detach(); // a detach() in a.data() could reset a.capacity() to a.size()
451 if (len > a.data_ptr().freeSpaceAtEnd()) // capacity() was broken when prepend()-optimization landed
452 a.reserve(qMax(len, 2 * a.capacity()));
453 QChar *it = a.data() + a.size();
455 // we need to resize after the appendTo for the case str+=foo+str
456 a.resize(it - a.constData()); //may be smaller than len if there was conversion from utf8
457 return a;
458}
459
461
462#endif // QSTRINGBUILDER_H
constexpr qsizetype size() const noexcept
constexpr const_pointer data() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:474
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
iterator end()
Returns an \l{STL-style iterators}{STL-style iterator} pointing just after the last byte in the byte-...
Definition qbytearray.h:432
\inmodule QtCore
Definition qchar.h:48
SpecialCharacter
\value Null A QChar with this value isNull().
Definition qchar.h:50
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:76
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:127
QByteArray toUtf8() const &
Definition qstring.h:563
QSet< QString >::iterator it
Combined button and popup list for selecting options.
bool isNull(const T &t)
decltype(std::declval< const T & >().isNull()) HasIsNull
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]
GLuint GLuint end
GLenum type
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLfloat n
const GLubyte * c
GLenum GLsizei len
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint in
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
QByteArray & operator+=(QByteArray &a, const QStringBuilder< A, B > &b)
auto operator%(A &&a, B &&b)
#define QT_ASCII_CAST_WARN
ptrdiff_t qsizetype
Definition qtypes.h:70
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:17