blob: 68ca4fc4decd1be4b86fc9453449a7719ecac3aa [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{
43 quint8 byte;
44 stream >> byte;
45 return static_cast<ubjson::Marker>(byte);
46}
47
48
49static int8_t
50readInt8(QDataStream &stream)
51{
Jose Fonseca46b88772015-05-19 16:52:10 +010052 qint8 i;
53 stream >> i;
54 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010055}
56
57static uint8_t
58readUInt8(QDataStream &stream)
59{
Jose Fonseca46b88772015-05-19 16:52:10 +010060 quint8 u;
61 stream >> u;
62 return u;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010063}
64
65static int16_t
66readInt16(QDataStream &stream)
67{
Jose Fonseca46b88772015-05-19 16:52:10 +010068 qint16 i;
69 stream >> i;
70 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010071}
72
73static int32_t
74readInt32(QDataStream &stream)
75{
Jose Fonseca46b88772015-05-19 16:52:10 +010076 qint32 i;
77 stream >> i;
78 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010079}
80
81static int64_t
82readInt64(QDataStream &stream)
83{
Jose Fonseca46b88772015-05-19 16:52:10 +010084 qint64 i;
85 stream >> i;
86 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010087}
88
89static float
90readFloat32(QDataStream &stream)
91{
Jose Fonseca46b88772015-05-19 16:52:10 +010092 float f;
93 stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
94 stream >> f;
95 return f;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010096}
97
98static float
99readFloat64(QDataStream &stream)
100{
Jose Fonseca46b88772015-05-19 16:52:10 +0100101 double f;
102 stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
103 stream >> f;
104 return f;
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100105}
106
107
108static size_t
109readSize(QDataStream &stream)
110{
111 Marker type = readMarker(stream);
112 switch (type) {
113 case MARKER_INT8:
114 return readInt8(stream);
115 case MARKER_UINT8:
116 return readUInt8(stream);
117 case MARKER_INT16:
118 return readInt16(stream);
119 case MARKER_INT32:
120 return readInt32(stream);
121 case MARKER_INT64:
122 return readInt64(stream);
123 default:
124 Q_UNIMPLEMENTED();
125 return 0;
126 }
127}
128
129
130static QString
131readString(QDataStream &stream)
132{
133 size_t size = readSize(stream);
134 char *buf = new char [size];
135 stream.readRawData(buf, size);
136 QString str = QString::fromLocal8Bit(buf, size);
137 free(buf);
138 return str;
139}
140
141
142static QVariant
143readVariant(QDataStream &stream, Marker type);
144
145
146static QVariant
147readArray(QDataStream &stream)
148{
149 Marker marker = readMarker(stream);
150 if (marker == MARKER_TYPE) {
151 Marker type = readMarker(stream);
152 Q_ASSERT(type == MARKER_UINT8);
153 marker = readMarker(stream);
154 Q_ASSERT(marker == MARKER_COUNT);
155 size_t count = readSize(stream);
156 QByteArray array(count, Qt::Uninitialized);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100157 int read = stream.readRawData(array.data(), count);
158 Q_ASSERT(read == count);
159 marker = readMarker(stream);
160 Q_ASSERT(marker == MARKER_ARRAY_END);
161 return array;
162 } else {
163 Q_ASSERT(marker != MARKER_COUNT);
164 QVariantList array;
165 while (marker != MARKER_ARRAY_END) {
166 QVariant value = readVariant(stream, marker);
167 array.append(value);
168 marker = readMarker(stream);
169 }
170 return array;
171 }
172}
173
174
175static QVariantMap
176readObject(QDataStream &stream)
177{
178 QVariantMap object;
179 Marker marker = readMarker(stream);
180 while (marker != MARKER_OBJECT_END) {
181 Q_ASSERT(marker == MARKER_STRING);
182 QString name = readString(stream);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100183 marker = readMarker(stream);
184 QVariant value = readVariant(stream, marker);
185 object[name] = value;
186 marker = readMarker(stream);
187 }
188 return object;
189}
190
191
192static QVariant
193readVariant(QDataStream &stream, Marker type)
194{
195 switch (type) {
196 case MARKER_NULL:
197 return QVariant();
198 case MARKER_NOOP:
199 return QVariant();
200 case MARKER_TRUE:
201 return true;
202 case MARKER_FALSE:
203 return false;
204 case MARKER_INT8:
205 return readInt8(stream);
206 case MARKER_UINT8:
207 return readUInt8(stream);
208 case MARKER_INT16:
209 return readInt16(stream);
210 case MARKER_INT32:
211 return readInt32(stream);
212 case MARKER_INT64:
213 return (qlonglong)readInt64(stream);
214 case MARKER_FLOAT32:
215 return readFloat32(stream);
216 case MARKER_FLOAT64:
217 return readFloat64(stream);
218 case MARKER_HIGH_PRECISION:
219 Q_UNIMPLEMENTED();
220 return QVariant();
221 case MARKER_CHAR:
222 Q_UNIMPLEMENTED();
223 return QVariant();
224 case MARKER_STRING:
225 return readString(stream);
226 case MARKER_ARRAY_BEGIN:
227 return readArray(stream);
228 case MARKER_OBJECT_BEGIN:
229 return readObject(stream);
230 case MARKER_ARRAY_END:
231 case MARKER_OBJECT_END:
232 case MARKER_TYPE:
233 case MARKER_COUNT:
234 default:
235 Q_ASSERT(0);
236 return QVariant();
237 }
238}
239
240
241
242
Jose Fonseca52aefcb2015-05-20 14:02:29 +0100243QVariantMap decodeUBJSONObject(QIODevice *io)
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100244{
Jose Fonseca52aefcb2015-05-20 14:02:29 +0100245 QDataStream stream(io);
Jose Fonseca46b88772015-05-19 16:52:10 +0100246 stream.setByteOrder(QDataStream::BigEndian);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100247 Marker marker = readMarker(stream);
248 Q_ASSERT(marker == MARKER_OBJECT_BEGIN);
249 return readObject(stream);
250}
251