diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2011-12-06 16:27:03 +0100 |
---|---|---|
committer | Simons Kevin <kevin.simons@nokia.com> | 2011-12-06 17:12:05 +0100 |
commit | 4cb4e4137bacd15c97f1107a99590ff871381e49 (patch) | |
tree | 904857515959d5235e9eebac31c697f10141a4b9 | |
parent | 5b0dfd8e2b5ed8c40a4b2accd15b2848e2ffec06 (diff) |
Add a JsonDocument class
A json document can contain either an Object
or an Array. Account for this here by having
a top level document class that tells about
the type of the Json document.
Change-Id: I81e55c68ff86895c57226538983cc9a95ee62e0c
Reviewed-by: Simons Kevin <kevin.simons@nokia.com>
-rw-r--r-- | src/qjson_p.h | 4 | ||||
-rw-r--r-- | src/qjsonarray.h | 1 | ||||
-rw-r--r-- | src/qjsondocument.cpp | 220 | ||||
-rw-r--r-- | src/qjsondocument.h | 49 | ||||
-rw-r--r-- | src/qjsonglobal.h | 1 | ||||
-rw-r--r-- | src/qjsonobject.cpp | 7 | ||||
-rw-r--r-- | src/qjsonobject.h | 1 | ||||
-rw-r--r-- | src/src.pro | 2 | ||||
-rw-r--r-- | tests/auto/tst_qtjson.cpp | 38 |
9 files changed, 316 insertions, 7 deletions
diff --git a/src/qjson_p.h b/src/qjson_p.h index 909b335..1fb16ef 100644 --- a/src/qjson_p.h +++ b/src/qjson_p.h @@ -196,9 +196,9 @@ struct Array : public Base struct Header { uint size; uint tag; // 'qbjs' - uint version; + uint type; uint unused; - Object root; + Base root; }; diff --git a/src/qjsonarray.h b/src/qjsonarray.h index 946040e..0c4c391 100644 --- a/src/qjsonarray.h +++ b/src/qjsonarray.h @@ -45,6 +45,7 @@ public: private: friend class Data; friend class JsonValue; + friend class JsonDocument; JsonArray(Data *data, Array *array); Data *d; Array *a; diff --git a/src/qjsondocument.cpp b/src/qjsondocument.cpp new file mode 100644 index 0000000..440e102 --- /dev/null +++ b/src/qjsondocument.cpp @@ -0,0 +1,220 @@ +#include <qjsondocument.h> +#include <qjsonobject.h> +#include <qjsonvalue.h> +#include <qjsonarray.h> +#include <qjson_p.h> +#include <qstringlist.h> + +using namespace QtJson; + +const uint QBJS_Tag = ('q' << 24) | ('b' << 16) | ('j' << 8) | 's'; + +JsonDocument::JsonDocument() + : d(0) +{ +} + +JsonDocument::JsonDocument(Data *data) + : d(data) +{ + Q_ASSERT(d); + d->ref.ref(); +} + + +JsonDocument::~JsonDocument() +{ + if (d && !d->ref.deref()) + delete d; +} + +JsonDocument::JsonDocument(const JsonDocument &other) +{ + d = other.d; + if (d) + d->ref.ref(); +} + +JsonDocument &JsonDocument::operator =(const JsonDocument &other) +{ + if (d != other.d) { + if (d && !d->ref.deref()) + delete d; + d = other.d; + if (d) + d->ref.ref(); + } + + return *this; +} + +JsonDocument JsonDocument::fromData(const QByteArray &data) +{ + Header *h = (Header *) data.constData(); + if (h->tag != QBJS_Tag || + h->size > (uint)data.size() || + (h->type != NullValue && + h->type != ObjectValue && + h->type != ArrayValue)) + return JsonDocument(); + + char *raw = (char *)malloc(data.size()); + memcpy(raw, data.constData(), data.size()); + Data *d = new Data(raw, data.size()); + + return JsonDocument(d); +} + +JsonDocument JsonDocument::fromVariant(const QVariant &map) +{ +// // ### this is implemented the trivial way, not the most efficient way + +// JsonDocument doc; +// for (QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it) +// object.insert(it.key(), JsonValue::fromVariant(it.value())); +// return object; +} + +QVariant JsonDocument::toVariant() const +{ +// QVariantMap map; +// for (uint i = 0; i < o->length; ++i) { +// Entry *e = o->entryAt(i); +// map.insert(e->key(), JsonValue(d, e->value()).toVariant()); +// } +// return map; +} + +QByteArray JsonDocument::toJson() const +{ + QByteArray json; +// json.reserve(o ? o->size/2 : 0); +// json += "{\n"; +// objectContentToJson(o, json, 1); +// json += "}\n"; + return json; +} + +bool JsonDocument::isEmpty() const +{ + if (!d) + return true; + + return false; +} + +QByteArray JsonDocument::binaryData() const +{ + if (!d || !d->rawData) + return QByteArray(); + + return QByteArray(d->rawData, d->_header->size); +} + +ValueType JsonDocument::type() const +{ + if (!d) + return NullValue; + + Header *h = (Header *)d->rawData; + return (ValueType)h->type; +} + +JsonObject JsonDocument::object() const +{ + if (d) { + Header *h = (Header *)d->rawData; + if (h->type == ObjectValue) + return JsonObject(d, static_cast<Object *>(&h->root)); + } + return JsonObject(); +} + +JsonArray JsonDocument::array() const +{ + if (d) { + Header *h = (Header *)d->rawData; + if (h->type == ArrayValue) + return JsonArray(d, static_cast<Array *>(&h->root)); + } + return JsonArray(); +} + +void JsonDocument::setObject(const JsonObject &object) +{ + Object *o = object.o; + int objectSize = o ? o->size : sizeof(Object); + int alloc = sizeof(Header) - sizeof(Base) + objectSize; + + Header *h = (Header *)malloc(alloc); + h->size = sizeof(Header); + h->tag = QBJS_Tag; + h->type = ObjectValue; + h->unused = 0; + if (o) { + memcpy(&h->root, o, o->size); + } else { + h->root.size = sizeof(Base); + h->root.length = 0; + h->root.unused = 0; + h->root.tableOffset = 0; + } + + *this = JsonDocument(new Data((char *)h, alloc)); +} + +void JsonDocument::setArray(const JsonArray &array) +{ + Array *a = array.a; + int arraySize = a ? a->size : sizeof(Array); + int alloc = sizeof(Header) - sizeof(Base) + arraySize; + + Header *h = (Header *)malloc(alloc); + h->size = sizeof(Header); + h->tag = ('q' << 24) | ('b' << 16) | ('j' << 8) | 's'; + h->type = ArrayValue; + h->unused = 0; + if (a) { + memcpy(&h->root, a, a->size); + } else { + h->root.size = sizeof(Base); + h->root.length = 0; + h->root.unused = 0; + h->root.tableOffset = 0; + } + + *this = JsonDocument(new Data((char *)h, alloc)); +} + + +bool JsonDocument::operator==(const JsonDocument &other) const +{ + if (d == other.d) + return true; + + if (!d) + return other.d->_header->type == NullValue; + if (!other.d) + return d->_header->type == NullValue; + if (d->_header->type != other.d->_header->type) + return false; + + switch (d->_header->type) { + case NullValue: + return true; + case ObjectValue: + return JsonObject(d, static_cast<Object *>(&d->_header->root)) + == JsonObject(other.d, static_cast<Object *>(&other.d->_header->root)); + case ArrayValue: + return JsonArray(d, static_cast<Array *>(&d->_header->root)) + == JsonArray(other.d, static_cast<Array *>(&other.d->_header->root)); + default: + break; + } + return false; +} + +bool JsonDocument::operator!=(const JsonDocument &other) const +{ + return !(*this == other); +} diff --git a/src/qjsondocument.h b/src/qjsondocument.h new file mode 100644 index 0000000..55d2511 --- /dev/null +++ b/src/qjsondocument.h @@ -0,0 +1,49 @@ +#ifndef QJSONDOCUMENT_H +#define QJSONDOCUMENT_H + +#include <qjsonglobal.h> +#include <qvariant.h> + +namespace QtJson { + +class JsonDocument +{ +public: + JsonDocument(); + ~JsonDocument(); + + JsonDocument(const JsonDocument &other); + JsonDocument &operator =(const JsonDocument &other); + + static JsonDocument fromData(const QByteArray &data); + static JsonDocument fromVariant(const QVariant &map); + + QVariant toVariant() const; + QByteArray toJson() const; + + QByteArray binaryData() const; + + bool isEmpty() const; + + ValueType type() const; + + JsonObject object() const; + JsonArray array() const; + + void setObject(const JsonObject &object); + void setArray(const JsonArray &array); + + bool operator==(const JsonDocument &other) const; + bool operator!=(const JsonDocument &other) const; + +private: + friend class Data; + friend class JsonValue; + JsonDocument(Data *data); + + Data *d; +}; + +} + +#endif // QJSONDOCUMENT_H diff --git a/src/qjsonglobal.h b/src/qjsonglobal.h index ee5ef82..0f67820 100644 --- a/src/qjsonglobal.h +++ b/src/qjsonglobal.h @@ -18,6 +18,7 @@ namespace QtJson class JsonValue; class JsonObject; class JsonArray; + class JsonDocument; enum ValueType { NullValue = 0x0, diff --git a/src/qjsonobject.cpp b/src/qjsonobject.cpp index 377a596..b624ebd 100644 --- a/src/qjsonobject.cpp +++ b/src/qjsonobject.cpp @@ -50,12 +50,9 @@ JsonObject &JsonObject::operator =(const JsonObject &other) JsonObject JsonObject::fromData(const QByteArray &data) { - Header *h = (Header *) data.constData(); - if (h->version != 0) + Object *o = (Object *) data.constData(); + if (o->size > (uint)data.size()) return JsonObject(); - if (h->size > (uint)data.size()) { - return JsonObject(); - } char *raw = (char *)malloc(data.size()); memcpy(raw, data.constData(), data.size()); diff --git a/src/qjsonobject.h b/src/qjsonobject.h index 21152e8..b26fe61 100644 --- a/src/qjsonobject.h +++ b/src/qjsonobject.h @@ -46,6 +46,7 @@ public: private: friend class Data; friend class JsonValue; + friend class JsonDocument; JsonObject(Data *data, Object *object); Data *d; diff --git a/src/src.pro b/src/src.pro index d9f906b..a9a688c 100644 --- a/src/src.pro +++ b/src/src.pro @@ -7,12 +7,14 @@ DESTDIR = ../lib HEADERS += \ qjson_p.h \ + qjsondocument.h \ qjsonobject.h \ qjsonglobal.h \ qjsonvalue.h \ qjsonarray.h SOURCES += \ + qjsondocument.cpp \ qjsonobject.cpp \ qjsonarray.cpp \ qjsonvalue.cpp diff --git a/tests/auto/tst_qtjson.cpp b/tests/auto/tst_qtjson.cpp index 87ddfa4..9fa1258 100644 --- a/tests/auto/tst_qtjson.cpp +++ b/tests/auto/tst_qtjson.cpp @@ -41,6 +41,7 @@ #include "qjsonarray.h" #include "qjsonobject.h" #include "qjsonvalue.h" +#include "qjsondocument.h" using namespace QtJson; @@ -66,6 +67,8 @@ private Q_SLOTS: void testArrayNestedEmpty(); void testObjectNestedEmpty(); + void testDocument(); + void nullValues(); void nullArrays(); void nullObject(); @@ -360,6 +363,41 @@ void TestQtJson::testObjectNestedEmpty() QCOMPARE(reconstituted.value("inner2").type(), ObjectValue); } +void TestQtJson::testDocument() +{ + JsonDocument doc; + QCOMPARE(doc.isEmpty(), true); + QCOMPARE(doc.type(), NullValue); + + JsonObject object; + doc.setObject(object); + QCOMPARE(doc.isEmpty(), false); + QCOMPARE(doc.type(), ObjectValue); + + object.insert(QLatin1String("Key"), "Value"); + doc.setObject(object); + QCOMPARE(doc.isEmpty(), false); + QCOMPARE(doc.type(), ObjectValue); + QVERIFY(doc.object() == object); + QVERIFY(doc.array() == JsonArray()); + + doc = JsonDocument(); + QCOMPARE(doc.isEmpty(), true); + QCOMPARE(doc.type(), NullValue); + + JsonArray array; + doc.setArray(array); + QCOMPARE(doc.isEmpty(), false); + QCOMPARE(doc.type(), ArrayValue); + + array.append(QLatin1String("Value")); + doc.setArray(array); + QCOMPARE(doc.isEmpty(), false); + QCOMPARE(doc.type(), ArrayValue); + QVERIFY(doc.array() == array); + QVERIFY(doc.object() == JsonObject()); +} + void TestQtJson::nullValues() { JsonArray array; |