Add the UTF16-to-Latin1 in-place converter
This is only possible for two important reasons: 1) QString and QByteArray d pointers are both done with QArrayData and that class does not care that the alignof(T) changes from 2 to 1, so we can give the pointer from QString to QByteArray (after adapting the allocated size, which is now double) 2) conversion from UTF16 to Latin1 always has fewer bytes (exactly half) Change-Id: I17b2690c910f3de8db55156c6d6b5f55be06d827 Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
parent
8892e3d0fc
commit
ee7536876c
@ -4020,6 +4020,36 @@ QByteArray QString::toLatin1_helper(const QChar *data, int length)
|
||||
return ba;
|
||||
}
|
||||
|
||||
QByteArray QString::toLatin1_helper_inplace(QString &s)
|
||||
{
|
||||
if (!s.isDetached())
|
||||
return s.toLatin1();
|
||||
|
||||
// We can return our own buffer to the caller.
|
||||
// Conversion to Latin-1 always shrinks the buffer by half.
|
||||
const ushort *data = reinterpret_cast<const ushort *>(s.constData());
|
||||
uint length = s.size();
|
||||
|
||||
// Swap the d pointers.
|
||||
// Kids, avert your eyes. Don't try this at home.
|
||||
QArrayData *ba_d = s.d;
|
||||
|
||||
// multiply the allocated capacity by sizeof(ushort)
|
||||
ba_d->alloc *= sizeof(ushort);
|
||||
|
||||
// reset ourselves to QString()
|
||||
s.d = QString().d;
|
||||
|
||||
// do the in-place conversion
|
||||
uchar *dst = reinterpret_cast<uchar *>(ba_d->data());
|
||||
QT_PREPEND_NAMESPACE(toLatin1_helper)(dst, data, length);
|
||||
dst[length] = '\0';
|
||||
|
||||
QByteArrayDataPtr badptr = { ba_d };
|
||||
return QByteArray(badptr);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\fn QByteArray QString::toLatin1() const
|
||||
|
||||
|
@ -481,7 +481,7 @@ public:
|
||||
QByteArray toLatin1() const & Q_REQUIRED_RESULT
|
||||
{ return toLatin1_helper(*this); }
|
||||
QByteArray toLatin1() && Q_REQUIRED_RESULT
|
||||
{ return toLatin1_helper(reinterpret_cast<const ushort *>(constData()), size()); }
|
||||
{ return toLatin1_helper_inplace(*this); }
|
||||
QByteArray toUtf8() const & Q_REQUIRED_RESULT
|
||||
{ return toUtf8_helper(*this); }
|
||||
QByteArray toUtf8() && Q_REQUIRED_RESULT
|
||||
@ -751,6 +751,7 @@ private:
|
||||
static QString fromLocal8Bit_helper(const char *, int size);
|
||||
static QByteArray toLatin1_helper(const QString &);
|
||||
static QByteArray toLatin1_helper(const QChar *data, int size);
|
||||
static QByteArray toLatin1_helper_inplace(QString &);
|
||||
static QByteArray toUtf8_helper(const QString &);
|
||||
static QByteArray toLocal8Bit_helper(const QChar *data, int size);
|
||||
static int toUcs4_helper(const ushort *uc, int length, uint *out);
|
||||
|
@ -3882,6 +3882,14 @@ void tst_QString::toLatin1Roundtrip()
|
||||
// and back:
|
||||
QCOMPARE(QString::fromLatin1(latin1, latin1.length()).length(), unicodedst.length());
|
||||
QCOMPARE(QString::fromLatin1(latin1, latin1.length()), unicodedst);
|
||||
|
||||
// try the rvalue version of toLatin1()
|
||||
QString s = unicodesrc;
|
||||
QCOMPARE(qMove(s).toLatin1(), latin1);
|
||||
|
||||
// and verify that the moved-from object can still be used
|
||||
s = "foo";
|
||||
s.clear();
|
||||
}
|
||||
|
||||
void tst_QString::stringRef_toLatin1Roundtrip_data()
|
||||
|
Loading…
x
Reference in New Issue
Block a user