QJsonObject: add some overloads taking QLatin1String

QXmlStreamReader also has QLatin1String overloads, which
greatly benefits parsers, since the vast majority of keys
in both JSON and XML are US-ASCII. This patch adds such an
overload to the JSON parser.

The value() function is all typical parsers need, so even
though many more QJsonObject functions taking QString could
benefit from the same treatment, value() is the single most
important one for read-only JSON access.

Add some more overloads, too, for functions that don't need
more internal scaffolding than value(). Requires adding a
dummy op[](QL1S) (forwarding to the QString overload) so as
not to make

  QJsonObject json;
  json[QLatin1String("key")]; // mutable

ambiguous between const op[](QL1S) and mutable op[](QString).

[ChangeLog][QtCore][QJsonObject] Added value(), op[] const,
find(), constFind(), contains() overloads taking QLatin1String.

Change-Id: I00883028956ad949ba5ba2b18dd8a6a25ad5085b
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
This commit is contained in:
Marc Mutz 2016-04-28 09:40:49 +02:00
parent 5e51b15066
commit a5159cc50a
5 changed files with 145 additions and 11 deletions

View File

@ -179,7 +179,29 @@ void Base::removeItems(int pos, int numItems)
length -= numItems;
}
int Object::indexOf(const QString &key, bool *exists)
int Object::indexOf(const QString &key, bool *exists) const
{
int min = 0;
int n = length;
while (n > 0) {
int half = n >> 1;
int middle = min + half;
if (*entryAt(middle) >= key) {
n = half;
} else {
min = middle + 1;
n -= half + 1;
}
}
if (min < (int)length && *entryAt(min) == key) {
*exists = true;
return min;
}
*exists = false;
return min;
}
int Object::indexOf(QLatin1String key, bool *exists) const
{
int min = 0;
int n = length;
@ -248,6 +270,14 @@ bool Entry::operator ==(const QString &key) const
return (shallowKey() == key);
}
bool Entry::operator==(QLatin1String key) const
{
if (value.latinKey)
return shallowLatin1Key() == key;
else
return shallowKey() == key;
}
bool Entry::operator ==(const Entry &other) const
{
if (value.latinKey) {

View File

@ -573,7 +573,8 @@ public:
Entry *entryAt(int i) const {
return reinterpret_cast<Entry *>(((char *)this) + table()[i]);
}
int indexOf(const QString &key, bool *exists);
int indexOf(const QString &key, bool *exists) const;
int indexOf(QLatin1String key, bool *exists) const;
bool isValid() const;
};
@ -675,6 +676,10 @@ public:
inline bool operator !=(const QString &key) const { return !operator ==(key); }
inline bool operator >=(const QString &key) const;
bool operator==(QLatin1String key) const;
inline bool operator!=(QLatin1String key) const { return !operator ==(key); }
inline bool operator>=(QLatin1String key) const;
bool operator ==(const Entry &other) const;
bool operator >=(const Entry &other) const;
};
@ -687,9 +692,20 @@ inline bool Entry::operator >=(const QString &key) const
return (shallowKey() >= key);
}
inline bool Entry::operator >=(QLatin1String key) const
{
if (value.latinKey)
return shallowLatin1Key() >= key;
else
return shallowKey() >= key;
}
inline bool operator <(const QString &key, const Entry &e)
{ return e >= key; }
inline bool operator<(QLatin1String key, const Entry &e)
{ return e >= key; }
class Header {
public:

View File

@ -374,6 +374,22 @@ QJsonValue QJsonObject::value(const QString &key) const
return QJsonValue(d, o, o->entryAt(i)->value);
}
/*!
\overload
\since 5.7
*/
QJsonValue QJsonObject::value(QLatin1String key) const
{
if (!d)
return QJsonValue(QJsonValue::Undefined);
bool keyExists;
int i = o->indexOf(key, &keyExists);
if (!keyExists)
return QJsonValue(QJsonValue::Undefined);
return QJsonValue(d, o, o->entryAt(i)->value);
}
/*!
Returns a QJsonValue representing the value for the key \a key.
@ -388,6 +404,13 @@ QJsonValue QJsonObject::operator [](const QString &key) const
return value(key);
}
/*!
\fn QJsonValue QJsonObject::operator [](QLatin1String key) const
\overload
\since 5.7
*/
/*!
Returns a reference to the value for \a key.
@ -411,6 +434,16 @@ QJsonValueRef QJsonObject::operator [](const QString &key)
return QJsonValueRef(this, index);
}
/*!
\overload
\since 5.7
*/
QJsonValueRef QJsonObject::operator [](QLatin1String key)
{
// ### optimize me
return operator[](QString(key));
}
/*!
Inserts a new item with the key \a key and a value of \a value.
@ -535,6 +568,20 @@ bool QJsonObject::contains(const QString &key) const
return keyExists;
}
/*!
\overload
\since 5.7
*/
bool QJsonObject::contains(QLatin1String key) const
{
if (!o)
return false;
bool keyExists;
o->indexOf(key, &keyExists);
return keyExists;
}
/*!
Returns \c true if \a other is equal to this object.
*/
@ -609,11 +656,31 @@ QJsonObject::iterator QJsonObject::find(const QString &key)
return iterator(this, index);
}
/*!
\overload
\since 5.7
*/
QJsonObject::iterator QJsonObject::find(QLatin1String key)
{
bool keyExists = false;
int index = o ? o->indexOf(key, &keyExists) : 0;
if (!keyExists)
return end();
detach2();
return iterator(this, index);
}
/*! \fn QJsonObject::const_iterator QJsonObject::find(const QString &key) const
\overload
*/
/*! \fn QJsonObject::const_iterator QJsonObject::find(QLatin1String key) const
\overload
\since 5.7
*/
/*!
Returns a const iterator pointing to the item with key \a key in the
map.
@ -630,6 +697,19 @@ QJsonObject::const_iterator QJsonObject::constFind(const QString &key) const
return const_iterator(this, index);
}
/*!
\overload
\since 5.7
*/
QJsonObject::const_iterator QJsonObject::constFind(QLatin1String key) const
{
bool keyExists = false;
int index = o ? o->indexOf(key, &keyExists) : 0;
if (!keyExists)
return end();
return const_iterator(this, index);
}
/*! \fn int QJsonObject::count() const
\overload

View File

@ -86,12 +86,16 @@ public:
bool isEmpty() const;
QJsonValue value(const QString &key) const;
QJsonValue value(QLatin1String key) const;
QJsonValue operator[] (const QString &key) const;
QJsonValue operator[] (QLatin1String key) const { return value(key); }
QJsonValueRef operator[] (const QString &key);
QJsonValueRef operator[] (QLatin1String key);
void remove(const QString &key);
QJsonValue take(const QString &key);
bool contains(const QString &key) const;
bool contains(QLatin1String key) const;
bool operator==(const QJsonObject &other) const;
bool operator!=(const QJsonObject &other) const;
@ -200,8 +204,11 @@ public:
typedef iterator Iterator;
typedef const_iterator ConstIterator;
iterator find(const QString &key);
iterator find(QLatin1String key);
const_iterator find(const QString &key) const { return constFind(key); }
const_iterator find(QLatin1String key) const { return constFind(key); }
const_iterator constFind(const QString &key) const;
const_iterator constFind(QLatin1String key) const;
iterator insert(const QString &key, const QJsonValue &value);
// STL compatibility

View File

@ -374,12 +374,13 @@ void tst_QtJson::testObjectSimple()
QJsonObject object;
object.insert("number", 999.);
QCOMPARE(object.value("number").type(), QJsonValue::Double);
QCOMPARE(object.value("number").toDouble(), 999.);
QCOMPARE(object.value(QLatin1String("number")).toDouble(), 999.);
object.insert("string", QString::fromLatin1("test"));
QCOMPARE(object.value("string").type(), QJsonValue::String);
QCOMPARE(object.value("string").toString(), QString("test"));
QCOMPARE(object.value(QLatin1String("string")).toString(), QString("test"));
object.insert("boolean", true);
QCOMPARE(object.value("boolean").toBool(), true);
QCOMPARE(object.value(QLatin1String("boolean")).toBool(), true);
QStringList keys = object.keys();
QVERIFY2(keys.contains("number"), "key number not found");
@ -403,7 +404,7 @@ void tst_QtJson::testObjectSimple()
QString before = object.value("string").toString();
object.insert("string", QString::fromLatin1("foo"));
QVERIFY2(object.value("string").toString() != before, "value should have been updated");
QVERIFY2(object.value(QLatin1String("string")).toString() != before, "value should have been updated");
size = object.size();
QJsonObject subobject;
@ -678,7 +679,7 @@ void tst_QtJson::testValueRef()
QCOMPARE(object.value(QLatin1String("null")), QJsonValue());
object[QLatin1String("null")] = 100.;
QCOMPARE(object.value(QLatin1String("null")).type(), QJsonValue::Double);
QJsonValue val = object[QLatin1String("null")];
QJsonValue val = qAsConst(object)[QLatin1String("null")];
QCOMPARE(val.toDouble(), 100.);
QCOMPARE(object.size(), 2);
@ -843,13 +844,13 @@ void tst_QtJson::testObjectFind()
QJsonObject::iterator it = object.find(QLatin1String("1"));
QCOMPARE((*it).toDouble(), 1.);
it = object.find(QLatin1String("11"));
it = object.find(QString("11"));
QCOMPARE((*it).type(), QJsonValue::Undefined);
QCOMPARE(it, object.end());
QJsonObject::const_iterator cit = object.constFind(QLatin1String("1"));
QCOMPARE((*cit).toDouble(), 1.);
cit = object.constFind(QLatin1String("11"));
cit = object.constFind(QString("11"));
QCOMPARE((*it).type(), QJsonValue::Undefined);
QCOMPARE(it, object.end());
}
@ -911,7 +912,7 @@ void tst_QtJson::testDocument()
doc3.setObject(outer.value(QLatin1String("innter")).toObject());
QCOMPARE(doc3.isArray(), false);
QCOMPARE(doc3.isObject(), true);
QVERIFY(doc3.object().contains(QLatin1String("innerKey")));
QVERIFY(doc3.object().contains(QString("innerKey")));
QCOMPARE(doc3.object().value(QLatin1String("innerKey")), QJsonValue(42));
QJsonDocument doc4(outer.value(QLatin1String("innterArray")).toArray());
@ -938,9 +939,9 @@ void tst_QtJson::nullValues()
QJsonObject object;
object.insert(QString("key"), QJsonValue());
QCOMPARE(object.contains("key"), true);
QCOMPARE(object.contains(QLatin1String("key")), true);
QCOMPARE(object.size(), 1);
QCOMPARE(object.value("key"), QJsonValue());
QCOMPARE(object.value(QString("key")), QJsonValue());
}
void tst_QtJson::nullArrays()