blob: 2649a41acfc13c3660bc5a44517ca7b85b795a38 [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>
Jose Fonseca8a5f0ed2015-05-20 16:17:50 +010031#include <QDataStream>
Jose Fonsecac296a3e2015-05-01 17:43:54 +010032
33#include "ubjson.hpp"
34
35
36using namespace ubjson;
37
38
39static Marker
40readMarker(QDataStream &stream)
41{
Jose Fonsecae2e4c362015-05-21 16:12:22 +010042 if (stream.atEnd()) {
43 return MARKER_EOF;
44 }
Jose Fonsecac296a3e2015-05-01 17:43:54 +010045 quint8 byte;
46 stream >> byte;
Jose Fonsecae2e4c362015-05-21 16:12:22 +010047 return static_cast<Marker>(byte);
Jose Fonsecac296a3e2015-05-01 17:43:54 +010048}
49
50
51static int8_t
52readInt8(QDataStream &stream)
53{
Jose Fonseca46b88772015-05-19 16:52:10 +010054 qint8 i;
55 stream >> i;
56 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010057}
58
59static uint8_t
60readUInt8(QDataStream &stream)
61{
Jose Fonseca46b88772015-05-19 16:52:10 +010062 quint8 u;
63 stream >> u;
64 return u;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010065}
66
67static int16_t
68readInt16(QDataStream &stream)
69{
Jose Fonseca46b88772015-05-19 16:52:10 +010070 qint16 i;
71 stream >> i;
72 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010073}
74
75static int32_t
76readInt32(QDataStream &stream)
77{
Jose Fonseca46b88772015-05-19 16:52:10 +010078 qint32 i;
79 stream >> i;
80 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010081}
82
83static int64_t
84readInt64(QDataStream &stream)
85{
Jose Fonseca46b88772015-05-19 16:52:10 +010086 qint64 i;
87 stream >> i;
88 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010089}
90
91static float
92readFloat32(QDataStream &stream)
93{
Jose Fonseca46b88772015-05-19 16:52:10 +010094 float f;
95 stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
96 stream >> f;
97 return f;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010098}
99
Jose Fonseca318743f2015-05-21 23:58:14 +0100100static double
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100101readFloat64(QDataStream &stream)
102{
Jose Fonseca46b88772015-05-19 16:52:10 +0100103 double f;
104 stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
105 stream >> f;
106 return f;
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100107}
108
109
110static size_t
Jose Fonseca84f5e9a2015-05-22 00:03:13 +0100111readSize(QDataStream &stream, Marker type)
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100112{
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100113 switch (type) {
114 case MARKER_INT8:
115 return readInt8(stream);
116 case MARKER_UINT8:
117 return readUInt8(stream);
118 case MARKER_INT16:
119 return readInt16(stream);
120 case MARKER_INT32:
121 return readInt32(stream);
122 case MARKER_INT64:
123 return readInt64(stream);
124 default:
125 Q_UNIMPLEMENTED();
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100126 case MARKER_EOF:
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100127 return 0;
128 }
129}
130
131
132static QString
Jose Fonseca84f5e9a2015-05-22 00:03:13 +0100133readChar(QDataStream &stream)
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100134{
Jose Fonseca84f5e9a2015-05-22 00:03:13 +0100135 qint8 c;
136 stream >> c;
137 Q_ASSERT(c >= 0);
138 return QChar(c);
139}
140
141
142static size_t
143readSize(QDataStream &stream)
144{
145 Marker type = readMarker(stream);
146 return readSize(stream, type);
147}
148
149
150static QString
151readString(QDataStream &stream, size_t size)
152{
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100153 char *buf = new char [size];
154 stream.readRawData(buf, size);
Jose Fonsecac9c987d2015-05-21 16:12:55 +0100155 QString str = QString::fromUtf8(buf, size);
156 delete [] buf;
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100157 return str;
158}
159
160
Jose Fonseca84f5e9a2015-05-22 00:03:13 +0100161static QString
162readString(QDataStream &stream)
163{
164 size_t size = readSize(stream);
165 return readString(stream, size);
166}
167
168
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100169static QVariant
170readVariant(QDataStream &stream, Marker type);
171
172
173static QVariant
174readArray(QDataStream &stream)
175{
176 Marker marker = readMarker(stream);
177 if (marker == MARKER_TYPE) {
178 Marker type = readMarker(stream);
179 Q_ASSERT(type == MARKER_UINT8);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100180 Q_UNUSED(type);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100181 marker = readMarker(stream);
182 Q_ASSERT(marker == MARKER_COUNT);
183 size_t count = readSize(stream);
184 QByteArray array(count, Qt::Uninitialized);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100185 int read = stream.readRawData(array.data(), count);
186 Q_ASSERT(read == count);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100187 Q_UNUSED(read);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100188 return array;
189 } else {
190 Q_ASSERT(marker != MARKER_COUNT);
191 QVariantList array;
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100192 while (marker != MARKER_ARRAY_END &&
193 marker != MARKER_EOF) {
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100194 QVariant value = readVariant(stream, marker);
195 array.append(value);
196 marker = readMarker(stream);
197 }
198 return array;
199 }
200}
201
202
203static QVariantMap
204readObject(QDataStream &stream)
205{
206 QVariantMap object;
207 Marker marker = readMarker(stream);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100208 while (marker != MARKER_OBJECT_END &&
209 marker != MARKER_EOF) {
Jose Fonseca84f5e9a2015-05-22 00:03:13 +0100210 size_t nameSize = readSize(stream, marker);
211 QString name = readString(stream, nameSize);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100212 marker = readMarker(stream);
213 QVariant value = readVariant(stream, marker);
214 object[name] = value;
215 marker = readMarker(stream);
216 }
217 return object;
218}
219
220
221static QVariant
222readVariant(QDataStream &stream, Marker type)
223{
224 switch (type) {
225 case MARKER_NULL:
226 return QVariant();
227 case MARKER_NOOP:
228 return QVariant();
229 case MARKER_TRUE:
230 return true;
231 case MARKER_FALSE:
232 return false;
233 case MARKER_INT8:
234 return readInt8(stream);
235 case MARKER_UINT8:
236 return readUInt8(stream);
237 case MARKER_INT16:
238 return readInt16(stream);
239 case MARKER_INT32:
240 return readInt32(stream);
241 case MARKER_INT64:
242 return (qlonglong)readInt64(stream);
243 case MARKER_FLOAT32:
244 return readFloat32(stream);
245 case MARKER_FLOAT64:
246 return readFloat64(stream);
247 case MARKER_HIGH_PRECISION:
248 Q_UNIMPLEMENTED();
249 return QVariant();
250 case MARKER_CHAR:
Jose Fonseca84f5e9a2015-05-22 00:03:13 +0100251 return readChar(stream);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100252 case MARKER_STRING:
253 return readString(stream);
254 case MARKER_ARRAY_BEGIN:
255 return readArray(stream);
256 case MARKER_OBJECT_BEGIN:
257 return readObject(stream);
258 case MARKER_ARRAY_END:
259 case MARKER_OBJECT_END:
260 case MARKER_TYPE:
261 case MARKER_COUNT:
262 default:
263 Q_ASSERT(0);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100264 case MARKER_EOF:
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100265 return QVariant();
266 }
267}
268
269
Jose Fonseca52aefcb2015-05-20 14:02:29 +0100270QVariantMap decodeUBJSONObject(QIODevice *io)
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100271{
Jose Fonseca52aefcb2015-05-20 14:02:29 +0100272 QDataStream stream(io);
Jose Fonseca46b88772015-05-19 16:52:10 +0100273 stream.setByteOrder(QDataStream::BigEndian);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100274 Marker marker = readMarker(stream);
275 Q_ASSERT(marker == MARKER_OBJECT_BEGIN);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100276 Q_UNUSED(marker);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100277 return readObject(stream);
278}
279