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