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 "qbinaryjsonarray_p.h" |
5 | #include "qbinaryjson_p.h" |
6 | |
7 | #include <qjsonarray.h> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | QBinaryJsonArray::~QBinaryJsonArray() |
12 | { |
13 | if (d && !d->ref.deref()) |
14 | delete d; |
15 | } |
16 | |
17 | QBinaryJsonArray QBinaryJsonArray::fromJsonArray(const QJsonArray &array) |
18 | { |
19 | QBinaryJsonArray binary; |
20 | for (const QJsonValue value : array) |
21 | binary.append(value: QBinaryJsonValue::fromJsonValue(json: 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 | |
28 | void QBinaryJsonArray::append(const QBinaryJsonValue &value) |
29 | { |
30 | const uint i = a ? a->length() : 0; |
31 | |
32 | bool compressed; |
33 | uint valueSize = QBinaryJsonPrivate::Value::requiredStorage(v: value, compressed: &compressed); |
34 | |
35 | if (!detach(reserve: valueSize + sizeof(QBinaryJsonPrivate::Value))) |
36 | return; |
37 | |
38 | if (!a->length()) |
39 | a->tableOffset = sizeof(QBinaryJsonPrivate::Array); |
40 | |
41 | uint valueOffset = a->reserveSpace(dataSize: valueSize, posInTable: i, numItems: 1, replace: false); |
42 | if (!valueOffset) |
43 | return; |
44 | |
45 | QBinaryJsonPrivate::Value *v = a->at(i); |
46 | v->setType(value.t == QJsonValue::Undefined ? QJsonValue::Null : value.t); |
47 | v->setIsLatinOrIntValue(compressed); |
48 | v->setIsLatinKey(false); |
49 | v->setValue(QBinaryJsonPrivate::Value::valueToStore(v: value, offset: valueOffset)); |
50 | if (valueSize) { |
51 | QBinaryJsonPrivate::Value::copyData(v: value, dest: reinterpret_cast<char *>(a) + valueOffset, |
52 | compressed); |
53 | } |
54 | } |
55 | |
56 | char *QBinaryJsonArray::takeRawData(uint *size) |
57 | { |
58 | if (d) |
59 | return d->takeRawData(size); |
60 | *size = 0; |
61 | return nullptr; |
62 | } |
63 | |
64 | bool QBinaryJsonArray::detach(uint reserve) |
65 | { |
66 | if (!d) { |
67 | if (reserve >= QBinaryJsonPrivate::Value::MaxSize) { |
68 | qWarning(msg: "QBinaryJson: Document too large to store in data structure"); |
69 | return false; |
70 | } |
71 | d = new QBinaryJsonPrivate::MutableData(reserve, QJsonValue::Array); |
72 | a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root()); |
73 | d->ref.ref(); |
74 | return true; |
75 | } |
76 | if (reserve == 0 && d->ref.loadRelaxed() == 1) |
77 | return true; |
78 | |
79 | QBinaryJsonPrivate::MutableData *x = d->clone(b: a, reserve); |
80 | if (!x) |
81 | return false; |
82 | x->ref.ref(); |
83 | if (!d->ref.deref()) |
84 | delete d; |
85 | d = x; |
86 | a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root()); |
87 | return true; |
88 | } |
89 | |
90 | void QBinaryJsonArray::compact() |
91 | { |
92 | if (!d || !d->compactionCounter) |
93 | return; |
94 | |
95 | detach(); |
96 | d->compact(); |
97 | a = static_cast<QBinaryJsonPrivate::Array *>(d->header->root()); |
98 | } |
99 | |
100 | QT_END_NAMESPACE |
101 | |
102 |