blob: 2004f298d6b57c83296ed686d935e90907ef3828 [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>
32
33#include "ubjson.hpp"
34
35
36using namespace ubjson;
37
38
39static Marker
40readMarker(QDataStream &stream)
41{
42 quint8 byte;
43 stream >> byte;
44 return static_cast<ubjson::Marker>(byte);
45}
46
47
48static int8_t
49readInt8(QDataStream &stream)
50{
51 quint8 byte;
52 stream >> byte;
53 return byte;
54}
55
56static uint8_t
57readUInt8(QDataStream &stream)
58{
59 quint8 byte;
60 stream >> byte;
61 return byte;
62}
63
64static int16_t
65readInt16(QDataStream &stream)
66{
67 uint16_t i;
68 stream.readRawData((char *)&i, sizeof i);
69 return bigEndian16(i);
70}
71
72static int32_t
73readInt32(QDataStream &stream)
74{
75 uint32_t i;
76 stream.readRawData((char *)&i, sizeof i);
77 return bigEndian32(i);
78}
79
80static int64_t
81readInt64(QDataStream &stream)
82{
83 uint64_t i;
84 stream.readRawData((char *)&i, sizeof i);
85 return bigEndian64(i);
86}
87
88static float
89readFloat32(QDataStream &stream)
90{
91 Float32 u;
92 u.i = readInt32(stream);
93 return u.f;
94}
95
96static float
97readFloat64(QDataStream &stream)
98{
99 Float64 u;
100 u.i = readInt64(stream);
101 return u.f;
102}
103
104
105static size_t
106readSize(QDataStream &stream)
107{
108 Marker type = readMarker(stream);
109 switch (type) {
110 case MARKER_INT8:
111 return readInt8(stream);
112 case MARKER_UINT8:
113 return readUInt8(stream);
114 case MARKER_INT16:
115 return readInt16(stream);
116 case MARKER_INT32:
117 return readInt32(stream);
118 case MARKER_INT64:
119 return readInt64(stream);
120 default:
121 Q_UNIMPLEMENTED();
122 return 0;
123 }
124}
125
126
127static QString
128readString(QDataStream &stream)
129{
130 size_t size = readSize(stream);
131 char *buf = new char [size];
132 stream.readRawData(buf, size);
133 QString str = QString::fromLocal8Bit(buf, size);
134 free(buf);
135 return str;
136}
137
138
139static QVariant
140readVariant(QDataStream &stream, Marker type);
141
142
143static QVariant
144readArray(QDataStream &stream)
145{
146 Marker marker = readMarker(stream);
147 if (marker == MARKER_TYPE) {
148 Marker type = readMarker(stream);
149 Q_ASSERT(type == MARKER_UINT8);
150 marker = readMarker(stream);
151 Q_ASSERT(marker == MARKER_COUNT);
152 size_t count = readSize(stream);
153 QByteArray array(count, Qt::Uninitialized);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100154 int read = stream.readRawData(array.data(), count);
155 Q_ASSERT(read == count);
156 marker = readMarker(stream);
157 Q_ASSERT(marker == MARKER_ARRAY_END);
158 return array;
159 } else {
160 Q_ASSERT(marker != MARKER_COUNT);
161 QVariantList array;
162 while (marker != MARKER_ARRAY_END) {
163 QVariant value = readVariant(stream, marker);
164 array.append(value);
165 marker = readMarker(stream);
166 }
167 return array;
168 }
169}
170
171
172static QVariantMap
173readObject(QDataStream &stream)
174{
175 QVariantMap object;
176 Marker marker = readMarker(stream);
177 while (marker != MARKER_OBJECT_END) {
178 Q_ASSERT(marker == MARKER_STRING);
179 QString name = readString(stream);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100180 marker = readMarker(stream);
181 QVariant value = readVariant(stream, marker);
182 object[name] = value;
183 marker = readMarker(stream);
184 }
185 return object;
186}
187
188
189static QVariant
190readVariant(QDataStream &stream, Marker type)
191{
192 switch (type) {
193 case MARKER_NULL:
194 return QVariant();
195 case MARKER_NOOP:
196 return QVariant();
197 case MARKER_TRUE:
198 return true;
199 case MARKER_FALSE:
200 return false;
201 case MARKER_INT8:
202 return readInt8(stream);
203 case MARKER_UINT8:
204 return readUInt8(stream);
205 case MARKER_INT16:
206 return readInt16(stream);
207 case MARKER_INT32:
208 return readInt32(stream);
209 case MARKER_INT64:
210 return (qlonglong)readInt64(stream);
211 case MARKER_FLOAT32:
212 return readFloat32(stream);
213 case MARKER_FLOAT64:
214 return readFloat64(stream);
215 case MARKER_HIGH_PRECISION:
216 Q_UNIMPLEMENTED();
217 return QVariant();
218 case MARKER_CHAR:
219 Q_UNIMPLEMENTED();
220 return QVariant();
221 case MARKER_STRING:
222 return readString(stream);
223 case MARKER_ARRAY_BEGIN:
224 return readArray(stream);
225 case MARKER_OBJECT_BEGIN:
226 return readObject(stream);
227 case MARKER_ARRAY_END:
228 case MARKER_OBJECT_END:
229 case MARKER_TYPE:
230 case MARKER_COUNT:
231 default:
232 Q_ASSERT(0);
233 return QVariant();
234 }
235}
236
237
238
239
240QVariantMap decodeUBJSONObject(QDataStream &stream)
241{
242 Marker marker = readMarker(stream);
243 Q_ASSERT(marker == MARKER_OBJECT_BEGIN);
244 return readObject(stream);
245}
246