summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2011-12-06 16:27:03 +0100
committerSimons Kevin <kevin.simons@nokia.com>2011-12-06 17:12:05 +0100
commit4cb4e4137bacd15c97f1107a99590ff871381e49 (patch)
tree904857515959d5235e9eebac31c697f10141a4b9
parent5b0dfd8e2b5ed8c40a4b2accd15b2848e2ffec06 (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.h4
-rw-r--r--src/qjsonarray.h1
-rw-r--r--src/qjsondocument.cpp220
-rw-r--r--src/qjsondocument.h49
-rw-r--r--src/qjsonglobal.h1
-rw-r--r--src/qjsonobject.cpp7
-rw-r--r--src/qjsonobject.h1
-rw-r--r--src/src.pro2
-rw-r--r--tests/auto/tst_qtjson.cpp38
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;