blob: 01b653c71a2c6fc467bb20310d00659dcaf9830d [file] [log] [blame]
Jose Fonsecac296a3e2015-05-01 17:43:54 +01001/**************************************************************************
2 *
3 * Copyright 2015 VMware, Inc
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 **************************************************************************/
25
26
27#include "qubjson.h"
28
29#include <QDebug>
30#include <QVariant>
31#include <QJsonArray>
Jose Fonseca8a5f0ed2015-05-20 16:17:50 +010032#include <QDataStream>
Jose Fonsecac296a3e2015-05-01 17:43:54 +010033
34#include "ubjson.hpp"
35
36
37using namespace ubjson;
38
39
40static Marker
41readMarker(QDataStream &stream)
42{
Jose Fonsecae2e4c362015-05-21 16:12:22 +010043 if (stream.atEnd()) {
44 return MARKER_EOF;
45 }
Jose Fonsecac296a3e2015-05-01 17:43:54 +010046 quint8 byte;
47 stream >> byte;
Jose Fonsecae2e4c362015-05-21 16:12:22 +010048 return static_cast<Marker>(byte);
Jose Fonsecac296a3e2015-05-01 17:43:54 +010049}
50
51
52static int8_t
53readInt8(QDataStream &stream)
54{
Jose Fonseca46b88772015-05-19 16:52:10 +010055 qint8 i;
56 stream >> i;
57 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010058}
59
60static uint8_t
61readUInt8(QDataStream &stream)
62{
Jose Fonseca46b88772015-05-19 16:52:10 +010063 quint8 u;
64 stream >> u;
65 return u;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010066}
67
68static int16_t
69readInt16(QDataStream &stream)
70{
Jose Fonseca46b88772015-05-19 16:52:10 +010071 qint16 i;
72 stream >> i;
73 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010074}
75
76static int32_t
77readInt32(QDataStream &stream)
78{
Jose Fonseca46b88772015-05-19 16:52:10 +010079 qint32 i;
80 stream >> i;
81 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010082}
83
84static int64_t
85readInt64(QDataStream &stream)
86{
Jose Fonseca46b88772015-05-19 16:52:10 +010087 qint64 i;
88 stream >> i;
89 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010090}
91
92static float
93readFloat32(QDataStream &stream)
94{
Jose Fonseca46b88772015-05-19 16:52:10 +010095 float f;
96 stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
97 stream >> f;
98 return f;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010099}
100
101static float
102readFloat64(QDataStream &stream)
103{
Jose Fonseca46b88772015-05-19 16:52:10 +0100104 double f;
105 stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
106 stream >> f;
107 return f;
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100108}
109
110
111static size_t
112readSize(QDataStream &stream)
113{
114 Marker type = readMarker(stream);
115 switch (type) {
116 case MARKER_INT8:
117 return readInt8(stream);
118 case MARKER_UINT8:
119 return readUInt8(stream);
120 case MARKER_INT16:
121 return readInt16(stream);
122 case MARKER_INT32:
123 return readInt32(stream);
124 case MARKER_INT64:
125 return readInt64(stream);
126 default:
127 Q_UNIMPLEMENTED();
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100128 case MARKER_EOF:
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100129 return 0;
130 }
131}
132
133
134static QString
135readString(QDataStream &stream)
136{
137 size_t size = readSize(stream);
138 char *buf = new char [size];
139 stream.readRawData(buf, size);
140 QString str = QString::fromLocal8Bit(buf, size);
141 free(buf);
142 return str;
143}
144
145
146static QVariant
147readVariant(QDataStream &stream, Marker type);
148
149
150static QVariant
151readArray(QDataStream &stream)
152{
153 Marker marker = readMarker(stream);
154 if (marker == MARKER_TYPE) {
155 Marker type = readMarker(stream);
156 Q_ASSERT(type == MARKER_UINT8);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100157 Q_UNUSED(type);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100158 marker = readMarker(stream);
159 Q_ASSERT(marker == MARKER_COUNT);
160 size_t count = readSize(stream);
161 QByteArray array(count, Qt::Uninitialized);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100162 int read = stream.readRawData(array.data(), count);
163 Q_ASSERT(read == count);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100164 Q_UNUSED(read);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100165 marker = readMarker(stream);
166 Q_ASSERT(marker == MARKER_ARRAY_END);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100167 Q_UNUSED(marker);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100168 return array;
169 } else {
170 Q_ASSERT(marker != MARKER_COUNT);
171 QVariantList array;
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100172 while (marker != MARKER_ARRAY_END &&
173 marker != MARKER_EOF) {
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100174 QVariant value = readVariant(stream, marker);
175 array.append(value);
176 marker = readMarker(stream);
177 }
178 return array;
179 }
180}
181
182
183static QVariantMap
184readObject(QDataStream &stream)
185{
186 QVariantMap object;
187 Marker marker = readMarker(stream);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100188 while (marker != MARKER_OBJECT_END &&
189 marker != MARKER_EOF) {
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100190 Q_ASSERT(marker == MARKER_STRING);
191 QString name = readString(stream);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100192 marker = readMarker(stream);
193 QVariant value = readVariant(stream, marker);
194 object[name] = value;
195 marker = readMarker(stream);
196 }
197 return object;
198}
199
200
201static QVariant
202readVariant(QDataStream &stream, Marker type)
203{
204 switch (type) {
205 case MARKER_NULL:
206 return QVariant();
207 case MARKER_NOOP:
208 return QVariant();
209 case MARKER_TRUE:
210 return true;
211 case MARKER_FALSE:
212 return false;
213 case MARKER_INT8:
214 return readInt8(stream);
215 case MARKER_UINT8:
216 return readUInt8(stream);
217 case MARKER_INT16:
218 return readInt16(stream);
219 case MARKER_INT32:
220 return readInt32(stream);
221 case MARKER_INT64:
222 return (qlonglong)readInt64(stream);
223 case MARKER_FLOAT32:
224 return readFloat32(stream);
225 case MARKER_FLOAT64:
226 return readFloat64(stream);
227 case MARKER_HIGH_PRECISION:
228 Q_UNIMPLEMENTED();
229 return QVariant();
230 case MARKER_CHAR:
231 Q_UNIMPLEMENTED();
232 return QVariant();
233 case MARKER_STRING:
234 return readString(stream);
235 case MARKER_ARRAY_BEGIN:
236 return readArray(stream);
237 case MARKER_OBJECT_BEGIN:
238 return readObject(stream);
239 case MARKER_ARRAY_END:
240 case MARKER_OBJECT_END:
241 case MARKER_TYPE:
242 case MARKER_COUNT:
243 default:
244 Q_ASSERT(0);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100245 case MARKER_EOF:
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100246 return QVariant();
247 }
248}
249
250
Jose Fonseca52aefcb2015-05-20 14:02:29 +0100251QVariantMap decodeUBJSONObject(QIODevice *io)
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100252{
Jose Fonseca52aefcb2015-05-20 14:02:29 +0100253 QDataStream stream(io);
Jose Fonseca46b88772015-05-19 16:52:10 +0100254 stream.setByteOrder(QDataStream::BigEndian);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100255 Marker marker = readMarker(stream);
256 Q_ASSERT(marker == MARKER_OBJECT_BEGIN);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100257 Q_UNUSED(marker);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100258 return readObject(stream);
259}
260