File indexing completed on 2026-09-17 09:25:14
0001
0002
0003
0004
0005 #include <QtCore/qstring.h>
0006
0007 #ifndef QSTRINGBUILDER_H
0008 #define QSTRINGBUILDER_H
0009
0010 #if 0
0011
0012
0013 #pragma qt_class(QStringBuilder)
0014 #pragma qt_sync_stop_processing
0015 #endif
0016
0017 #include <QtCore/qbytearray.h>
0018
0019 #include <string.h>
0020
0021 QT_BEGIN_NAMESPACE
0022
0023
0024 struct Q_CORE_EXPORT QAbstractConcatenable
0025 {
0026 protected:
0027 static void convertFromUtf8(QByteArrayView in, QChar *&out) noexcept;
0028 static inline void convertFromAscii(char a, QChar *&out) noexcept
0029 {
0030 *out++ = QLatin1Char(a);
0031 }
0032 static void appendLatin1To(QLatin1StringView in, QChar *out) noexcept;
0033 };
0034
0035 template <typename T> struct QConcatenable;
0036
0037 template <typename T>
0038 using QConcatenableEx = QConcatenable<q20::remove_cvref_t<T>>;
0039
0040 namespace QtStringBuilder {
0041 template <typename A, typename B> struct ConvertToTypeHelper
0042 { typedef A ConvertTo; };
0043 template <typename T> struct ConvertToTypeHelper<T, QString>
0044 { typedef QString ConvertTo; };
0045
0046 template <typename T> using HasIsNull = decltype(std::declval<const T &>().isNull());
0047 template <typename T> bool isNull(const T &t)
0048 {
0049 if constexpr (qxp::is_detected_v<HasIsNull, T>)
0050 return t.isNull();
0051 else
0052 return false;
0053 }
0054 }
0055
0056 template<typename Builder, typename T>
0057 struct QStringBuilderCommon
0058 {
0059 T toUpper() const { return resolved().toUpper(); }
0060 T toLower() const { return resolved().toLower(); }
0061
0062 protected:
0063 T resolved() const { return *static_cast<const Builder*>(this); }
0064 };
0065
0066 template<typename Builder, typename T>
0067 struct QStringBuilderBase : public QStringBuilderCommon<Builder, T>
0068 {
0069 };
0070
0071 template<typename Builder>
0072 struct QStringBuilderBase<Builder, QString> : public QStringBuilderCommon<Builder, QString>
0073 {
0074 QByteArray toLatin1() const { return this->resolved().toLatin1(); }
0075 QByteArray toUtf8() const { return this->resolved().toUtf8(); }
0076 QByteArray toLocal8Bit() const { return this->resolved().toLocal8Bit(); }
0077 };
0078
0079 template <typename A, typename B>
0080 class QStringBuilder : public QStringBuilderBase<QStringBuilder<A, B>,
0081 typename QtStringBuilder::ConvertToTypeHelper<
0082 typename QConcatenableEx<A>::ConvertTo,
0083 typename QConcatenableEx<B>::ConvertTo
0084 >::ConvertTo
0085 >
0086 {
0087 public:
0088 QStringBuilder(A &&a_, B &&b_) : a(std::forward<A>(a_)), b(std::forward<B>(b_)) {}
0089
0090 QStringBuilder(QStringBuilder &&) = default;
0091 QStringBuilder(const QStringBuilder &) = default;
0092 ~QStringBuilder() = default;
0093
0094 private:
0095 friend class QByteArray;
0096 friend class QString;
0097 template <typename T> T convertTo() const
0098 {
0099 if (isNull()) {
0100
0101
0102 return T();
0103 }
0104 return convertToImpl<T>(Concatenable::size(*this));
0105 }
0106 template <typename T> T convertToImpl(const qsizetype len) const
0107 {
0108 T s(len, Qt::Uninitialized);
0109
0110
0111
0112
0113
0114 auto d = reinterpret_cast<typename T::iterator>(s.data_ptr().data());
0115 const auto start = d;
0116 Concatenable::appendTo(*this, d);
0117
0118 if constexpr (Concatenable::ExactSize) {
0119 Q_UNUSED(start)
0120 } else {
0121 if (len != d - start) {
0122
0123
0124 s.resize(d - start);
0125 }
0126 }
0127 return s;
0128 }
0129
0130 typedef QConcatenable<QStringBuilder<A, B> > Concatenable;
0131 public:
0132 typedef typename Concatenable::ConvertTo ConvertTo;
0133 operator ConvertTo() const { return convertTo<ConvertTo>(); }
0134
0135 qsizetype size() const { return Concatenable::size(*this); }
0136
0137 bool isNull() const
0138 {
0139 return QtStringBuilder::isNull(a) && QtStringBuilder::isNull(b);
0140 }
0141
0142 A a;
0143 B b;
0144
0145 private:
0146 QStringBuilder &operator=(QStringBuilder &&) = delete;
0147 QStringBuilder &operator=(const QStringBuilder &) = delete;
0148 };
0149
0150 template <> struct QConcatenable<char> : private QAbstractConcatenable
0151 {
0152 typedef char type;
0153 typedef QByteArray ConvertTo;
0154 enum { ExactSize = true };
0155 static qsizetype size(const char) { return 1; }
0156 #ifndef QT_NO_CAST_FROM_ASCII
0157 QT_ASCII_CAST_WARN static inline void appendTo(const char c, QChar *&out)
0158 {
0159 QAbstractConcatenable::convertFromAscii(c, out);
0160 }
0161 #endif
0162 static inline void appendTo(const char c, char *&out)
0163 { *out++ = c; }
0164 };
0165
0166 template <> struct QConcatenable<QByteArrayView> : private QAbstractConcatenable
0167 {
0168 typedef QByteArrayView type;
0169 typedef QByteArray ConvertTo;
0170 enum { ExactSize = true };
0171 static qsizetype size(QByteArrayView bav) { return bav.size(); }
0172 #ifndef QT_NO_CAST_FROM_ASCII
0173 QT_ASCII_CAST_WARN static inline void appendTo(QByteArrayView bav, QChar *&out)
0174 {
0175 QAbstractConcatenable::convertFromUtf8(bav, out);
0176 }
0177 #endif
0178 static inline void appendTo(QByteArrayView bav, char *&out)
0179 {
0180 qsizetype n = bav.size();
0181 if (n)
0182 memcpy(out, bav.data(), n);
0183 out += n;
0184 }
0185 };
0186
0187 template <> struct QConcatenable<char16_t> : private QAbstractConcatenable
0188 {
0189 typedef char16_t type;
0190 typedef QString ConvertTo;
0191 enum { ExactSize = true };
0192 static constexpr qsizetype size(char16_t) { return 1; }
0193 static inline void appendTo(char16_t c, QChar *&out)
0194 { *out++ = c; }
0195 };
0196
0197 template <> struct QConcatenable<QLatin1Char>
0198 {
0199 typedef QLatin1Char type;
0200 typedef QString ConvertTo;
0201 enum { ExactSize = true };
0202 static qsizetype size(const QLatin1Char) { return 1; }
0203 static inline void appendTo(const QLatin1Char c, QChar *&out)
0204 { *out++ = c; }
0205 static inline void appendTo(const QLatin1Char c, char *&out)
0206 { *out++ = c.toLatin1(); }
0207 };
0208
0209 template <> struct QConcatenable<QChar> : private QAbstractConcatenable
0210 {
0211 typedef QChar type;
0212 typedef QString ConvertTo;
0213 enum { ExactSize = true };
0214 static qsizetype size(const QChar) { return 1; }
0215 static inline void appendTo(const QChar c, QChar *&out)
0216 { *out++ = c; }
0217 };
0218
0219 template <> struct QConcatenable<QChar::SpecialCharacter> : private QAbstractConcatenable
0220 {
0221 typedef QChar::SpecialCharacter type;
0222 typedef QString ConvertTo;
0223 enum { ExactSize = true };
0224 static qsizetype size(const QChar::SpecialCharacter) { return 1; }
0225 static inline void appendTo(const QChar::SpecialCharacter c, QChar *&out)
0226 { *out++ = c; }
0227 };
0228
0229 template <> struct QConcatenable<QLatin1StringView> : private QAbstractConcatenable
0230 {
0231 typedef QLatin1StringView type;
0232 typedef QString ConvertTo;
0233 enum { ExactSize = true };
0234 static qsizetype size(const QLatin1StringView a) { return a.size(); }
0235 static inline void appendTo(const QLatin1StringView a, QChar *&out)
0236 {
0237 appendLatin1To(a, out);
0238 out += a.size();
0239 }
0240 static inline void appendTo(const QLatin1StringView a, char *&out)
0241 {
0242 if (const char *data = a.data()) {
0243 memcpy(out, data, a.size());
0244 out += a.size();
0245 }
0246 }
0247 };
0248
0249 template <> struct QConcatenable<QString> : private QAbstractConcatenable
0250 {
0251 typedef QString type;
0252 typedef QString ConvertTo;
0253 enum { ExactSize = true };
0254 static qsizetype size(const QString &a) { return a.size(); }
0255 static inline void appendTo(const QString &a, QChar *&out)
0256 {
0257 const qsizetype n = a.size();
0258 if (n)
0259 memcpy(out, a.data(), sizeof(QChar) * n);
0260 out += n;
0261 }
0262 };
0263
0264 template <> struct QConcatenable<QStringView> : private QAbstractConcatenable
0265 {
0266 typedef QStringView type;
0267 typedef QString ConvertTo;
0268 enum { ExactSize = true };
0269 static qsizetype size(QStringView a) { return a.size(); }
0270 static inline void appendTo(QStringView a, QChar *&out)
0271 {
0272 const auto n = a.size();
0273 if (n)
0274 memcpy(out, a.data(), sizeof(QChar) * n);
0275 out += n;
0276 }
0277 };
0278
0279 template <qsizetype N> struct QConcatenable<const char[N]> : private QAbstractConcatenable
0280 {
0281 typedef const char type[N];
0282 typedef QByteArray ConvertTo;
0283 enum { ExactSize = false };
0284 static qsizetype size(const char[N]) { return N - 1; }
0285 #ifndef QT_NO_CAST_FROM_ASCII
0286 QT_ASCII_CAST_WARN static inline void appendTo(const char a[N], QChar *&out)
0287 {
0288 QAbstractConcatenable::convertFromUtf8(QByteArrayView(a, N - 1), out);
0289 }
0290 #endif
0291 static inline void appendTo(const char a[N], char *&out)
0292 {
0293 while (*a)
0294 *out++ = *a++;
0295 }
0296 };
0297
0298 template <qsizetype N> struct QConcatenable<char[N]> : QConcatenable<const char[N]>
0299 {
0300 typedef char type[N];
0301 };
0302
0303 template <> struct QConcatenable<const char *> : private QAbstractConcatenable
0304 {
0305 typedef const char *type;
0306 typedef QByteArray ConvertTo;
0307 enum { ExactSize = false };
0308 static qsizetype size(const char *a) { return qstrlen(a); }
0309 #ifndef QT_NO_CAST_FROM_ASCII
0310 QT_ASCII_CAST_WARN static inline void appendTo(const char *a, QChar *&out)
0311 { QAbstractConcatenable::convertFromUtf8(QByteArrayView(a), out); }
0312 #endif
0313 static inline void appendTo(const char *a, char *&out)
0314 {
0315 if (!a)
0316 return;
0317 while (*a)
0318 *out++ = *a++;
0319 }
0320 };
0321
0322 template <> struct QConcatenable<char *> : QConcatenable<const char*>
0323 {
0324 typedef char *type;
0325 };
0326
0327 template <qsizetype N> struct QConcatenable<const char16_t[N]> : private QAbstractConcatenable
0328 {
0329 using type = const char16_t[N];
0330 using ConvertTo = QString;
0331 enum { ExactSize = true };
0332 static qsizetype size(const char16_t[N]) { return N - 1; }
0333 static void appendTo(const char16_t a[N], QChar *&out)
0334 {
0335 memcpy(static_cast<void *>(out), a, (N - 1) * sizeof(char16_t));
0336 out += N - 1;
0337 }
0338 };
0339
0340 template <qsizetype N> struct QConcatenable<char16_t[N]> : QConcatenable<const char16_t[N]>
0341 {
0342 using type = char16_t[N];
0343 };
0344
0345 template <> struct QConcatenable<const char16_t *> : private QAbstractConcatenable
0346 {
0347 using type = const char16_t *;
0348 using ConvertTo = QString;
0349 enum { ExactSize = true };
0350 static qsizetype size(const char16_t *a) { return QStringView(a).size(); }
0351 QT_ASCII_CAST_WARN static inline void appendTo(const char16_t *a, QChar *&out)
0352 {
0353 if (!a)
0354 return;
0355 while (*a)
0356 *out++ = *a++;
0357 }
0358 };
0359
0360 template <> struct QConcatenable<char16_t *> : QConcatenable<const char16_t*>
0361 {
0362 typedef char16_t *type;
0363 };
0364
0365 template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
0366 {
0367 typedef QByteArray type;
0368 typedef QByteArray ConvertTo;
0369 enum { ExactSize = false };
0370 static qsizetype size(const QByteArray &ba) { return ba.size(); }
0371 #ifndef QT_NO_CAST_FROM_ASCII
0372 QT_ASCII_CAST_WARN static inline void appendTo(const QByteArray &ba, QChar *&out)
0373 {
0374 QAbstractConcatenable::convertFromUtf8(ba, out);
0375 }
0376 #endif
0377 static inline void appendTo(const QByteArray &ba, char *&out)
0378 {
0379 const qsizetype n = ba.size();
0380 if (n)
0381 memcpy(out, ba.begin(), n);
0382 out += n;
0383 }
0384 };
0385
0386
0387 template <typename A, typename B>
0388 struct QConcatenable< QStringBuilder<A, B> >
0389 {
0390 typedef QStringBuilder<A, B> type;
0391 using ConvertTo = typename QtStringBuilder::ConvertToTypeHelper<
0392 typename QConcatenableEx<A>::ConvertTo,
0393 typename QConcatenableEx<B>::ConvertTo
0394 >::ConvertTo;
0395 enum { ExactSize = QConcatenableEx<A>::ExactSize && QConcatenableEx<B>::ExactSize };
0396 static qsizetype size(const type &p)
0397 {
0398 return QConcatenableEx<A>::size(p.a) + QConcatenableEx<B>::size(p.b);
0399 }
0400 template<typename T> static inline void appendTo(const type &p, T *&out)
0401 {
0402 QConcatenableEx<A>::appendTo(p.a, out);
0403 QConcatenableEx<B>::appendTo(p.b, out);
0404 }
0405 };
0406
0407 template <typename A, typename B,
0408 typename = std::void_t<typename QConcatenableEx<A>::type, typename QConcatenableEx<B>::type>>
0409 auto operator%(A &&a, B &&b)
0410 {
0411 return QStringBuilder<A, B>(std::forward<A>(a), std::forward<B>(b));
0412 }
0413
0414
0415
0416 #if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
0417 template <typename A, typename B,
0418 typename = std::void_t<typename QConcatenableEx<A>::type, typename QConcatenableEx<B>::type>>
0419 auto operator+(A &&a, B &&b)
0420 {
0421 return std::forward<A>(a) % std::forward<B>(b);
0422 }
0423 #endif
0424
0425 namespace QtStringBuilder {
0426 template <typename A, typename B>
0427 QByteArray &appendToByteArray(QByteArray &a, const QStringBuilder<A, B> &b, char)
0428 {
0429
0430 qsizetype len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
0431 a.detach();
0432 if (len > a.data_ptr().freeSpaceAtEnd())
0433 a.reserve(qMax(len, 2 * a.capacity()));
0434 char *it = a.data() + a.size();
0435 QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
0436 a.resize(len);
0437 return a;
0438 }
0439
0440 #ifndef QT_NO_CAST_TO_ASCII
0441 template <typename A, typename B>
0442 QByteArray &appendToByteArray(QByteArray &a, const QStringBuilder<A, B> &b, QChar)
0443 {
0444 return a += QString(b).toUtf8();
0445 }
0446 #endif
0447 }
0448
0449 template <typename A, typename B>
0450 QByteArray &operator+=(QByteArray &a, const QStringBuilder<A, B> &b)
0451 {
0452 return QtStringBuilder::appendToByteArray(a, b,
0453 typename QConcatenable< QStringBuilder<A, B> >::ConvertTo::value_type());
0454 }
0455
0456 template <typename A, typename B>
0457 QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
0458 {
0459 qsizetype len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
0460 a.detach();
0461 if (len > a.data_ptr().freeSpaceAtEnd())
0462 a.reserve(qMax(len, 2 * a.capacity()));
0463 QChar *it = a.data() + a.size();
0464 QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
0465
0466 a.resize(it - a.constData());
0467 return a;
0468 }
0469
0470 QT_END_NAMESPACE
0471
0472 #endif