diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2011-12-08 11:07:35 +0100 |
---|---|---|
committer | Hicks James <jamey.hicks@nokia.com> | 2011-12-08 15:20:40 +0100 |
commit | 3105e87528a0ba786ef6b15265dec5e597317dac (patch) | |
tree | 5997a4c50c33112b42c5a905e7c1e14a4bfaadc4 | |
parent | d168fcbfdc0e9d5357209a0e7f06a6b8c02308a8 (diff) |
Add an explicit UndefinedValue type
The type is required to distinguish between a null
entry and a non existant entry in objects and arrays.
Now trying to read a non existant key or an out of
bounds value in the array will return an undefined
JsonValue.
Also added a private constructor to JsonValue to
avoid implicit conversions from const char * to bool
when constructing values.
Change-Id: Icbb065503af0eb828f8c1fc681b329be8b23cb46
Reviewed-by: Hicks James <jamey.hicks@nokia.com>
-rw-r--r-- | src/qjsonarray.cpp | 6 | ||||
-rw-r--r-- | src/qjsonglobal.h | 3 | ||||
-rw-r--r-- | src/qjsonobject.cpp | 11 | ||||
-rw-r--r-- | src/qjsonvalue.cpp | 9 | ||||
-rw-r--r-- | src/qjsonvalue.h | 7 | ||||
-rw-r--r-- | tests/auto/tst_qtjson.cpp | 57 |
6 files changed, 65 insertions, 28 deletions
diff --git a/src/qjsonarray.cpp b/src/qjsonarray.cpp index 6c54cb6..b9a0dd2 100644 --- a/src/qjsonarray.cpp +++ b/src/qjsonarray.cpp @@ -94,7 +94,7 @@ bool JsonArray::isEmpty() const JsonValue JsonArray::at(int i) const { if (!a || i < 0 || i >= (int)a->length) - return JsonValue(); + return JsonValue(UndefinedValue); return JsonValue(d, a, a->at(i)); } @@ -127,7 +127,7 @@ void JsonArray::removeAt(int i) JsonValue JsonArray::takeAt(int i) { if (!a || i < 0 || i >= (int)a->length) - return JsonValue(); + return JsonValue(UndefinedValue); detach(); @@ -153,7 +153,7 @@ void JsonArray::insert(int i, const JsonValue &value) int valueOffset = a->reserveSpace(valueSize, i, 1); Value &v = (*a)[i]; - v.type = value.t; + v.type = (value.t == UndefinedValue ? NullValue : value.t); v.compressed = compressed; v.val = value.valueToStore(valueOffset); if (valueSize) diff --git a/src/qjsonglobal.h b/src/qjsonglobal.h index 09cc9fb..970a8f2 100644 --- a/src/qjsonglobal.h +++ b/src/qjsonglobal.h @@ -27,7 +27,8 @@ namespace QtJson NumberValue = 0x2, StringValue = 0x3, ArrayValue = 0x4, - ObjectValue = 0x5 + ObjectValue = 0x5, + UndefinedValue = 0x80 }; } diff --git a/src/qjsonobject.cpp b/src/qjsonobject.cpp index 0b02dea..209a5d7 100644 --- a/src/qjsonobject.cpp +++ b/src/qjsonobject.cpp @@ -136,7 +136,7 @@ JsonValue JsonObject::value(const QString &key) const return JsonValue(d, o, e->value); } } - return JsonValue(); + return JsonValue(UndefinedValue); } static bool useCompressed(const QString &s) @@ -155,6 +155,11 @@ static bool useCompressed(const QString &s) void JsonObject::insert(const QString &key, const JsonValue &value) { + if (value.t == UndefinedValue) { + remove(key); + return; + } + bool compressed; int valueSize = value.requiredStorage(&compressed); @@ -208,11 +213,11 @@ void JsonObject::remove(const QString &key) JsonValue JsonObject::take(const QString &key) { if (!o) - return JsonValue(); + return JsonValue(UndefinedValue); int index = o->indexOf(key); if (index < 0) - return JsonValue(); + return JsonValue(UndefinedValue); Entry *e = o->entryAt(index); o->removeItems(index, 1); diff --git a/src/qjsonvalue.cpp b/src/qjsonvalue.cpp index 2527500..15d248a 100644 --- a/src/qjsonvalue.cpp +++ b/src/qjsonvalue.cpp @@ -12,8 +12,8 @@ using namespace QtJson; static const Base emptyBase = { sizeof(Base), 0, 0, 0 }; -JsonValue::JsonValue() - : t(NullValue), d(0), dbl(0.) +JsonValue::JsonValue(ValueType type) + : t(type), d(0), dbl(0.) { } @@ -22,6 +22,7 @@ JsonValue::JsonValue(Data *data, Base *base, const Value &v) { t = (ValueType)v.type; switch (t) { + case UndefinedValue: case NullValue: dbl = 0; break; @@ -191,6 +192,7 @@ QVariant JsonValue::toVariant() const case ObjectValue: return JsonObject(d, object).toVariantMap(); case NullValue: + case UndefinedValue: break; } return QVariant(); @@ -288,6 +290,7 @@ bool JsonValue::operator==(const JsonValue &other) const return false; switch (t) { + case UndefinedValue: case NullValue: break; case BooleanValue: @@ -347,6 +350,7 @@ int JsonValue::requiredStorage(bool *compressed) const return array ? array->size : sizeof(Array); case ObjectValue: return object ? object->size : sizeof(Object); + case UndefinedValue: case NullValue: case BooleanValue: break; @@ -357,6 +361,7 @@ int JsonValue::requiredStorage(bool *compressed) const uint JsonValue::valueToStore(uint offset) const { switch (t) { + case UndefinedValue: case NullValue: break; case BooleanValue: diff --git a/src/qjsonvalue.h b/src/qjsonvalue.h index 74f2702..6ace201 100644 --- a/src/qjsonvalue.h +++ b/src/qjsonvalue.h @@ -9,7 +9,7 @@ namespace QtJson { class JsonValue { public: - JsonValue(); + JsonValue(ValueType = NullValue); JsonValue(bool b); JsonValue(double n); JsonValue(int n); @@ -27,8 +27,7 @@ public: QVariant toVariant() const; ValueType type() const; - -// template <> value() const; + inline bool isUndefined() const { return type() == UndefinedValue; } void setValue(bool); void setValue(double); @@ -51,6 +50,8 @@ public: void detach(); private: + // avoid implicit conversions from char * to bool + inline JsonValue(const void *) {} friend class Data; friend class Value; friend class JsonArray; diff --git a/tests/auto/tst_qtjson.cpp b/tests/auto/tst_qtjson.cpp index da1cc57..8926a4c 100644 --- a/tests/auto/tst_qtjson.cpp +++ b/tests/auto/tst_qtjson.cpp @@ -73,6 +73,8 @@ private Q_SLOTS: void nullArrays(); void nullObject(); + void undefinedValues(); + void fromVariantMap(); void toVariantMap(); @@ -163,7 +165,7 @@ void TestQtJson::testObjectSimple() // if we put a JsonValue into the JsonObject and retreive // it, it should be identical. - JsonValue value("foo"); + JsonValue value(QLatin1String("foo")); object.insert("value", value); QCOMPARE(object.value("value"), value); @@ -196,7 +198,7 @@ void TestQtJson::testArraySimple() // if we put a JsonValue into the JsonArray and retreive // it, it should be identical. - JsonValue value("foo"); + JsonValue value(QLatin1String("foo")); array.append(value); QCOMPARE(array.at(3), value); @@ -217,15 +219,15 @@ void TestQtJson::testArraySimple() QCOMPARE(array.last().type(), NullValue); QCOMPARE(array.last(), JsonValue()); - QCOMPARE(array.at(-1), JsonValue()); - QCOMPARE(array.at(array.size()), JsonValue()); + QCOMPARE(array.at(-1), JsonValue(UndefinedValue)); + QCOMPARE(array.at(array.size()), JsonValue(UndefinedValue)); } void TestQtJson::testValueObject() { JsonObject object; object.insert("number", 999.); - object.insert("string", "test"); + object.insert("string", QLatin1String("test")); object.insert("boolean", true); JsonValue value(object); @@ -243,7 +245,7 @@ void TestQtJson::testValueArray() { JsonArray array; array.append(999.); - array.append("test"); + array.append(QLatin1String("test")); array.append(true); JsonValue value(array); @@ -253,7 +255,7 @@ void TestQtJson::testValueArray() QCOMPARE(value.toArray(), array); // if we modify the original array, it should detach - array.append("test"); + array.append(QLatin1String("test")); QVERIFY2(value.toArray() != array, "array should have detached"); } @@ -379,7 +381,7 @@ void TestQtJson::testDocument() QCOMPARE(doc.isEmpty(), false); QCOMPARE(doc.type(), ObjectValue); - object.insert(QLatin1String("Key"), "Value"); + object.insert(QLatin1String("Key"), QLatin1String("Value")); doc.setObject(object); QCOMPARE(doc.isEmpty(), false); QCOMPARE(doc.type(), ObjectValue); @@ -429,9 +431,9 @@ void TestQtJson::nullArrays() QVERIFY(nonNull != nullArray); QCOMPARE(nullArray.size(), 0); - QCOMPARE(nullArray.takeAt(0), JsonValue()); - QCOMPARE(nullArray.first(), JsonValue()); - QCOMPARE(nullArray.last(), JsonValue()); + QCOMPARE(nullArray.takeAt(0), JsonValue(UndefinedValue)); + QCOMPARE(nullArray.first(), JsonValue(UndefinedValue)); + QCOMPARE(nullArray.last(), JsonValue(UndefinedValue)); nullArray.removeAt(0); nullArray.removeAt(-1); @@ -439,9 +441,9 @@ void TestQtJson::nullArrays() nullArray.removeAt(0); QCOMPARE(nullArray.size(), 0); - QCOMPARE(nullArray.takeAt(0), JsonValue()); - QCOMPARE(nullArray.first(), JsonValue()); - QCOMPARE(nullArray.last(), JsonValue()); + QCOMPARE(nullArray.takeAt(0), JsonValue(UndefinedValue)); + QCOMPARE(nullArray.first(), JsonValue(UndefinedValue)); + QCOMPARE(nullArray.last(), JsonValue(UndefinedValue)); nullArray.removeAt(0); nullArray.removeAt(-1); @@ -463,7 +465,7 @@ void TestQtJson::nullObject() QCOMPARE(nullObject.keys(), QStringList()); nullObject.remove("foo"); QCOMPARE(nullObject, JsonObject()); - QCOMPARE(nullObject.take("foo"), JsonValue()); + QCOMPARE(nullObject.take("foo"), JsonValue(UndefinedValue)); QCOMPARE(nullObject.contains("foo"), false); nullObject.detach(16); @@ -476,10 +478,33 @@ void TestQtJson::nullObject() QCOMPARE(nullObject.keys(), QStringList()); nullObject.remove("foo"); QCOMPARE(nullObject, JsonObject()); - QCOMPARE(nullObject.take("foo"), JsonValue()); + QCOMPARE(nullObject.take("foo"), JsonValue(UndefinedValue)); QCOMPARE(nullObject.contains("foo"), false); } +void TestQtJson::undefinedValues() +{ + JsonObject object; + object.insert("Key", JsonValue(UndefinedValue)); + QCOMPARE(object.numKeys(), 0); + + object.insert("Key", QLatin1String("Value")); + QCOMPARE(object.numKeys(), 1); + QCOMPARE(object.value("Key").type(), StringValue); + QCOMPARE(object.value("foo").type(), UndefinedValue); + object.insert("Key", JsonValue(UndefinedValue)); + QCOMPARE(object.numKeys(), 0); + QCOMPARE(object.value("Key").type(), UndefinedValue); + + JsonArray array; + array.append(JsonValue(UndefinedValue)); + QCOMPARE(array.size(), 1); + QCOMPARE(array.at(0).type(), NullValue); + + QCOMPARE(array.at(1).type(), UndefinedValue); + QCOMPARE(array.at(-1).type(), UndefinedValue); +} + void TestQtJson::fromVariantMap() { |