1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qbinaryjsonobject_p.h"
5#include "qbinaryjson_p.h"
6
7#include <qjsonobject.h>
8
9QT_BEGIN_NAMESPACE
10
11QBinaryJsonObject::~QBinaryJsonObject()
12{
13 if (d && !d->ref.deref())
14 delete d;
15}
16
17QBinaryJsonObject QBinaryJsonObject::fromJsonObject(const QJsonObject &object)
18{
19 QBinaryJsonObject binary;
20 for (auto it = object.begin(), end = object.end(); it != end; ++it)
21 binary.insert(key: it.key(), value: QBinaryJsonValue::fromJsonValue(json: it.value()));
22 if (binary.d) // We want to compact it as it is a root item now
23 binary.d->compactionCounter++;
24 binary.compact();
25 return binary;
26}
27
28void QBinaryJsonObject::insert(const QString &key, const QBinaryJsonValue &value)
29{
30 bool latinOrIntValue;
31 uint valueSize = QBinaryJsonPrivate::Value::requiredStorage(v: value, compressed: &latinOrIntValue);
32
33 bool latinKey = QBinaryJsonPrivate::useCompressed(s: key);
34 uint valueOffset = sizeof(QBinaryJsonPrivate::Entry)
35 + QBinaryJsonPrivate::qStringSize(string: key, compress: latinKey);
36 uint requiredSize = valueOffset + valueSize;
37
38 if (!detach(reserve: requiredSize + sizeof(QBinaryJsonPrivate::offset))) // offset for the new index entry
39 return;
40
41 if (!o->length())
42 o->tableOffset = sizeof(QBinaryJsonPrivate::Object);
43
44 bool keyExists = false;
45 uint pos = o->indexOf(key, exists: &keyExists);
46 if (keyExists)
47 ++d->compactionCounter;
48
49 uint off = o->reserveSpace(dataSize: requiredSize, posInTable: pos, numItems: 1, replace: keyExists);
50 if (!off)
51 return;
52
53 QBinaryJsonPrivate::Entry *e = o->entryAt(i: pos);
54 e->value.setType(value.t);
55 e->value.setIsLatinKey(latinKey);
56 e->value.setIsLatinOrIntValue(latinOrIntValue);
57 e->value.setValue(QBinaryJsonPrivate::Value::valueToStore(
58 v: value, offset: reinterpret_cast<char *>(e) - reinterpret_cast<char *>(o) + valueOffset));
59 QBinaryJsonPrivate::copyString(dest: reinterpret_cast<char *>(e + 1), str: key, compress: latinKey);
60 if (valueSize) {
61 QBinaryJsonPrivate::Value::copyData(v: value, dest: reinterpret_cast<char *>(e) + valueOffset,
62 compressed: latinOrIntValue);
63 }
64
65 if (d->compactionCounter > 32U && d->compactionCounter >= unsigned(o->length()) / 2U)
66 compact();
67}
68
69char *QBinaryJsonObject::takeRawData(uint *size) const
70{
71 if (d)
72 return d->takeRawData(size);
73 *size = 0;
74 return nullptr;
75}
76
77bool QBinaryJsonObject::detach(uint reserve)
78{
79 if (!d) {
80 if (reserve >= QBinaryJsonPrivate::Value::MaxSize) {
81 qWarning(msg: "QBinaryJson: Document too large to store in data structure");
82 return false;
83 }
84 d = new QBinaryJsonPrivate::MutableData(reserve, QJsonValue::Object);
85 o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
86 d->ref.ref();
87 return true;
88 }
89 if (reserve == 0 && d->ref.loadRelaxed() == 1)
90 return true;
91
92 QBinaryJsonPrivate::MutableData *x = d->clone(b: o, reserve);
93 if (!x)
94 return false;
95 x->ref.ref();
96 if (!d->ref.deref())
97 delete d;
98 d = x;
99 o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
100 return true;
101}
102
103void QBinaryJsonObject::compact()
104{
105 if (!d || !d->compactionCounter)
106 return;
107
108 detach();
109 d->compact();
110 o = static_cast<QBinaryJsonPrivate::Object *>(d->header->root());
111}
112
113QT_END_NAMESPACE
114

source code of qt5compat/src/core5/serialization/qbinaryjsonobject.cpp