blob: 90bf77e4896428e2286b53d18dde28371924237a [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
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 return array;
165 } else {
166 Q_ASSERT(marker != MARKER_COUNT);
167 QVariantList array;
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100168 while (marker != MARKER_ARRAY_END &&
169 marker != MARKER_EOF) {
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100170 QVariant value = readVariant(stream, marker);
171 array.append(value);
172 marker = readMarker(stream);
173 }
174 return array;
175 }
176}
177
178
179static QVariantMap
180readObject(QDataStream &stream)
181{
182 QVariantMap object;
183 Marker marker = readMarker(stream);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100184 while (marker != MARKER_OBJECT_END &&
185 marker != MARKER_EOF) {
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100186 Q_ASSERT(marker == MARKER_STRING);
187 QString name = readString(stream);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100188 marker = readMarker(stream);
189 QVariant value = readVariant(stream, marker);
190 object[name] = value;
191 marker = readMarker(stream);
192 }
193 return object;
194}
195
196
197static QVariant
198readVariant(QDataStream &stream, Marker type)
199{
200 switch (type) {
201 case MARKER_NULL:
202 return QVariant();
203 case MARKER_NOOP:
204 return QVariant();
205 case MARKER_TRUE:
206 return true;
207 case MARKER_FALSE:
208 return false;
209 case MARKER_INT8:
210 return readInt8(stream);
211 case MARKER_UINT8:
212 return readUInt8(stream);
213 case MARKER_INT16:
214 return readInt16(stream);
215 case MARKER_INT32:
216 return readInt32(stream);
217 case MARKER_INT64:
218 return (qlonglong)readInt64(stream);
219 case MARKER_FLOAT32:
220 return readFloat32(stream);
221 case MARKER_FLOAT64:
222 return readFloat64(stream);
223 case MARKER_HIGH_PRECISION:
224 Q_UNIMPLEMENTED();
225 return QVariant();
226 case MARKER_CHAR:
227 Q_UNIMPLEMENTED();
228 return QVariant();
229 case MARKER_STRING:
230 return readString(stream);
231 case MARKER_ARRAY_BEGIN:
232 return readArray(stream);
233 case MARKER_OBJECT_BEGIN:
234 return readObject(stream);
235 case MARKER_ARRAY_END:
236 case MARKER_OBJECT_END:
237 case MARKER_TYPE:
238 case MARKER_COUNT:
239 default:
240 Q_ASSERT(0);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100241 case MARKER_EOF:
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100242 return QVariant();
243 }
244}
245
246
Jose Fonseca52aefcb2015-05-20 14:02:29 +0100247QVariantMap decodeUBJSONObject(QIODevice *io)
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100248{
Jose Fonseca52aefcb2015-05-20 14:02:29 +0100249 QDataStream stream(io);
Jose Fonseca46b88772015-05-19 16:52:10 +0100250 stream.setByteOrder(QDataStream::BigEndian);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100251 Marker marker = readMarker(stream);
252 Q_ASSERT(marker == MARKER_OBJECT_BEGIN);
Jose Fonsecae2e4c362015-05-21 16:12:22 +0100253 Q_UNUSED(marker);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100254 return readObject(stream);
255}
256