Fix bugs in internal comparison operators

The comparison operators between QJsonPrivate::String
and QJsonPrivate::Latin1String weren't all correct, leading
to wrong sorting of keys in QJsonObjects when the keys were
outside of the latin1 range and resulting lookup errors.

Task-number: QTBUG-41100
Change-Id: Idceff615f85d7ab874ad2a8e4a6c1ce8c2aa0f65
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
This commit is contained in:
Lars Knoll 2014-09-05 12:58:19 +02:00
parent 395d865b80
commit 853845a4a2
2 changed files with 44 additions and 3 deletions

View File

@ -354,7 +354,7 @@ public:
return !memcmp(d->utf16, str.d->utf16, d->length*sizeof(ushort)); return !memcmp(d->utf16, str.d->utf16, d->length*sizeof(ushort));
} }
inline bool operator<(const String &other) const; inline bool operator<(const String &other) const;
inline bool operator >=(const String &other) const { return other < *this; } inline bool operator >=(const String &other) const { return !(*this < other); }
inline QString toString() const { inline QString toString() const {
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
@ -414,12 +414,29 @@ public:
val = d->length - str.d->length; val = d->length - str.d->length;
return val >= 0; return val >= 0;
} }
inline bool operator<(const String &str) const
{
const qle_ushort *uc = (qle_ushort *) str.d->utf16;
if (!uc || *uc == 0)
return false;
const uchar *c = (uchar *)d->latin1;
const uchar *e = c + qMin((int)d->length, (int)str.d->length);
while (c < e) {
if (*c != *uc)
break;
++c;
++uc;
}
return (c == e ? (int)d->length < (int)str.d->length : *c < *uc);
}
inline bool operator ==(const String &str) const { inline bool operator ==(const String &str) const {
return (str == *this); return (str == *this);
} }
inline bool operator >=(const String &str) const { inline bool operator >=(const String &str) const {
return (str < *this); return !(*this < str);
} }
inline QString toString() const { inline QString toString() const {
@ -456,7 +473,7 @@ inline bool String::operator <(const String &other) const
a++,b++; a++,b++;
if (l==-1) if (l==-1)
return (alen < blen); return (alen < blen);
return (ushort)*a - (ushort)*b; return (ushort)*a < (ushort)*b;
} }
inline bool String::operator<(const Latin1String &str) const inline bool String::operator<(const Latin1String &str) const

View File

@ -149,6 +149,8 @@ private Q_SLOTS:
void arrayInitializerList(); void arrayInitializerList();
void objectInitializerList(); void objectInitializerList();
void unicodeKeys();
private: private:
QString testDataDir; QString testDataDir;
}; };
@ -2753,5 +2755,27 @@ void tst_QtJson::objectInitializerList()
#endif #endif
} }
void tst_QtJson::unicodeKeys()
{
QByteArray json = "{"
"\"x\u2090_1\": \"hello_1\","
"\"y\u2090_2\": \"hello_2\","
"\"T\u2090_3\": \"hello_3\","
"\"xyz_4\": \"hello_4\","
"\"abc_5\": \"hello_5\""
"}";
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(json, &error);
QVERIFY(error.error == QJsonParseError::NoError);
QJsonObject o = doc.object();
QCOMPARE(o.keys().size(), 5);
Q_FOREACH (const QString &key, o.keys()) {
QString suffix = key.mid(key.indexOf(QLatin1Char('_')));
QCOMPARE(o[key].toString(), QString("hello") + suffix);
}
}
QTEST_MAIN(tst_QtJson) QTEST_MAIN(tst_QtJson)
#include "tst_qtjson.moc" #include "tst_qtjson.moc"