blob: 4f86eff9bc3967f69e71fd35f3854fc7e1f67c47 [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);
154 qDebug() << "count " << count;
155 int read = stream.readRawData(array.data(), count);
156 Q_ASSERT(read == count);
157 marker = readMarker(stream);
158 Q_ASSERT(marker == MARKER_ARRAY_END);
159 return array;
160 } else {
161 Q_ASSERT(marker != MARKER_COUNT);
162 QVariantList array;
163 while (marker != MARKER_ARRAY_END) {
164 QVariant value = readVariant(stream, marker);
165 array.append(value);
166 marker = readMarker(stream);
167 }
168 return array;
169 }
170}
171
172
173static QVariantMap
174readObject(QDataStream &stream)
175{
176 QVariantMap object;
177 Marker marker = readMarker(stream);
178 while (marker != MARKER_OBJECT_END) {
179 Q_ASSERT(marker == MARKER_STRING);
180 QString name = readString(stream);
181 if (0) qDebug() << name;
182 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{
244 Marker marker = readMarker(stream);
245 Q_ASSERT(marker == MARKER_OBJECT_BEGIN);
246 return readObject(stream);
247}
248