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 <thiago.macieira@intel.com>
This commit is contained in:
Lars Knoll 2020-04-21 10:10:18 +02:00
parent 9ada6e5719
commit 542ded462e

View File

@ -41,6 +41,9 @@
#define QSTRINGCONVERTER_H #define QSTRINGCONVERTER_H
#include <QtCore/qstring.h> #include <QtCore/qstring.h>
#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
#include <QtCore/qstringbuilder.h>
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -169,10 +172,36 @@ public:
: QStringConverter(encoding, flags) : QStringConverter(encoding, flags)
{} {}
#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
template<typename T>
struct DecodedData
{
QStringEncoder *encoder;
T data;
operator QByteArray() const { return encoder->encode(QStringView(data)); }
};
DecodedData<const QString &> operator()(const QString &str)
{ return DecodedData<const QString &>{this, str}; }
DecodedData<QStringView> operator()(QStringView in)
{ return DecodedData<QStringView>{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) QByteArray operator()(const QChar *in, qsizetype length)
{ return (*this)(QStringView(in, 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); QByteArray result(iface->fromUtf16Len(in.size()), Qt::Uninitialized);
char *out = result.data(); char *out = result.data();
@ -181,10 +210,20 @@ public:
result.truncate(out - result.constData()); result.truncate(out - result.constData());
return result; return result;
} }
}; };
class QStringDecoder : public QStringConverter 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: protected:
QSTRINGCONVERTER_CONSTEXPR QStringDecoder(const Interface *i) QSTRINGCONVERTER_CONSTEXPR QStringDecoder(const Interface *i)
: QStringConverter(i) : QStringConverter(i)
@ -194,21 +233,75 @@ public:
: QStringConverter(encoding, flags) : QStringConverter(encoding, flags)
{} {}
#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
template<typename T>
struct EncodedData
{
QStringDecoder *decoder;
T data;
operator QString() const { return decoder->decode(data.data(), data.length()); }
};
EncodedData<const QByteArray &> operator()(const QByteArray &ba)
{ return EncodedData<const QByteArray &>{this, ba}; }
EncodedData<View> operator()(const char *in, qsizetype length)
{ return EncodedData<View>{this, {in, length}}; }
EncodedData<View> operator()(const char *chars)
{ return EncodedData<View>{this, {chars, qsizetype(strlen(chars))}}; }
#else
QString operator()(const QByteArray &ba)
{ return decode(ba.data(), ba.length()); }
QString operator()(const char *in, qsizetype 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); QString result(iface->toUtf16Len(length), Qt::Uninitialized);
QChar *out = result.data(); 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); out = iface->toUtf16(out, in, length, state.flags & Stateless ? nullptr : &state);
result.truncate(out - result.constData()); result.truncate(out - result.constData());
return result; 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 <typename T>
struct QConcatenable<QStringDecoder::EncodedData<T>>
: private QAbstractConcatenable
{
typedef QChar type;
typedef QString ConvertTo;
enum { ExactSize = false };
static qsizetype size(const QStringDecoder::EncodedData<T> &s) { return s.decoder->requiredSpace(s.data.length()); }
static inline void appendTo(const QStringDecoder::EncodedData<T> &s, QChar *&out)
{
out = s.decoder->decodeIntoBuffer(out, s.data.data(), s.data.length());
}
};
template <typename T>
struct QConcatenable<QStringEncoder::DecodedData<T>>
: private QAbstractConcatenable
{
typedef char type;
typedef QByteArray ConvertTo;
enum { ExactSize = false };
static qsizetype size(const QStringEncoder::DecodedData<T> &s) { return s.encoder->requiredSpace(s.data.length()); }
static inline void appendTo(const QStringEncoder::DecodedData<T> &s, char *&out)
{
out = s.decoder->decodeIntoBuffer(out, s.data.data(), s.data.length());
}
};
#endif
QT_END_NAMESPACE QT_END_NAMESPACE
#undef QSTRINGCONVERTER_CONSTEXPR #undef QSTRINGCONVERTER_CONSTEXPR