blob: c36e0659f116d1f8524d00f3d87e5eee7c4184c0 [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
100static float
101readFloat64(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
111readSize(QDataStream &stream)
112{
113 Marker type = readMarker(stream);
114 switch (type) {
115 case MARKER_INT8:
116 return readInt8(stream);
117 case MARKER_UINT8:
118 return readUInt8(stream);
119 case MARKER_INT16:
120 return readInt16(stream);
121 case MARKER_INT32:
122 return readInt32(stream);
123 case MARKER_INT64:
124 return readInt64(stream);
125 default:
126 Q_UNIMPLEMENTED();
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100127 case MARKER_EOF:
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100128 return 0;
129 }
130}
131
132
133static QString
134readString(QDataStream &stream)
135{
136 size_t size = readSize(stream);
137 char *buf = new char [size];
138 stream.readRawData(buf, size);
Jose Fonsecac9c987d2015-05-21 16:12:55 +0100139 QString str = QString::fromUtf8(buf, size);
140 delete [] buf;
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100141 return str;
142}
143
144
145static QVariant
146readVariant(QDataStream &stream, Marker type);
147
148
149static QVariant
150readArray(QDataStream &stream)
151{
152 Marker marker = readMarker(stream);
153 if (marker == MARKER_TYPE) {
154 Marker type = readMarker(stream);
155 Q_ASSERT(type == MARKER_UINT8);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100156 Q_UNUSED(type);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100157 marker = readMarker(stream);
158 Q_ASSERT(marker == MARKER_COUNT);
159 size_t count = readSize(stream);
160 QByteArray array(count, Qt::Uninitialized);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100161 int read = stream.readRawData(array.data(), count);
162 Q_ASSERT(read == count);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100163 Q_UNUSED(read);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100164 marker = readMarker(stream);
165 Q_ASSERT(marker == MARKER_ARRAY_END);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100166 Q_UNUSED(marker);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100167 return array;
168 } else {
169 Q_ASSERT(marker != MARKER_COUNT);
170 QVariantList array;
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100171 while (marker != MARKER_ARRAY_END &&
172 marker != MARKER_EOF) {
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100173 QVariant value = readVariant(stream, marker);
174 array.append(value);
175 marker = readMarker(stream);
176 }
177 return array;
178 }
179}
180
181
182static QVariantMap
183readObject(QDataStream &stream)
184{
185 QVariantMap object;
186 Marker marker = readMarker(stream);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100187 while (marker != MARKER_OBJECT_END &&
188 marker != MARKER_EOF) {
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100189 Q_ASSERT(marker == MARKER_STRING);
190 QString name = readString(stream);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100191 marker = readMarker(stream);
192 QVariant value = readVariant(stream, marker);
193 object[name] = value;
194 marker = readMarker(stream);
195 }
196 return object;
197}
198
199
200static QVariant
201readVariant(QDataStream &stream, Marker type)
202{
203 switch (type) {
204 case MARKER_NULL:
205 return QVariant();
206 case MARKER_NOOP:
207 return QVariant();
208 case MARKER_TRUE:
209 return true;
210 case MARKER_FALSE:
211 return false;
212 case MARKER_INT8:
213 return readInt8(stream);
214 case MARKER_UINT8:
215 return readUInt8(stream);
216 case MARKER_INT16:
217 return readInt16(stream);
218 case MARKER_INT32:
219 return readInt32(stream);
220 case MARKER_INT64:
221 return (qlonglong)readInt64(stream);
222 case MARKER_FLOAT32:
223 return readFloat32(stream);
224 case MARKER_FLOAT64:
225 return readFloat64(stream);
226 case MARKER_HIGH_PRECISION:
227 Q_UNIMPLEMENTED();
228 return QVariant();
229 case MARKER_CHAR:
230 Q_UNIMPLEMENTED();
231 return QVariant();
232 case MARKER_STRING:
233 return readString(stream);
234 case MARKER_ARRAY_BEGIN:
235 return readArray(stream);
236 case MARKER_OBJECT_BEGIN:
237 return readObject(stream);
238 case MARKER_ARRAY_END:
239 case MARKER_OBJECT_END:
240 case MARKER_TYPE:
241 case MARKER_COUNT:
242 default:
243 Q_ASSERT(0);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100244 case MARKER_EOF:
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100245 return QVariant();
246 }
247}
248
249
Jose Fonseca52aefcb2015-05-20 14:02:29 +0100250QVariantMap decodeUBJSONObject(QIODevice *io)
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100251{
Jose Fonseca52aefcb2015-05-20 14:02:29 +0100252 QDataStream stream(io);
Jose Fonseca46b88772015-05-19 16:52:10 +0100253 stream.setByteOrder(QDataStream::BigEndian);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100254 Marker marker = readMarker(stream);
255 Q_ASSERT(marker == MARKER_OBJECT_BEGIN);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100256 Q_UNUSED(marker);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100257 return readObject(stream);
258}
259