summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2016-01-11 16:10:00 +0100
committerMarc Mutz <marc.mutz@kdab.com>2016-01-12 06:13:05 +0000
commit08775e4bd745276bcc6a5a9fdc4bed7aca225112 (patch)
tree267ccc37794fac3f97f8553c1353ee298e09a60e
parentca7f1d2197f78ec3332cfd86ab9921730b6d4f23 (diff)
Revert "QString: preserve embedded NULs when converting from QByteArray"
This partially reverts commit e486d69133178ccce7c75cf48201ab28efb20e44. It broke too many users, even though all of them deserved to be broken. The new functionality will be provided by differently-named functions, where possible (problem: equality operators). I did not revert the fix for the off-by-one error in tst_qtextdocumentfragment.cpp. I also didn't revert the change in the inequality relational operators, since for all strings s1, s2 and s2' where s2' is s2 truncated at the first NUL, s1 < s2 ⟺ s1 < s2' (since NUL < c for any c != 0), and, trivially, for ≤, >, ≥, too. This does not hold for = and ≠, of course, since "foo\0bar" ≠ "foo". [ChangeLog][Important Behavior Changes][EDITORIAL] Reverted: All conversions from QByteArray to QString now preserve embedded NULs... Change-Id: If4b47048b39ae5be6ed08e6d91809626a67ea7f5 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/tools/qstring.h18
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp39
2 files changed, 46 insertions, 11 deletions
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 1d04bcb457..1fbcff35d1 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -86,7 +86,7 @@ public:
Q_DECL_CONSTEXPR inline QLatin1String() Q_DECL_NOTHROW : m_size(0), m_data(Q_NULLPTR) {}
Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) Q_DECL_NOTHROW : m_size(s ? int(strlen(s)) : 0), m_data(s) {}
Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) Q_DECL_NOTHROW : m_size(sz), m_data(s) {}
- inline explicit QLatin1String(const QByteArray &s) Q_DECL_NOTHROW : m_size(s.size()), m_data(s.constData()) {}
+ inline explicit QLatin1String(const QByteArray &s) Q_DECL_NOTHROW : m_size(int(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {}
Q_DECL_CONSTEXPR const char *latin1() const Q_DECL_NOTHROW { return m_data; }
Q_DECL_CONSTEXPR int size() const Q_DECL_NOTHROW { return m_size; }
@@ -539,11 +539,11 @@ public:
return fromLocal8Bit_helper(str, (str && size == -1) ? int(strlen(str)) : size);
}
static inline QString fromLatin1(const QByteArray &str)
- { return str.isNull() ? QString() : fromLatin1(str.data(), str.size()); }
+ { return str.isNull() ? QString() : fromLatin1(str.data(), qstrnlen(str.constData(), str.size())); }
static inline QString fromUtf8(const QByteArray &str)
- { return str.isNull() ? QString() : fromUtf8(str.data(), str.size()); }
+ { return str.isNull() ? QString() : fromUtf8(str.data(), qstrnlen(str.constData(), str.size())); }
static inline QString fromLocal8Bit(const QByteArray &str)
- { return str.isNull() ? QString() : fromLocal8Bit(str.data(), str.size()); }
+ { return str.isNull() ? QString() : fromLocal8Bit(str.data(), qstrnlen(str.constData(), str.size())); }
static QString fromUtf16(const ushort *, int size = -1);
static QString fromUcs4(const uint *, int size = -1);
static QString fromRawData(const QChar *, int size);
@@ -655,7 +655,7 @@ public:
: d(fromAscii_helper(ch, ch ? int(strlen(ch)) : -1))
{}
inline QT_ASCII_CAST_WARN QString(const QByteArray &a)
- : d(fromAscii_helper(a.constData(), a.size()))
+ : d(fromAscii_helper(a.constData(), qstrnlen(a.constData(), a.size())))
{}
inline QT_ASCII_CAST_WARN QString &operator=(const char *ch)
{ return (*this = fromUtf8(ch)); }
@@ -1223,9 +1223,9 @@ inline QT_ASCII_CAST_WARN bool QLatin1String::operator>=(const QByteArray &s) co
{ return QString::fromUtf8(s) <= *this; }
inline QT_ASCII_CAST_WARN bool QString::operator==(const QByteArray &s) const
-{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) == 0; }
+{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) == 0; }
inline QT_ASCII_CAST_WARN bool QString::operator!=(const QByteArray &s) const
-{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) != 0; }
+{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) != 0; }
inline QT_ASCII_CAST_WARN bool QString::operator<(const QByteArray &s) const
{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) < 0; }
inline QT_ASCII_CAST_WARN bool QString::operator>(const QByteArray &s) const
@@ -1236,9 +1236,9 @@ inline QT_ASCII_CAST_WARN bool QString::operator>=(const QByteArray &s) const
{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) >= 0; }
inline bool QByteArray::operator==(const QString &s) const
-{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) == 0; }
+{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) == 0; }
inline bool QByteArray::operator!=(const QString &s) const
-{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) != 0; }
+{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) != 0; }
inline bool QByteArray::operator<(const QString &s) const
{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) > 0; }
inline bool QByteArray::operator>(const QString &s) const
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index 907dcf17e1..a922e3ad27 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -1148,7 +1148,7 @@ void tst_QString::constructorQByteArray_data()
ba1[5] = 'e';
ba1[6] = 'f';
- QTest::newRow( "2" ) << ba1 << QStringLiteral("abc\0def");
+ QTest::newRow( "2" ) << ba1 << QString("abc");
QTest::newRow( "3" ) << QByteArray::fromRawData("abcd", 3) << QString("abc");
QTest::newRow( "4" ) << QByteArray("\xc3\xa9") << QString("\xc3\xa9");
@@ -1169,6 +1169,12 @@ void tst_QString::constructorQByteArray()
QCOMPARE( strBA, expected );
// test operator= too
+ if (src.constData()[src.length()] == '\0') {
+ str1.clear();
+ str1 = src.constData();
+ QCOMPARE( str1, expected );
+ }
+
strBA.clear();
strBA = src;
QCOMPARE( strBA, expected );
@@ -2569,6 +2575,14 @@ void tst_QString::append_bytearray_special_cases()
QTEST( str, "res" );
}
+
+ QFETCH( QByteArray, ba );
+ if (ba.constData()[ba.length()] == '\0') {
+ QFETCH( QString, str );
+
+ str.append(ba.constData());
+ QTEST( str, "res" );
+ }
}
void tst_QString::operator_pluseq_data(bool emptyIsNoop)
@@ -2599,6 +2613,14 @@ void tst_QString::operator_pluseq_bytearray_special_cases()
QTEST( str, "res" );
}
+
+ QFETCH( QByteArray, ba );
+ if (ba.constData()[ba.length()] == '\0') {
+ QFETCH( QString, str );
+
+ str += ba.constData();
+ QTEST( str, "res" );
+ }
}
void tst_QString::operator_eqeq_bytearray_data()
@@ -2613,6 +2635,11 @@ void tst_QString::operator_eqeq_bytearray()
QVERIFY(expected == src);
QVERIFY(!(expected != src));
+
+ if (src.constData()[src.length()] == '\0') {
+ QVERIFY(expected == src.constData());
+ QVERIFY(!(expected != src.constData()));
+ }
}
void tst_QString::swap()
@@ -2670,7 +2697,7 @@ void tst_QString::prepend_bytearray_special_cases_data()
// byte array with only a 0
ba.resize( 1 );
ba[0] = 0;
- QTest::newRow( "emptyString" ) << QString("foobar ") << ba << QStringLiteral("\0foobar ");
+ QTest::newRow( "emptyString" ) << QString("foobar ") << ba << QString("foobar ");
// empty byte array
ba.resize( 0 );
@@ -2700,6 +2727,14 @@ void tst_QString::prepend_bytearray_special_cases()
QTEST( str, "res" );
}
+
+ QFETCH( QByteArray, ba );
+ if (ba.constData()[ba.length()] == '\0') {
+ QFETCH( QString, str );
+
+ str.prepend(ba.constData());
+ QTEST( str, "res" );
+ }
}
void tst_QString::replace_uint_uint()