blob: a0652cd275e603d446efdcd61397f25b7806c910 [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{
Jose Fonseca46b88772015-05-19 16:52:10 +010051 qint8 i;
52 stream >> i;
53 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010054}
55
56static uint8_t
57readUInt8(QDataStream &stream)
58{
Jose Fonseca46b88772015-05-19 16:52:10 +010059 quint8 u;
60 stream >> u;
61 return u;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010062}
63
64static int16_t
65readInt16(QDataStream &stream)
66{
Jose Fonseca46b88772015-05-19 16:52:10 +010067 qint16 i;
68 stream >> i;
69 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010070}
71
72static int32_t
73readInt32(QDataStream &stream)
74{
Jose Fonseca46b88772015-05-19 16:52:10 +010075 qint32 i;
76 stream >> i;
77 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010078}
79
80static int64_t
81readInt64(QDataStream &stream)
82{
Jose Fonseca46b88772015-05-19 16:52:10 +010083 qint64 i;
84 stream >> i;
85 return i;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010086}
87
88static float
89readFloat32(QDataStream &stream)
90{
Jose Fonseca46b88772015-05-19 16:52:10 +010091 float f;
92 stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
93 stream >> f;
94 return f;
Jose Fonsecac296a3e2015-05-01 17:43:54 +010095}
96
97static float
98readFloat64(QDataStream &stream)
99{
Jose Fonseca46b88772015-05-19 16:52:10 +0100100 double f;
101 stream.setFloatingPointPrecision(QDataStream::DoublePrecision);
102 stream >> f;
103 return f;
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100104}
105
106
107static size_t
108readSize(QDataStream &stream)
109{
110 Marker type = readMarker(stream);
111 switch (type) {
112 case MARKER_INT8:
113 return readInt8(stream);
114 case MARKER_UINT8:
115 return readUInt8(stream);
116 case MARKER_INT16:
117 return readInt16(stream);
118 case MARKER_INT32:
119 return readInt32(stream);
120 case MARKER_INT64:
121 return readInt64(stream);
122 default:
123 Q_UNIMPLEMENTED();
124 return 0;
125 }
126}
127
128
129static QString
130readString(QDataStream &stream)
131{
132 size_t size = readSize(stream);
133 char *buf = new char [size];
134 stream.readRawData(buf, size);
135 QString str = QString::fromLocal8Bit(buf, size);
136 free(buf);
137 return str;
138}
139
140
141static QVariant
142readVariant(QDataStream &stream, Marker type);
143
144
145static QVariant
146readArray(QDataStream &stream)
147{
148 Marker marker = readMarker(stream);
149 if (marker == MARKER_TYPE) {
150 Marker type = readMarker(stream);
151 Q_ASSERT(type == MARKER_UINT8);
152 marker = readMarker(stream);
153 Q_ASSERT(marker == MARKER_COUNT);
154 size_t count = readSize(stream);
155 QByteArray array(count, Qt::Uninitialized);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100156 int read = stream.readRawData(array.data(), count);
157 Q_ASSERT(read == count);
158 marker = readMarker(stream);
159 Q_ASSERT(marker == MARKER_ARRAY_END);
160 return array;
161 } else {
162 Q_ASSERT(marker != MARKER_COUNT);
163 QVariantList array;
164 while (marker != MARKER_ARRAY_END) {
165 QVariant value = readVariant(stream, marker);
166 array.append(value);
167 marker = readMarker(stream);
168 }
169 return array;
170 }
171}
172
173
174static QVariantMap
175readObject(QDataStream &stream)
176{
177 QVariantMap object;
178 Marker marker = readMarker(stream);
179 while (marker != MARKER_OBJECT_END) {
180 Q_ASSERT(marker == MARKER_STRING);
181 QString name = readString(stream);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100182 marker = readMarker(stream);
183 QVariant value = readVariant(stream, marker);
184 object[name] = value;
185 marker = readMarker(stream);
186 }
187 return object;
188}
189
190
191static QVariant
192readVariant(QDataStream &stream, Marker type)
193{
194 switch (type) {
195 case MARKER_NULL:
196 return QVariant();
197 case MARKER_NOOP:
198 return QVariant();
199 case MARKER_TRUE:
200 return true;
201 case MARKER_FALSE:
202 return false;
203 case MARKER_INT8:
204 return readInt8(stream);
205 case MARKER_UINT8:
206 return readUInt8(stream);
207 case MARKER_INT16:
208 return readInt16(stream);
209 case MARKER_INT32:
210 return readInt32(stream);
211 case MARKER_INT64:
212 return (qlonglong)readInt64(stream);
213 case MARKER_FLOAT32:
214 return readFloat32(stream);
215 case MARKER_FLOAT64:
216 return readFloat64(stream);
217 case MARKER_HIGH_PRECISION:
218 Q_UNIMPLEMENTED();
219 return QVariant();
220 case MARKER_CHAR:
221 Q_UNIMPLEMENTED();
222 return QVariant();
223 case MARKER_STRING:
224 return readString(stream);
225 case MARKER_ARRAY_BEGIN:
226 return readArray(stream);
227 case MARKER_OBJECT_BEGIN:
228 return readObject(stream);
229 case MARKER_ARRAY_END:
230 case MARKER_OBJECT_END:
231 case MARKER_TYPE:
232 case MARKER_COUNT:
233 default:
234 Q_ASSERT(0);
235 return QVariant();
236 }
237}
238
239
240
241
242QVariantMap decodeUBJSONObject(QDataStream &stream)
243{
Jose Fonseca46b88772015-05-19 16:52:10 +0100244 stream.setByteOrder(QDataStream::BigEndian);
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100245 Marker marker = readMarker(stream);
246 Q_ASSERT(marker == MARKER_OBJECT_BEGIN);
247 return readObject(stream);
248}
249