summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qstring.cpp30
-rw-r--r--src/corelib/tools/qstring.h3
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp8
3 files changed, 40 insertions, 1 deletions
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 1b07e31c89..18c96c0b38 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -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
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 943d7c266e..460afb00f4 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -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);
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index 9a3aaebaaf..a0edc16718 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -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()