/**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include using namespace QtJson; JsonDocument::JsonDocument() : d(0) { } JsonDocument::JsonDocument(const JsonObject &object) : d(0) { setObject(object); } JsonDocument::JsonDocument(const JsonArray &array) : d(0) { setArray(array); } 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::fromBinaryData(const QByteArray &data) { Header *h = (Header *) data.constData(); if (data.size() < (int)(sizeof(Header) + sizeof(Base)) || h->tag != QBJS_Tag || h->version != 1u || sizeof(Header) + h->root()->size > (uint)data.size()) 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 &v) { JsonDocument doc; if (v.type() == QVariant::Map) { doc.setObject(JsonObject::fromVariantMap(v.toMap())); } else if (v.type() == QVariant::List) { doc.setArray(JsonArray::fromVariantList(v.toList())); } else if (v.type() == QVariant::StringList) { doc.setArray(JsonArray::fromStringList(v.toStringList())); } return doc; } QVariant JsonDocument::toVariant() const { if (!d) return QVariant(); if (d->header->root()->isArray()) return JsonArray(d, static_cast(d->header->root())).toVariantList(); else return JsonObject(d, static_cast(d->header->root())).toVariantMap(); } QByteArray JsonDocument::toJson() const { if (!d) return QByteArray(); QByteArray json; if (d->header->root()->isArray()) QJsonWriter::arrayToJson(static_cast(d->header->root()), json, 0); else QJsonWriter::objectToJson(static_cast(d->header->root()), json, 0); return json; } JsonDocument JsonDocument::fromJson(const QByteArray &json) { QJsonParser parser(json.constData(), json.length()); return parser.parse(); } bool JsonDocument::isEmpty() const { if (!d) return true; return false; } QByteArray JsonDocument::toBinaryData() const { if (!d || !d->rawData) return QByteArray(); return QByteArray(d->rawData, d->header->root()->size + sizeof(Header)); } ValueType JsonDocument::type() const { if (!d) return NullValue; Header *h = (Header *)d->rawData; return h->root()->isArray() ? ArrayValue : ObjectValue; } JsonObject JsonDocument::object() const { if (d) { Base *b = d->header->root(); if (b->isObject()) return JsonObject(d, static_cast(b)); } return JsonObject(); } JsonArray JsonDocument::array() const { if (d) { Base *b = d->header->root(); if (b->isArray()) return JsonArray(d, static_cast(b)); } return JsonArray(); } void JsonDocument::setObject(const JsonObject &object) { if (d && !d->ref.deref()) delete d; d = object.d; if (!d) { d = new Data(0, ObjectValue); } else if (d->compactionCounter) { object.compact(); d = object.d; } else if (object.o != d->header->root()) { JsonObject detached(object); detached.detach(); d = detached.d; d->ref.ref(); return; } d->ref.ref(); } void JsonDocument::setArray(const JsonArray &array) { if (d && !d->ref.deref()) delete d; d = array.d; if (!d) { d = new Data(0, ArrayValue); } else if (d->compactionCounter) { array.compact(); d = array.d; } else if (array.a != d->header->root()) { JsonArray detached(array); detached.detach(); d = detached.d; d->ref.ref(); return; } d->ref.ref(); } bool JsonDocument::operator==(const JsonDocument &other) const { if (d == other.d) return true; if (!d || !other.d) return false; if (d->header->root()->isArray() != other.d->header->root()->isArray()) return false; if (d->header->root()->isArray()) return JsonObject(d, static_cast(d->header->root())) == JsonObject(other.d, static_cast(other.d->header->root())); else return JsonArray(d, static_cast(d->header->root())) == JsonArray(other.d, static_cast(other.d->header->root())); } bool JsonDocument::operator!=(const JsonDocument &other) const { return !(*this == other); } bool JsonDocument::isValid() { if (!d) return false; if (d->valid == Data::Unchecked) // Unchecked, check for validity d->validate(); if (d->valid != Data::Validated) { if (!d->ref.deref()) delete d; d = 0; } return d != 0; }