From 542ded462ef637dd48b29ba10845c3afb76ec126 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 21 Apr 2020 10:10:18 +0200 Subject: [PATCH] Enable using QStringConverter together with QStringBuilder The way the new converters are structured allows us to use them together with QStringBuilder. Like this, we can avoid additional and unnecessary copies of the data. Change-Id: I168da3860537fe81a1eb62632e4d9a6680f86af1 Reviewed-by: Thiago Macieira --- src/corelib/text/qstringconverter.h | 105 ++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 6 deletions(-) diff --git a/src/corelib/text/qstringconverter.h b/src/corelib/text/qstringconverter.h index 2e0f0db616..f2b78508e6 100644 --- a/src/corelib/text/qstringconverter.h +++ b/src/corelib/text/qstringconverter.h @@ -41,6 +41,9 @@ #define QSTRINGCONVERTER_H #include +#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER) +#include +#endif QT_BEGIN_NAMESPACE @@ -169,10 +172,36 @@ public: : QStringConverter(encoding, flags) {} +#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER) + template + struct DecodedData + { + QStringEncoder *encoder; + T data; + operator QByteArray() const { return encoder->encode(QStringView(data)); } + }; + DecodedData operator()(const QString &str) + { return DecodedData{this, str}; } + DecodedData operator()(QStringView in) + { return DecodedData{this, in}; } +#else + QByteArray operator()(const QString &in) + { + return encode(QStringView(in)); + } + QByteArray operator()(QStringView in) + { + return encode(in); + } +#endif QByteArray operator()(const QChar *in, qsizetype length) { return (*this)(QStringView(in, length)); } - QByteArray operator()(QStringView in) + qsizetype requiredSpace(qsizetype inputLength) const + { return iface->fromUtf16Len(inputLength); } + char *decodeIntoBuffer(char *out, const QChar *in, qsizetype length) + { return iface->fromUtf16(out, QStringView(in, length), state.flags & Stateless ? nullptr : &state); } + QByteArray encode(QStringView in) { QByteArray result(iface->fromUtf16Len(in.size()), Qt::Uninitialized); char *out = result.data(); @@ -181,10 +210,20 @@ public: result.truncate(out - result.constData()); return result; } + }; class QStringDecoder : public QStringConverter { +#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER) + struct View { + const char *ch; + qsizetype l; + const char *data() const { return ch; } + qsizetype length() const { return l; } + }; +#endif + protected: QSTRINGCONVERTER_CONSTEXPR QStringDecoder(const Interface *i) : QStringConverter(i) @@ -194,21 +233,75 @@ public: : QStringConverter(encoding, flags) {} +#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER) + template + struct EncodedData + { + QStringDecoder *decoder; + T data; + operator QString() const { return decoder->decode(data.data(), data.length()); } + }; + EncodedData operator()(const QByteArray &ba) + { return EncodedData{this, ba}; } + EncodedData operator()(const char *in, qsizetype length) + { return EncodedData{this, {in, length}}; } + EncodedData operator()(const char *chars) + { return EncodedData{this, {chars, qsizetype(strlen(chars))}}; } +#else + QString operator()(const QByteArray &ba) + { return decode(ba.data(), ba.length()); } QString operator()(const char *in, qsizetype length) + { return decode(in, length); } + QString operator()(const char *chars) + { return decode(chars, strlen(chars)); } +#endif + + qsizetype requiredSpace(qsizetype inputLength) const + { return iface->toUtf16Len(inputLength); } + QChar *decodeIntoBuffer(QChar *out, const char *in, qsizetype length) + { return iface->toUtf16(out, in, length, state.flags & Stateless ? nullptr : &state); } + QString decode(const char *in, qsizetype length) { QString result(iface->toUtf16Len(length), Qt::Uninitialized); QChar *out = result.data(); - // ### Fixme: needs to be moved into the conversion methods + // ### Fixme: state handling needs to be moved into the conversion methods out = iface->toUtf16(out, in, length, state.flags & Stateless ? nullptr : &state); result.truncate(out - result.constData()); return result; } - QString operator()(const QByteArray &ba) - { return (*this)(ba.constData(), ba.size()); } - QString operator()(const char *chars) - { return (*this)(chars, strlen(chars)); } }; + +#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER) +template +struct QConcatenable> + : private QAbstractConcatenable +{ + typedef QChar type; + typedef QString ConvertTo; + enum { ExactSize = false }; + static qsizetype size(const QStringDecoder::EncodedData &s) { return s.decoder->requiredSpace(s.data.length()); } + static inline void appendTo(const QStringDecoder::EncodedData &s, QChar *&out) + { + out = s.decoder->decodeIntoBuffer(out, s.data.data(), s.data.length()); + } +}; + +template +struct QConcatenable> + : private QAbstractConcatenable +{ + typedef char type; + typedef QByteArray ConvertTo; + enum { ExactSize = false }; + static qsizetype size(const QStringEncoder::DecodedData &s) { return s.encoder->requiredSpace(s.data.length()); } + static inline void appendTo(const QStringEncoder::DecodedData &s, char *&out) + { + out = s.decoder->decodeIntoBuffer(out, s.data.data(), s.data.length()); + } +}; +#endif + QT_END_NAMESPACE #undef QSTRINGCONVERTER_CONSTEXPR