ucl 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE-DEPENDENCIES.md +161 -0
- data/README.md +104 -15
- data/ext/extconf.rb +42 -40
- data/ext/libucl/COPYING +23 -0
- data/ext/libucl/include/ucl.h +1689 -0
- data/ext/libucl/klib/khash.h +627 -0
- data/ext/libucl/klib/kvec.h +161 -0
- data/ext/libucl/src/mum.h +440 -0
- data/ext/libucl/src/tree.h +209 -0
- data/ext/libucl/src/ucl_chartable.h +267 -0
- data/ext/libucl/src/ucl_emitter.c +721 -0
- data/ext/libucl/src/ucl_emitter_streamline.c +178 -0
- data/ext/libucl/src/ucl_emitter_utils.c +521 -0
- data/ext/libucl/src/ucl_hash.c +642 -0
- data/ext/libucl/src/ucl_hash.h +115 -0
- data/ext/libucl/src/ucl_internal.h +668 -0
- data/ext/libucl/src/ucl_msgpack.c +1574 -0
- data/ext/libucl/src/ucl_parser.c +3247 -0
- data/ext/libucl/src/ucl_schema.c +1102 -0
- data/ext/libucl/src/ucl_sexp.c +229 -0
- data/ext/libucl/src/ucl_util.c +4004 -0
- data/ext/libucl/uthash/uthash.h +720 -0
- data/ext/libucl/uthash/utlist.h +1076 -0
- data/ext/libucl/uthash/utstring.h +412 -0
- data/ext/ucl.c +308 -89
- data/test/test_ucl.rb +129 -0
- data/ucl.gemspec +20 -7
- metadata +25 -17
|
@@ -0,0 +1,1574 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015, Vsevolod Stakhov
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* Redistribution and use in source and binary forms, with or without
|
|
6
|
+
* modification, are permitted provided that the following conditions are met:
|
|
7
|
+
* * Redistributions of source code must retain the above copyright
|
|
8
|
+
* notice, this list of conditions and the following disclaimer.
|
|
9
|
+
* * Redistributions in binary form must reproduce the above copyright
|
|
10
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
11
|
+
* documentation and/or other materials provided with the distribution.
|
|
12
|
+
*
|
|
13
|
+
* THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
|
|
14
|
+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
15
|
+
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
16
|
+
* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
|
|
17
|
+
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
18
|
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
19
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
20
|
+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
21
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
22
|
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
#ifdef HAVE_CONFIG_H
|
|
27
|
+
#include "config.h"
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#include "ucl.h"
|
|
31
|
+
#include "ucl_internal.h"
|
|
32
|
+
|
|
33
|
+
#ifdef HAVE_ENDIAN_H
|
|
34
|
+
#include <endian.h>
|
|
35
|
+
#elif defined(HAVE_SYS_ENDIAN_H)
|
|
36
|
+
#include <sys/endian.h>
|
|
37
|
+
#elif defined(HAVE_MACHINE_ENDIAN_H)
|
|
38
|
+
#include <machine/endian.h>
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
|
|
42
|
+
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
43
|
+
#define __LITTLE_ENDIAN__
|
|
44
|
+
#elif __BYTE_ORDER == __BIG_ENDIAN
|
|
45
|
+
#define __BIG_ENDIAN__
|
|
46
|
+
#elif _WIN32
|
|
47
|
+
#define __LITTLE_ENDIAN__
|
|
48
|
+
#endif
|
|
49
|
+
#endif
|
|
50
|
+
|
|
51
|
+
#define SWAP_LE_BE16(val) ((uint16_t) ((uint16_t) ((uint16_t) (val) >> 8) | \
|
|
52
|
+
(uint16_t) ((uint16_t) (val) << 8)))
|
|
53
|
+
|
|
54
|
+
#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 4 && defined(__GNUC_MINOR__) && __GNUC_MINOR__ >= 3)
|
|
55
|
+
#define SWAP_LE_BE32(val) ((uint32_t) __builtin_bswap32((uint32_t) (val)))
|
|
56
|
+
#define SWAP_LE_BE64(val) ((uint64_t) __builtin_bswap64((uint64_t) (val)))
|
|
57
|
+
#else
|
|
58
|
+
#define SWAP_LE_BE32(val) ((uint32_t) ((((uint32_t) (val) & (uint32_t) 0x000000ffU) << 24) | \
|
|
59
|
+
(((uint32_t) (val) & (uint32_t) 0x0000ff00U) << 8) | \
|
|
60
|
+
(((uint32_t) (val) & (uint32_t) 0x00ff0000U) >> 8) | \
|
|
61
|
+
(((uint32_t) (val) & (uint32_t) 0xff000000U) >> 24)))
|
|
62
|
+
|
|
63
|
+
#define SWAP_LE_BE64(val) ((uint64_t) ((((uint64_t) (val) & \
|
|
64
|
+
(uint64_t) (0x00000000000000ffULL)) \
|
|
65
|
+
<< 56) | \
|
|
66
|
+
(((uint64_t) (val) & \
|
|
67
|
+
(uint64_t) (0x000000000000ff00ULL)) \
|
|
68
|
+
<< 40) | \
|
|
69
|
+
(((uint64_t) (val) & \
|
|
70
|
+
(uint64_t) (0x0000000000ff0000ULL)) \
|
|
71
|
+
<< 24) | \
|
|
72
|
+
(((uint64_t) (val) & \
|
|
73
|
+
(uint64_t) (0x00000000ff000000ULL)) \
|
|
74
|
+
<< 8) | \
|
|
75
|
+
(((uint64_t) (val) & \
|
|
76
|
+
(uint64_t) (0x000000ff00000000ULL)) >> \
|
|
77
|
+
8) | \
|
|
78
|
+
(((uint64_t) (val) & \
|
|
79
|
+
(uint64_t) (0x0000ff0000000000ULL)) >> \
|
|
80
|
+
24) | \
|
|
81
|
+
(((uint64_t) (val) & \
|
|
82
|
+
(uint64_t) (0x00ff000000000000ULL)) >> \
|
|
83
|
+
40) | \
|
|
84
|
+
(((uint64_t) (val) & \
|
|
85
|
+
(uint64_t) (0xff00000000000000ULL)) >> \
|
|
86
|
+
56)))
|
|
87
|
+
#endif
|
|
88
|
+
|
|
89
|
+
#ifdef __LITTLE_ENDIAN__
|
|
90
|
+
#define TO_BE16 SWAP_LE_BE16
|
|
91
|
+
#define TO_BE32 SWAP_LE_BE32
|
|
92
|
+
#define TO_BE64 SWAP_LE_BE64
|
|
93
|
+
#define FROM_BE16 SWAP_LE_BE16
|
|
94
|
+
#define FROM_BE32 SWAP_LE_BE32
|
|
95
|
+
#define FROM_BE64 SWAP_LE_BE64
|
|
96
|
+
#else
|
|
97
|
+
#define TO_BE16(val) (uint16_t) (val)
|
|
98
|
+
#define TO_BE32(val) (uint32_t) (val)
|
|
99
|
+
#define TO_BE64(val) (uint64_t) (val)
|
|
100
|
+
#define FROM_BE16(val) (uint16_t) (val)
|
|
101
|
+
#define FROM_BE32(val) (uint32_t) (val)
|
|
102
|
+
#define FROM_BE64(val) (uint64_t) (val)
|
|
103
|
+
#endif
|
|
104
|
+
|
|
105
|
+
void ucl_emitter_print_int_msgpack(struct ucl_emitter_context *ctx, int64_t val)
|
|
106
|
+
{
|
|
107
|
+
const struct ucl_emitter_functions *func = ctx->func;
|
|
108
|
+
unsigned char buf[sizeof(uint64_t) + 1];
|
|
109
|
+
const unsigned char mask_positive = 0x7f, mask_negative = 0xe0,
|
|
110
|
+
uint8_ch = 0xcc, uint16_ch = 0xcd, uint32_ch = 0xce, uint64_ch = 0xcf,
|
|
111
|
+
int8_ch = 0xd0, int16_ch = 0xd1, int32_ch = 0xd2, int64_ch = 0xd3;
|
|
112
|
+
unsigned len;
|
|
113
|
+
|
|
114
|
+
if (val >= 0) {
|
|
115
|
+
if (val <= 0x7f) {
|
|
116
|
+
/* Fixed num 7 bits */
|
|
117
|
+
len = 1;
|
|
118
|
+
buf[0] = mask_positive & val;
|
|
119
|
+
}
|
|
120
|
+
else if (val <= UINT8_MAX) {
|
|
121
|
+
len = 2;
|
|
122
|
+
buf[0] = uint8_ch;
|
|
123
|
+
buf[1] = val & 0xff;
|
|
124
|
+
}
|
|
125
|
+
else if (val <= UINT16_MAX) {
|
|
126
|
+
uint16_t v = TO_BE16(val);
|
|
127
|
+
|
|
128
|
+
len = 3;
|
|
129
|
+
buf[0] = uint16_ch;
|
|
130
|
+
memcpy(&buf[1], &v, sizeof(v));
|
|
131
|
+
}
|
|
132
|
+
else if (val <= UINT32_MAX) {
|
|
133
|
+
uint32_t v = TO_BE32(val);
|
|
134
|
+
|
|
135
|
+
len = 5;
|
|
136
|
+
buf[0] = uint32_ch;
|
|
137
|
+
memcpy(&buf[1], &v, sizeof(v));
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
uint64_t v = TO_BE64(val);
|
|
141
|
+
|
|
142
|
+
len = 9;
|
|
143
|
+
buf[0] = uint64_ch;
|
|
144
|
+
memcpy(&buf[1], &v, sizeof(v));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
uint64_t uval;
|
|
149
|
+
/* Bithack abs */
|
|
150
|
+
uval = ((val ^ (val >> 63)) - (val >> 63));
|
|
151
|
+
|
|
152
|
+
if (val > -(1 << 5)) {
|
|
153
|
+
len = 1;
|
|
154
|
+
buf[0] = (mask_negative | uval) & 0xff;
|
|
155
|
+
}
|
|
156
|
+
else if (uval <= INT8_MAX) {
|
|
157
|
+
uint8_t v = (uint8_t) val;
|
|
158
|
+
len = 2;
|
|
159
|
+
buf[0] = int8_ch;
|
|
160
|
+
buf[1] = v;
|
|
161
|
+
}
|
|
162
|
+
else if (uval <= INT16_MAX) {
|
|
163
|
+
uint16_t v = TO_BE16(val);
|
|
164
|
+
|
|
165
|
+
len = 3;
|
|
166
|
+
buf[0] = int16_ch;
|
|
167
|
+
memcpy(&buf[1], &v, sizeof(v));
|
|
168
|
+
}
|
|
169
|
+
else if (uval <= INT32_MAX) {
|
|
170
|
+
uint32_t v = TO_BE32(val);
|
|
171
|
+
|
|
172
|
+
len = 5;
|
|
173
|
+
buf[0] = int32_ch;
|
|
174
|
+
memcpy(&buf[1], &v, sizeof(v));
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
uint64_t v = TO_BE64(val);
|
|
178
|
+
|
|
179
|
+
len = 9;
|
|
180
|
+
buf[0] = int64_ch;
|
|
181
|
+
memcpy(&buf[1], &v, sizeof(v));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
func->ucl_emitter_append_len(buf, len, func->ud);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
void ucl_emitter_print_double_msgpack(struct ucl_emitter_context *ctx, double val)
|
|
189
|
+
{
|
|
190
|
+
const struct ucl_emitter_functions *func = ctx->func;
|
|
191
|
+
union {
|
|
192
|
+
double d;
|
|
193
|
+
uint64_t i;
|
|
194
|
+
} u;
|
|
195
|
+
const unsigned char dbl_ch = 0xcb;
|
|
196
|
+
unsigned char buf[sizeof(double) + 1];
|
|
197
|
+
|
|
198
|
+
/* Convert to big endian */
|
|
199
|
+
u.d = val;
|
|
200
|
+
u.i = TO_BE64(u.i);
|
|
201
|
+
|
|
202
|
+
buf[0] = dbl_ch;
|
|
203
|
+
memcpy(&buf[1], &u.d, sizeof(double));
|
|
204
|
+
func->ucl_emitter_append_len(buf, sizeof(buf), func->ud);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
void ucl_emitter_print_bool_msgpack(struct ucl_emitter_context *ctx, bool val)
|
|
208
|
+
{
|
|
209
|
+
const struct ucl_emitter_functions *func = ctx->func;
|
|
210
|
+
const unsigned char true_ch = 0xc3, false_ch = 0xc2;
|
|
211
|
+
|
|
212
|
+
func->ucl_emitter_append_character(val ? true_ch : false_ch, 1, func->ud);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
void ucl_emitter_print_string_msgpack(struct ucl_emitter_context *ctx,
|
|
216
|
+
const char *s, size_t len)
|
|
217
|
+
{
|
|
218
|
+
const struct ucl_emitter_functions *func = ctx->func;
|
|
219
|
+
const unsigned char fix_mask = 0xA0, l8_ch = 0xd9, l16_ch = 0xda, l32_ch = 0xdb;
|
|
220
|
+
unsigned char buf[5];
|
|
221
|
+
unsigned blen;
|
|
222
|
+
|
|
223
|
+
if (len <= 0x1F) {
|
|
224
|
+
blen = 1;
|
|
225
|
+
buf[0] = (len | fix_mask) & 0xff;
|
|
226
|
+
}
|
|
227
|
+
else if (len <= 0xff) {
|
|
228
|
+
blen = 2;
|
|
229
|
+
buf[0] = l8_ch;
|
|
230
|
+
buf[1] = len & 0xff;
|
|
231
|
+
}
|
|
232
|
+
else if (len <= 0xffff) {
|
|
233
|
+
uint16_t bl = TO_BE16(len);
|
|
234
|
+
|
|
235
|
+
blen = 3;
|
|
236
|
+
buf[0] = l16_ch;
|
|
237
|
+
memcpy(&buf[1], &bl, sizeof(bl));
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
uint32_t bl = TO_BE32(len);
|
|
241
|
+
|
|
242
|
+
blen = 5;
|
|
243
|
+
buf[0] = l32_ch;
|
|
244
|
+
memcpy(&buf[1], &bl, sizeof(bl));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
func->ucl_emitter_append_len(buf, blen, func->ud);
|
|
248
|
+
func->ucl_emitter_append_len(s, len, func->ud);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
void ucl_emitter_print_binary_string_msgpack(struct ucl_emitter_context *ctx,
|
|
252
|
+
const char *s, size_t len)
|
|
253
|
+
{
|
|
254
|
+
const struct ucl_emitter_functions *func = ctx->func;
|
|
255
|
+
const unsigned char l8_ch = 0xc4, l16_ch = 0xc5, l32_ch = 0xc6;
|
|
256
|
+
unsigned char buf[5];
|
|
257
|
+
unsigned blen;
|
|
258
|
+
|
|
259
|
+
if (len <= 0xff) {
|
|
260
|
+
blen = 2;
|
|
261
|
+
buf[0] = l8_ch;
|
|
262
|
+
buf[1] = len & 0xff;
|
|
263
|
+
}
|
|
264
|
+
else if (len <= 0xffff) {
|
|
265
|
+
uint16_t bl = TO_BE16(len);
|
|
266
|
+
|
|
267
|
+
blen = 3;
|
|
268
|
+
buf[0] = l16_ch;
|
|
269
|
+
memcpy(&buf[1], &bl, sizeof(bl));
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
uint32_t bl = TO_BE32(len);
|
|
273
|
+
|
|
274
|
+
blen = 5;
|
|
275
|
+
buf[0] = l32_ch;
|
|
276
|
+
memcpy(&buf[1], &bl, sizeof(bl));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
func->ucl_emitter_append_len(buf, blen, func->ud);
|
|
280
|
+
func->ucl_emitter_append_len(s, len, func->ud);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
void ucl_emitter_print_null_msgpack(struct ucl_emitter_context *ctx)
|
|
284
|
+
{
|
|
285
|
+
const struct ucl_emitter_functions *func = ctx->func;
|
|
286
|
+
const unsigned char nil = 0xc0;
|
|
287
|
+
|
|
288
|
+
func->ucl_emitter_append_character(nil, 1, func->ud);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
void ucl_emitter_print_key_msgpack(bool print_key, struct ucl_emitter_context *ctx,
|
|
292
|
+
const ucl_object_t *obj)
|
|
293
|
+
{
|
|
294
|
+
if (print_key) {
|
|
295
|
+
ucl_emitter_print_string_msgpack(ctx, obj->key, obj->keylen);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
void ucl_emitter_print_array_msgpack(struct ucl_emitter_context *ctx, size_t len)
|
|
300
|
+
{
|
|
301
|
+
const struct ucl_emitter_functions *func = ctx->func;
|
|
302
|
+
const unsigned char fix_mask = 0x90, l16_ch = 0xdc, l32_ch = 0xdd;
|
|
303
|
+
unsigned char buf[5];
|
|
304
|
+
unsigned blen;
|
|
305
|
+
|
|
306
|
+
if (len <= 0xF) {
|
|
307
|
+
blen = 1;
|
|
308
|
+
buf[0] = (len | fix_mask) & 0xff;
|
|
309
|
+
}
|
|
310
|
+
else if (len <= 0xffff) {
|
|
311
|
+
uint16_t bl = TO_BE16(len);
|
|
312
|
+
|
|
313
|
+
blen = 3;
|
|
314
|
+
buf[0] = l16_ch;
|
|
315
|
+
memcpy(&buf[1], &bl, sizeof(bl));
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
uint32_t bl = TO_BE32(len);
|
|
319
|
+
|
|
320
|
+
blen = 5;
|
|
321
|
+
buf[0] = l32_ch;
|
|
322
|
+
memcpy(&buf[1], &bl, sizeof(bl));
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
func->ucl_emitter_append_len(buf, blen, func->ud);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
void ucl_emitter_print_object_msgpack(struct ucl_emitter_context *ctx, size_t len)
|
|
329
|
+
{
|
|
330
|
+
const struct ucl_emitter_functions *func = ctx->func;
|
|
331
|
+
const unsigned char fix_mask = 0x80, l16_ch = 0xde, l32_ch = 0xdf;
|
|
332
|
+
unsigned char buf[5];
|
|
333
|
+
unsigned blen;
|
|
334
|
+
|
|
335
|
+
if (len <= 0xF) {
|
|
336
|
+
blen = 1;
|
|
337
|
+
buf[0] = (len | fix_mask) & 0xff;
|
|
338
|
+
}
|
|
339
|
+
else if (len <= 0xffff) {
|
|
340
|
+
uint16_t bl = TO_BE16(len);
|
|
341
|
+
|
|
342
|
+
blen = 3;
|
|
343
|
+
buf[0] = l16_ch;
|
|
344
|
+
memcpy(&buf[1], &bl, sizeof(bl));
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
uint32_t bl = TO_BE32(len);
|
|
348
|
+
|
|
349
|
+
blen = 5;
|
|
350
|
+
buf[0] = l32_ch;
|
|
351
|
+
memcpy(&buf[1], &bl, sizeof(bl));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
func->ucl_emitter_append_len(buf, blen, func->ud);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
enum ucl_msgpack_format {
|
|
359
|
+
msgpack_positive_fixint = 0,
|
|
360
|
+
msgpack_fixmap,
|
|
361
|
+
msgpack_fixarray,
|
|
362
|
+
msgpack_fixstr,
|
|
363
|
+
msgpack_nil,
|
|
364
|
+
msgpack_false,
|
|
365
|
+
msgpack_true,
|
|
366
|
+
msgpack_bin8,
|
|
367
|
+
msgpack_bin16,
|
|
368
|
+
msgpack_bin32,
|
|
369
|
+
msgpack_ext8,
|
|
370
|
+
msgpack_ext16,
|
|
371
|
+
msgpack_ext32,
|
|
372
|
+
msgpack_float32,
|
|
373
|
+
msgpack_float64,
|
|
374
|
+
msgpack_uint8,
|
|
375
|
+
msgpack_uint16,
|
|
376
|
+
msgpack_uint32,
|
|
377
|
+
msgpack_uint64,
|
|
378
|
+
msgpack_int8,
|
|
379
|
+
msgpack_int16,
|
|
380
|
+
msgpack_int32,
|
|
381
|
+
msgpack_int64,
|
|
382
|
+
msgpack_fixext1,
|
|
383
|
+
msgpack_fixext2,
|
|
384
|
+
msgpack_fixext4,
|
|
385
|
+
msgpack_fixext8,
|
|
386
|
+
msgpack_fixext16,
|
|
387
|
+
msgpack_str8,
|
|
388
|
+
msgpack_str16,
|
|
389
|
+
msgpack_str32,
|
|
390
|
+
msgpack_array16,
|
|
391
|
+
msgpack_array32,
|
|
392
|
+
msgpack_map16,
|
|
393
|
+
msgpack_map32,
|
|
394
|
+
msgpack_negative_fixint,
|
|
395
|
+
msgpack_invalid
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
typedef ssize_t (*ucl_msgpack_parse_function)(struct ucl_parser *parser,
|
|
399
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
400
|
+
const unsigned char *pos, size_t remain);
|
|
401
|
+
|
|
402
|
+
static ssize_t ucl_msgpack_parse_map(struct ucl_parser *parser,
|
|
403
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
404
|
+
const unsigned char *pos, size_t remain);
|
|
405
|
+
static ssize_t ucl_msgpack_parse_array(struct ucl_parser *parser,
|
|
406
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
407
|
+
const unsigned char *pos, size_t remain);
|
|
408
|
+
static ssize_t ucl_msgpack_parse_string(struct ucl_parser *parser,
|
|
409
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
410
|
+
const unsigned char *pos, size_t remain);
|
|
411
|
+
static ssize_t ucl_msgpack_parse_int(struct ucl_parser *parser,
|
|
412
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
413
|
+
const unsigned char *pos, size_t remain);
|
|
414
|
+
static ssize_t ucl_msgpack_parse_float(struct ucl_parser *parser,
|
|
415
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
416
|
+
const unsigned char *pos, size_t remain);
|
|
417
|
+
static ssize_t ucl_msgpack_parse_bool(struct ucl_parser *parser,
|
|
418
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
419
|
+
const unsigned char *pos, size_t remain);
|
|
420
|
+
static ssize_t ucl_msgpack_parse_null(struct ucl_parser *parser,
|
|
421
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
422
|
+
const unsigned char *pos, size_t remain);
|
|
423
|
+
static ssize_t ucl_msgpack_parse_ignore(struct ucl_parser *parser,
|
|
424
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
425
|
+
const unsigned char *pos, size_t remain);
|
|
426
|
+
|
|
427
|
+
#define MSGPACK_FLAG_FIXED (1 << 0)
|
|
428
|
+
#define MSGPACK_FLAG_CONTAINER (1 << 1)
|
|
429
|
+
#define MSGPACK_FLAG_TYPEVALUE (1 << 2)
|
|
430
|
+
#define MSGPACK_FLAG_EXT (1 << 3)
|
|
431
|
+
#define MSGPACK_FLAG_ASSOC (1 << 4)
|
|
432
|
+
#define MSGPACK_FLAG_KEY (1 << 5)
|
|
433
|
+
|
|
434
|
+
/*
|
|
435
|
+
* Search tree packed in array
|
|
436
|
+
*/
|
|
437
|
+
struct ucl_msgpack_parser {
|
|
438
|
+
uint8_t prefix; /* Prefix byte */
|
|
439
|
+
uint8_t prefixlen; /* Length of prefix in bits */
|
|
440
|
+
uint8_t fmt; /* The desired format */
|
|
441
|
+
uint8_t len; /* Length of the object
|
|
442
|
+
(either length bytes
|
|
443
|
+
or length of value in case
|
|
444
|
+
of fixed objects */
|
|
445
|
+
uint8_t flags; /* Flags of the specified type */
|
|
446
|
+
ucl_msgpack_parse_function func; /* Parser function */
|
|
447
|
+
} parsers[] = {
|
|
448
|
+
{0xa0,
|
|
449
|
+
3,
|
|
450
|
+
msgpack_fixstr,
|
|
451
|
+
0,
|
|
452
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_KEY,
|
|
453
|
+
ucl_msgpack_parse_string},
|
|
454
|
+
{0x0,
|
|
455
|
+
1,
|
|
456
|
+
msgpack_positive_fixint,
|
|
457
|
+
0,
|
|
458
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_TYPEVALUE,
|
|
459
|
+
ucl_msgpack_parse_int},
|
|
460
|
+
{0xe0,
|
|
461
|
+
3,
|
|
462
|
+
msgpack_negative_fixint,
|
|
463
|
+
0,
|
|
464
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_TYPEVALUE,
|
|
465
|
+
ucl_msgpack_parse_int},
|
|
466
|
+
{0x80,
|
|
467
|
+
4,
|
|
468
|
+
msgpack_fixmap,
|
|
469
|
+
0,
|
|
470
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_CONTAINER | MSGPACK_FLAG_ASSOC,
|
|
471
|
+
ucl_msgpack_parse_map},
|
|
472
|
+
{0x90,
|
|
473
|
+
4,
|
|
474
|
+
msgpack_fixarray,
|
|
475
|
+
0,
|
|
476
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_CONTAINER,
|
|
477
|
+
ucl_msgpack_parse_array},
|
|
478
|
+
{0xd9,
|
|
479
|
+
8,
|
|
480
|
+
msgpack_str8,
|
|
481
|
+
1,
|
|
482
|
+
MSGPACK_FLAG_KEY,
|
|
483
|
+
ucl_msgpack_parse_string},
|
|
484
|
+
{0xc4,
|
|
485
|
+
8,
|
|
486
|
+
msgpack_bin8,
|
|
487
|
+
1,
|
|
488
|
+
MSGPACK_FLAG_KEY,
|
|
489
|
+
ucl_msgpack_parse_string},
|
|
490
|
+
{0xcf,
|
|
491
|
+
8,
|
|
492
|
+
msgpack_uint64,
|
|
493
|
+
8,
|
|
494
|
+
MSGPACK_FLAG_FIXED,
|
|
495
|
+
ucl_msgpack_parse_int},
|
|
496
|
+
{0xd3,
|
|
497
|
+
8,
|
|
498
|
+
msgpack_int64,
|
|
499
|
+
8,
|
|
500
|
+
MSGPACK_FLAG_FIXED,
|
|
501
|
+
ucl_msgpack_parse_int},
|
|
502
|
+
{0xce,
|
|
503
|
+
8,
|
|
504
|
+
msgpack_uint32,
|
|
505
|
+
4,
|
|
506
|
+
MSGPACK_FLAG_FIXED,
|
|
507
|
+
ucl_msgpack_parse_int},
|
|
508
|
+
{0xd2,
|
|
509
|
+
8,
|
|
510
|
+
msgpack_int32,
|
|
511
|
+
4,
|
|
512
|
+
MSGPACK_FLAG_FIXED,
|
|
513
|
+
ucl_msgpack_parse_int},
|
|
514
|
+
{0xcb,
|
|
515
|
+
8,
|
|
516
|
+
msgpack_float64,
|
|
517
|
+
8,
|
|
518
|
+
MSGPACK_FLAG_FIXED,
|
|
519
|
+
ucl_msgpack_parse_float},
|
|
520
|
+
{0xca,
|
|
521
|
+
8,
|
|
522
|
+
msgpack_float32,
|
|
523
|
+
4,
|
|
524
|
+
MSGPACK_FLAG_FIXED,
|
|
525
|
+
ucl_msgpack_parse_float},
|
|
526
|
+
{0xc2,
|
|
527
|
+
8,
|
|
528
|
+
msgpack_false,
|
|
529
|
+
1,
|
|
530
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_TYPEVALUE,
|
|
531
|
+
ucl_msgpack_parse_bool},
|
|
532
|
+
{0xc3,
|
|
533
|
+
8,
|
|
534
|
+
msgpack_true,
|
|
535
|
+
1,
|
|
536
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_TYPEVALUE,
|
|
537
|
+
ucl_msgpack_parse_bool},
|
|
538
|
+
{0xcc,
|
|
539
|
+
8,
|
|
540
|
+
msgpack_uint8,
|
|
541
|
+
1,
|
|
542
|
+
MSGPACK_FLAG_FIXED,
|
|
543
|
+
ucl_msgpack_parse_int},
|
|
544
|
+
{0xcd,
|
|
545
|
+
8,
|
|
546
|
+
msgpack_uint16,
|
|
547
|
+
2,
|
|
548
|
+
MSGPACK_FLAG_FIXED,
|
|
549
|
+
ucl_msgpack_parse_int},
|
|
550
|
+
{0xd0,
|
|
551
|
+
8,
|
|
552
|
+
msgpack_int8,
|
|
553
|
+
1,
|
|
554
|
+
MSGPACK_FLAG_FIXED,
|
|
555
|
+
ucl_msgpack_parse_int},
|
|
556
|
+
{0xd1,
|
|
557
|
+
8,
|
|
558
|
+
msgpack_int16,
|
|
559
|
+
2,
|
|
560
|
+
MSGPACK_FLAG_FIXED,
|
|
561
|
+
ucl_msgpack_parse_int},
|
|
562
|
+
{0xc0,
|
|
563
|
+
8,
|
|
564
|
+
msgpack_nil,
|
|
565
|
+
0,
|
|
566
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_TYPEVALUE,
|
|
567
|
+
ucl_msgpack_parse_null},
|
|
568
|
+
{0xda,
|
|
569
|
+
8,
|
|
570
|
+
msgpack_str16,
|
|
571
|
+
2,
|
|
572
|
+
MSGPACK_FLAG_KEY,
|
|
573
|
+
ucl_msgpack_parse_string},
|
|
574
|
+
{0xdb,
|
|
575
|
+
8,
|
|
576
|
+
msgpack_str32,
|
|
577
|
+
4,
|
|
578
|
+
MSGPACK_FLAG_KEY,
|
|
579
|
+
ucl_msgpack_parse_string},
|
|
580
|
+
{0xc5,
|
|
581
|
+
8,
|
|
582
|
+
msgpack_bin16,
|
|
583
|
+
2,
|
|
584
|
+
MSGPACK_FLAG_KEY,
|
|
585
|
+
ucl_msgpack_parse_string},
|
|
586
|
+
{0xc6,
|
|
587
|
+
8,
|
|
588
|
+
msgpack_bin32,
|
|
589
|
+
4,
|
|
590
|
+
MSGPACK_FLAG_KEY,
|
|
591
|
+
ucl_msgpack_parse_string},
|
|
592
|
+
{0xdc,
|
|
593
|
+
8,
|
|
594
|
+
msgpack_array16,
|
|
595
|
+
2,
|
|
596
|
+
MSGPACK_FLAG_CONTAINER,
|
|
597
|
+
ucl_msgpack_parse_array},
|
|
598
|
+
{0xdd,
|
|
599
|
+
8,
|
|
600
|
+
msgpack_array32,
|
|
601
|
+
4,
|
|
602
|
+
MSGPACK_FLAG_CONTAINER,
|
|
603
|
+
ucl_msgpack_parse_array},
|
|
604
|
+
{0xde,
|
|
605
|
+
8,
|
|
606
|
+
msgpack_map16,
|
|
607
|
+
2,
|
|
608
|
+
MSGPACK_FLAG_CONTAINER | MSGPACK_FLAG_ASSOC,
|
|
609
|
+
ucl_msgpack_parse_map},
|
|
610
|
+
{0xdf,
|
|
611
|
+
8,
|
|
612
|
+
msgpack_map32,
|
|
613
|
+
4,
|
|
614
|
+
MSGPACK_FLAG_CONTAINER | MSGPACK_FLAG_ASSOC,
|
|
615
|
+
ucl_msgpack_parse_map},
|
|
616
|
+
{0xc7,
|
|
617
|
+
8,
|
|
618
|
+
msgpack_ext8,
|
|
619
|
+
1,
|
|
620
|
+
MSGPACK_FLAG_EXT,
|
|
621
|
+
ucl_msgpack_parse_ignore},
|
|
622
|
+
{0xc8,
|
|
623
|
+
8,
|
|
624
|
+
msgpack_ext16,
|
|
625
|
+
2,
|
|
626
|
+
MSGPACK_FLAG_EXT,
|
|
627
|
+
ucl_msgpack_parse_ignore},
|
|
628
|
+
{0xc9,
|
|
629
|
+
8,
|
|
630
|
+
msgpack_ext32,
|
|
631
|
+
4,
|
|
632
|
+
MSGPACK_FLAG_EXT,
|
|
633
|
+
ucl_msgpack_parse_ignore},
|
|
634
|
+
{0xd4,
|
|
635
|
+
8,
|
|
636
|
+
msgpack_fixext1,
|
|
637
|
+
1,
|
|
638
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_EXT,
|
|
639
|
+
ucl_msgpack_parse_ignore},
|
|
640
|
+
{0xd5,
|
|
641
|
+
8,
|
|
642
|
+
msgpack_fixext2,
|
|
643
|
+
2,
|
|
644
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_EXT,
|
|
645
|
+
ucl_msgpack_parse_ignore},
|
|
646
|
+
{0xd6,
|
|
647
|
+
8,
|
|
648
|
+
msgpack_fixext4,
|
|
649
|
+
4,
|
|
650
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_EXT,
|
|
651
|
+
ucl_msgpack_parse_ignore},
|
|
652
|
+
{0xd7,
|
|
653
|
+
8,
|
|
654
|
+
msgpack_fixext8,
|
|
655
|
+
8,
|
|
656
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_EXT,
|
|
657
|
+
ucl_msgpack_parse_ignore},
|
|
658
|
+
{0xd8,
|
|
659
|
+
8,
|
|
660
|
+
msgpack_fixext16,
|
|
661
|
+
16,
|
|
662
|
+
MSGPACK_FLAG_FIXED | MSGPACK_FLAG_EXT,
|
|
663
|
+
ucl_msgpack_parse_ignore}};
|
|
664
|
+
|
|
665
|
+
#undef MSGPACK_DEBUG_PARSER
|
|
666
|
+
|
|
667
|
+
static inline struct ucl_msgpack_parser *
|
|
668
|
+
ucl_msgpack_get_parser_from_type(unsigned char t)
|
|
669
|
+
{
|
|
670
|
+
unsigned int i, shift, mask;
|
|
671
|
+
|
|
672
|
+
for (i = 0; i < sizeof(parsers) / sizeof(parsers[0]); i++) {
|
|
673
|
+
shift = CHAR_BIT - parsers[i].prefixlen;
|
|
674
|
+
mask = parsers[i].prefix >> shift;
|
|
675
|
+
|
|
676
|
+
if (mask == (((unsigned int) t) >> shift)) {
|
|
677
|
+
return &parsers[i];
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
return NULL;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
static inline struct ucl_stack *
|
|
685
|
+
ucl_msgpack_get_container(struct ucl_parser *parser,
|
|
686
|
+
struct ucl_msgpack_parser *obj_parser, uint64_t len)
|
|
687
|
+
{
|
|
688
|
+
struct ucl_stack *stack;
|
|
689
|
+
|
|
690
|
+
assert(obj_parser != NULL);
|
|
691
|
+
|
|
692
|
+
if (obj_parser->flags & MSGPACK_FLAG_CONTAINER) {
|
|
693
|
+
/*
|
|
694
|
+
* Insert new container to the stack
|
|
695
|
+
*/
|
|
696
|
+
if (parser->stack == NULL) {
|
|
697
|
+
parser->stack = calloc(1, sizeof(struct ucl_stack));
|
|
698
|
+
|
|
699
|
+
if (parser->stack == NULL) {
|
|
700
|
+
ucl_create_err(&parser->err, "no memory");
|
|
701
|
+
return NULL;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
parser->stack->chunk = parser->chunks;
|
|
705
|
+
}
|
|
706
|
+
else {
|
|
707
|
+
stack = calloc(1, sizeof(struct ucl_stack));
|
|
708
|
+
|
|
709
|
+
if (stack == NULL) {
|
|
710
|
+
ucl_create_err(&parser->err, "no memory");
|
|
711
|
+
return NULL;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
stack->chunk = parser->chunks;
|
|
715
|
+
stack->next = parser->stack;
|
|
716
|
+
parser->stack = stack;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
parser->stack->e.len = len;
|
|
720
|
+
|
|
721
|
+
#ifdef MSGPACK_DEBUG_PARSER
|
|
722
|
+
stack = parser->stack;
|
|
723
|
+
while (stack) {
|
|
724
|
+
fprintf(stderr, "+");
|
|
725
|
+
stack = stack->next;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
fprintf(stderr, "%s -> %d\n", obj_parser->flags & MSGPACK_FLAG_ASSOC ? "object" : "array", (int) len);
|
|
729
|
+
#endif
|
|
730
|
+
}
|
|
731
|
+
else {
|
|
732
|
+
/*
|
|
733
|
+
* Get the current stack top
|
|
734
|
+
*/
|
|
735
|
+
if (parser->stack) {
|
|
736
|
+
return parser->stack;
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
ucl_create_err(&parser->err, "bad top level object for msgpack");
|
|
740
|
+
return NULL;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
return parser->stack;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
static bool
|
|
748
|
+
ucl_msgpack_is_container_finished(struct ucl_stack *container)
|
|
749
|
+
{
|
|
750
|
+
assert(container != NULL);
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
if (container->e.len == 0) {
|
|
754
|
+
return true;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
return false;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
static bool
|
|
761
|
+
ucl_msgpack_insert_object(struct ucl_parser *parser,
|
|
762
|
+
const unsigned char *key,
|
|
763
|
+
size_t keylen, ucl_object_t *obj)
|
|
764
|
+
{
|
|
765
|
+
struct ucl_stack *container;
|
|
766
|
+
|
|
767
|
+
container = parser->stack;
|
|
768
|
+
assert(container != NULL);
|
|
769
|
+
assert(container->e.len > 0);
|
|
770
|
+
assert(obj != NULL);
|
|
771
|
+
assert(container->obj != NULL);
|
|
772
|
+
|
|
773
|
+
if (container->obj->type == UCL_ARRAY) {
|
|
774
|
+
ucl_array_append(container->obj, obj);
|
|
775
|
+
}
|
|
776
|
+
else if (container->obj->type == UCL_OBJECT) {
|
|
777
|
+
if (key == NULL || keylen == 0) {
|
|
778
|
+
ucl_create_err(&parser->err, "cannot insert object with no key");
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
obj->key = key;
|
|
783
|
+
obj->keylen = keylen;
|
|
784
|
+
|
|
785
|
+
if (!(parser->flags & UCL_PARSER_ZEROCOPY)) {
|
|
786
|
+
ucl_copy_key_trash(obj);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
ucl_parser_process_object_element(parser, obj);
|
|
790
|
+
}
|
|
791
|
+
else {
|
|
792
|
+
ucl_create_err(&parser->err, "bad container type");
|
|
793
|
+
return false;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
container->e.len--;
|
|
797
|
+
|
|
798
|
+
return true;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
static struct ucl_stack *
|
|
802
|
+
ucl_msgpack_get_next_container(struct ucl_parser *parser)
|
|
803
|
+
{
|
|
804
|
+
struct ucl_stack *cur = NULL;
|
|
805
|
+
uint64_t len;
|
|
806
|
+
|
|
807
|
+
cur = parser->stack;
|
|
808
|
+
|
|
809
|
+
if (cur == NULL) {
|
|
810
|
+
return NULL;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
len = cur->e.len;
|
|
814
|
+
|
|
815
|
+
if (len == 0) {
|
|
816
|
+
/* We need to switch to the previous container */
|
|
817
|
+
parser->stack = cur->next;
|
|
818
|
+
parser->cur_obj = cur->obj;
|
|
819
|
+
free(cur);
|
|
820
|
+
|
|
821
|
+
#ifdef MSGPACK_DEBUG_PARSER
|
|
822
|
+
cur = parser->stack;
|
|
823
|
+
while (cur) {
|
|
824
|
+
fprintf(stderr, "-");
|
|
825
|
+
cur = cur->next;
|
|
826
|
+
}
|
|
827
|
+
fprintf(stderr, "-%s -> %d\n", parser->cur_obj->type == UCL_OBJECT ? "object" : "array", (int) parser->cur_obj->len);
|
|
828
|
+
#endif
|
|
829
|
+
|
|
830
|
+
return ucl_msgpack_get_next_container(parser);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
/*
|
|
834
|
+
* For UCL containers we don't know length, so we just insert the whole
|
|
835
|
+
* message pack blob into the top level container
|
|
836
|
+
*/
|
|
837
|
+
|
|
838
|
+
assert(cur->obj != NULL);
|
|
839
|
+
|
|
840
|
+
return cur;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
#define CONSUME_RET \
|
|
844
|
+
do { \
|
|
845
|
+
if (ret != -1) { \
|
|
846
|
+
p += ret; \
|
|
847
|
+
remain -= ret; \
|
|
848
|
+
obj_parser = NULL; \
|
|
849
|
+
assert(remain >= 0); \
|
|
850
|
+
} \
|
|
851
|
+
else { \
|
|
852
|
+
ucl_create_err(&parser->err, \
|
|
853
|
+
"cannot parse type %d of len %u", \
|
|
854
|
+
(int) obj_parser->fmt, \
|
|
855
|
+
(unsigned) len); \
|
|
856
|
+
return false; \
|
|
857
|
+
} \
|
|
858
|
+
} while (0)
|
|
859
|
+
|
|
860
|
+
#define GET_NEXT_STATE \
|
|
861
|
+
do { \
|
|
862
|
+
container = ucl_msgpack_get_next_container(parser); \
|
|
863
|
+
if (container == NULL) { \
|
|
864
|
+
ucl_create_err(&parser->err, \
|
|
865
|
+
"empty container"); \
|
|
866
|
+
return false; \
|
|
867
|
+
} \
|
|
868
|
+
next_state = container->obj->type == UCL_OBJECT ? read_assoc_key : read_array_value; \
|
|
869
|
+
} while (0)
|
|
870
|
+
|
|
871
|
+
static bool
|
|
872
|
+
ucl_msgpack_consume(struct ucl_parser *parser)
|
|
873
|
+
{
|
|
874
|
+
const unsigned char *p, *end, *key = NULL;
|
|
875
|
+
struct ucl_stack *container;
|
|
876
|
+
enum e_msgpack_parser_state {
|
|
877
|
+
read_type,
|
|
878
|
+
start_assoc,
|
|
879
|
+
start_array,
|
|
880
|
+
read_assoc_key,
|
|
881
|
+
read_assoc_value,
|
|
882
|
+
finish_assoc_value,
|
|
883
|
+
read_array_value,
|
|
884
|
+
finish_array_value,
|
|
885
|
+
error_state
|
|
886
|
+
} state = read_type,
|
|
887
|
+
next_state = error_state;
|
|
888
|
+
struct ucl_msgpack_parser *obj_parser = NULL;
|
|
889
|
+
uint64_t len = 0;
|
|
890
|
+
ssize_t ret, remain, keylen = 0;
|
|
891
|
+
#ifdef MSGPACK_DEBUG_PARSER
|
|
892
|
+
uint64_t i;
|
|
893
|
+
enum e_msgpack_parser_state hist[256];
|
|
894
|
+
#endif
|
|
895
|
+
|
|
896
|
+
p = parser->chunks->begin;
|
|
897
|
+
remain = parser->chunks->remain;
|
|
898
|
+
end = p + remain;
|
|
899
|
+
|
|
900
|
+
|
|
901
|
+
while (p < end) {
|
|
902
|
+
#ifdef MSGPACK_DEBUG_PARSER
|
|
903
|
+
hist[i++ % 256] = state;
|
|
904
|
+
#endif
|
|
905
|
+
switch (state) {
|
|
906
|
+
case read_type:
|
|
907
|
+
obj_parser = ucl_msgpack_get_parser_from_type(*p);
|
|
908
|
+
|
|
909
|
+
if (obj_parser == NULL) {
|
|
910
|
+
ucl_create_err(&parser->err, "unknown msgpack format: %x",
|
|
911
|
+
(unsigned int) *p);
|
|
912
|
+
|
|
913
|
+
return false;
|
|
914
|
+
}
|
|
915
|
+
/* Now check length sanity */
|
|
916
|
+
if (obj_parser->flags & MSGPACK_FLAG_FIXED) {
|
|
917
|
+
if (obj_parser->len == 0) {
|
|
918
|
+
/* We have an embedded size */
|
|
919
|
+
len = *p & ~obj_parser->prefix;
|
|
920
|
+
}
|
|
921
|
+
else {
|
|
922
|
+
if (remain < obj_parser->len) {
|
|
923
|
+
ucl_create_err(&parser->err, "not enough data remain to "
|
|
924
|
+
"read object's length: %u remain, %u needed",
|
|
925
|
+
(unsigned) remain, obj_parser->len);
|
|
926
|
+
|
|
927
|
+
return false;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
len = obj_parser->len;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
if (!(obj_parser->flags & MSGPACK_FLAG_TYPEVALUE)) {
|
|
934
|
+
/* We must pass value as the second byte */
|
|
935
|
+
if (remain > 0) {
|
|
936
|
+
p++;
|
|
937
|
+
remain--;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
/* Len is irrelevant now */
|
|
942
|
+
len = 0;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
else {
|
|
946
|
+
/* Length is not embedded */
|
|
947
|
+
remain--;
|
|
948
|
+
|
|
949
|
+
if (remain < obj_parser->len) {
|
|
950
|
+
ucl_create_err(&parser->err, "not enough data remain to "
|
|
951
|
+
"read object's length: %u remain, %u needed",
|
|
952
|
+
(unsigned) remain, obj_parser->len);
|
|
953
|
+
|
|
954
|
+
return false;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
p++;
|
|
958
|
+
|
|
959
|
+
switch (obj_parser->len) {
|
|
960
|
+
case 1:
|
|
961
|
+
len = *p;
|
|
962
|
+
break;
|
|
963
|
+
case 2:
|
|
964
|
+
len = FROM_BE16(*(uint16_t *) p);
|
|
965
|
+
break;
|
|
966
|
+
case 4:
|
|
967
|
+
len = FROM_BE32(*(uint32_t *) p);
|
|
968
|
+
break;
|
|
969
|
+
case 8:
|
|
970
|
+
len = FROM_BE64(*(uint64_t *) p);
|
|
971
|
+
break;
|
|
972
|
+
default:
|
|
973
|
+
ucl_create_err(&parser->err, "invalid length of the length field: %u",
|
|
974
|
+
(unsigned) obj_parser->len);
|
|
975
|
+
|
|
976
|
+
return false;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
p += obj_parser->len;
|
|
980
|
+
remain -= obj_parser->len;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
if (obj_parser->flags & MSGPACK_FLAG_ASSOC) {
|
|
984
|
+
/* We have just read the new associative map */
|
|
985
|
+
state = start_assoc;
|
|
986
|
+
}
|
|
987
|
+
else if (obj_parser->flags & MSGPACK_FLAG_CONTAINER) {
|
|
988
|
+
state = start_array;
|
|
989
|
+
}
|
|
990
|
+
else {
|
|
991
|
+
state = next_state;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
break;
|
|
995
|
+
case start_assoc:
|
|
996
|
+
parser->cur_obj = ucl_object_new_full(UCL_OBJECT,
|
|
997
|
+
parser->chunks->priority);
|
|
998
|
+
/* Insert to the previous level container */
|
|
999
|
+
if (parser->stack && !ucl_msgpack_insert_object(parser,
|
|
1000
|
+
key, keylen, parser->cur_obj)) {
|
|
1001
|
+
return false;
|
|
1002
|
+
}
|
|
1003
|
+
/* Get new container */
|
|
1004
|
+
container = ucl_msgpack_get_container(parser, obj_parser, len);
|
|
1005
|
+
|
|
1006
|
+
if (container == NULL) {
|
|
1007
|
+
return false;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
ret = obj_parser->func(parser, container, len, obj_parser->fmt,
|
|
1011
|
+
p, remain);
|
|
1012
|
+
CONSUME_RET;
|
|
1013
|
+
key = NULL;
|
|
1014
|
+
keylen = 0;
|
|
1015
|
+
|
|
1016
|
+
if (len > 0) {
|
|
1017
|
+
state = read_type;
|
|
1018
|
+
next_state = read_assoc_key;
|
|
1019
|
+
}
|
|
1020
|
+
else {
|
|
1021
|
+
/* Empty object */
|
|
1022
|
+
state = finish_assoc_value;
|
|
1023
|
+
}
|
|
1024
|
+
break;
|
|
1025
|
+
|
|
1026
|
+
case start_array:
|
|
1027
|
+
parser->cur_obj = ucl_object_new_full(UCL_ARRAY,
|
|
1028
|
+
parser->chunks->priority);
|
|
1029
|
+
/* Insert to the previous level container */
|
|
1030
|
+
if (parser->stack && !ucl_msgpack_insert_object(parser,
|
|
1031
|
+
key, keylen, parser->cur_obj)) {
|
|
1032
|
+
return false;
|
|
1033
|
+
}
|
|
1034
|
+
/* Get new container */
|
|
1035
|
+
container = ucl_msgpack_get_container(parser, obj_parser, len);
|
|
1036
|
+
|
|
1037
|
+
if (container == NULL) {
|
|
1038
|
+
return false;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
ret = obj_parser->func(parser, container, len, obj_parser->fmt,
|
|
1042
|
+
p, remain);
|
|
1043
|
+
CONSUME_RET;
|
|
1044
|
+
|
|
1045
|
+
if (len > 0) {
|
|
1046
|
+
state = read_type;
|
|
1047
|
+
next_state = read_array_value;
|
|
1048
|
+
}
|
|
1049
|
+
else {
|
|
1050
|
+
/* Empty array */
|
|
1051
|
+
state = finish_array_value;
|
|
1052
|
+
}
|
|
1053
|
+
break;
|
|
1054
|
+
|
|
1055
|
+
case read_array_value:
|
|
1056
|
+
/*
|
|
1057
|
+
* p is now at the value start, len now contains length read and
|
|
1058
|
+
* obj_parser contains the corresponding specific parser
|
|
1059
|
+
*/
|
|
1060
|
+
container = parser->stack;
|
|
1061
|
+
|
|
1062
|
+
if (parser->stack == NULL) {
|
|
1063
|
+
ucl_create_err(&parser->err,
|
|
1064
|
+
"read assoc value when no container represented");
|
|
1065
|
+
return false;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
ret = obj_parser->func(parser, container, len, obj_parser->fmt,
|
|
1069
|
+
p, remain);
|
|
1070
|
+
CONSUME_RET;
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
/* Insert value to the container and check if we have finished array */
|
|
1074
|
+
if (parser->cur_obj) {
|
|
1075
|
+
if (!ucl_msgpack_insert_object(parser, NULL, 0,
|
|
1076
|
+
parser->cur_obj)) {
|
|
1077
|
+
return false;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
else {
|
|
1081
|
+
/* We have parsed ext, ignore it */
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
if (ucl_msgpack_is_container_finished(container)) {
|
|
1085
|
+
state = finish_array_value;
|
|
1086
|
+
}
|
|
1087
|
+
else {
|
|
1088
|
+
/* Read more elements */
|
|
1089
|
+
state = read_type;
|
|
1090
|
+
next_state = read_array_value;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
break;
|
|
1094
|
+
|
|
1095
|
+
case read_assoc_key:
|
|
1096
|
+
/*
|
|
1097
|
+
* Keys must have string type for ucl msgpack
|
|
1098
|
+
*/
|
|
1099
|
+
if (!(obj_parser->flags & MSGPACK_FLAG_KEY)) {
|
|
1100
|
+
ucl_create_err(&parser->err, "bad type for key: %u, expected "
|
|
1101
|
+
"string",
|
|
1102
|
+
(unsigned) obj_parser->fmt);
|
|
1103
|
+
|
|
1104
|
+
return false;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
key = p;
|
|
1108
|
+
keylen = len;
|
|
1109
|
+
|
|
1110
|
+
if (keylen > remain || keylen == 0) {
|
|
1111
|
+
ucl_create_err(&parser->err, "too long or empty key");
|
|
1112
|
+
return false;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
p += len;
|
|
1116
|
+
remain -= len;
|
|
1117
|
+
|
|
1118
|
+
state = read_type;
|
|
1119
|
+
next_state = read_assoc_value;
|
|
1120
|
+
break;
|
|
1121
|
+
|
|
1122
|
+
case read_assoc_value:
|
|
1123
|
+
/*
|
|
1124
|
+
* p is now at the value start, len now contains length read and
|
|
1125
|
+
* obj_parser contains the corresponding specific parser
|
|
1126
|
+
*/
|
|
1127
|
+
container = parser->stack;
|
|
1128
|
+
|
|
1129
|
+
if (container == NULL) {
|
|
1130
|
+
ucl_create_err(&parser->err,
|
|
1131
|
+
"read assoc value when no container represented");
|
|
1132
|
+
return false;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
ret = obj_parser->func(parser, container, len, obj_parser->fmt,
|
|
1136
|
+
p, remain);
|
|
1137
|
+
CONSUME_RET;
|
|
1138
|
+
|
|
1139
|
+
assert(key != NULL && keylen > 0);
|
|
1140
|
+
|
|
1141
|
+
if (parser->cur_obj) {
|
|
1142
|
+
if (!ucl_msgpack_insert_object(parser, key, keylen,
|
|
1143
|
+
parser->cur_obj)) {
|
|
1144
|
+
|
|
1145
|
+
return false;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
key = NULL;
|
|
1150
|
+
keylen = 0;
|
|
1151
|
+
|
|
1152
|
+
if (ucl_msgpack_is_container_finished(container)) {
|
|
1153
|
+
state = finish_assoc_value;
|
|
1154
|
+
}
|
|
1155
|
+
else {
|
|
1156
|
+
/* Read more elements */
|
|
1157
|
+
state = read_type;
|
|
1158
|
+
next_state = read_assoc_key;
|
|
1159
|
+
}
|
|
1160
|
+
break;
|
|
1161
|
+
|
|
1162
|
+
case finish_array_value:
|
|
1163
|
+
case finish_assoc_value:
|
|
1164
|
+
GET_NEXT_STATE;
|
|
1165
|
+
state = read_type;
|
|
1166
|
+
break;
|
|
1167
|
+
|
|
1168
|
+
case error_state:
|
|
1169
|
+
ucl_create_err(&parser->err, "invalid state machine state");
|
|
1170
|
+
|
|
1171
|
+
return false;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
/* Check the finishing state */
|
|
1176
|
+
switch (state) {
|
|
1177
|
+
case start_array:
|
|
1178
|
+
case start_assoc:
|
|
1179
|
+
/* Empty container at the end */
|
|
1180
|
+
if (len != 0) {
|
|
1181
|
+
ucl_create_err(&parser->err,
|
|
1182
|
+
"invalid non-empty container at the end; len=%zu",
|
|
1183
|
+
(uintmax_t) len);
|
|
1184
|
+
|
|
1185
|
+
return false;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
parser->cur_obj = ucl_object_new_full(
|
|
1189
|
+
state == start_array ? UCL_ARRAY : UCL_OBJECT,
|
|
1190
|
+
parser->chunks->priority);
|
|
1191
|
+
|
|
1192
|
+
if (parser->stack == NULL) {
|
|
1193
|
+
ucl_create_err(&parser->err,
|
|
1194
|
+
"read assoc value when no container represented");
|
|
1195
|
+
return false;
|
|
1196
|
+
}
|
|
1197
|
+
/* Insert to the previous level container */
|
|
1198
|
+
if (!ucl_msgpack_insert_object(parser,
|
|
1199
|
+
key, keylen, parser->cur_obj)) {
|
|
1200
|
+
return false;
|
|
1201
|
+
}
|
|
1202
|
+
/* Get new container */
|
|
1203
|
+
container = ucl_msgpack_get_container(parser, obj_parser, len);
|
|
1204
|
+
|
|
1205
|
+
if (container == NULL) {
|
|
1206
|
+
return false;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
ret = obj_parser->func(parser, container, len, obj_parser->fmt,
|
|
1210
|
+
p, remain);
|
|
1211
|
+
break;
|
|
1212
|
+
|
|
1213
|
+
case read_array_value:
|
|
1214
|
+
case read_assoc_value:
|
|
1215
|
+
if (len != 0) {
|
|
1216
|
+
ucl_create_err(&parser->err, "unfinished value at the end");
|
|
1217
|
+
|
|
1218
|
+
return false;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
container = parser->stack;
|
|
1222
|
+
|
|
1223
|
+
if (parser->stack == NULL) {
|
|
1224
|
+
ucl_create_err(&parser->err,
|
|
1225
|
+
"read assoc value when no container represented");
|
|
1226
|
+
return false;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
ret = obj_parser->func(parser, container, len, obj_parser->fmt,
|
|
1230
|
+
p, remain);
|
|
1231
|
+
CONSUME_RET;
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
/* Insert value to the container and check if we have finished array */
|
|
1235
|
+
if (parser->cur_obj) {
|
|
1236
|
+
if (!ucl_msgpack_insert_object(parser, NULL, 0,
|
|
1237
|
+
parser->cur_obj)) {
|
|
1238
|
+
return false;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
break;
|
|
1242
|
+
case finish_array_value:
|
|
1243
|
+
case finish_assoc_value:
|
|
1244
|
+
case read_type:
|
|
1245
|
+
/* Valid finishing state */
|
|
1246
|
+
break;
|
|
1247
|
+
default:
|
|
1248
|
+
/* Invalid finishing state */
|
|
1249
|
+
ucl_create_err(&parser->err, "invalid state machine finishing state: %d",
|
|
1250
|
+
state);
|
|
1251
|
+
|
|
1252
|
+
return false;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
/* Rewind to the top level container */
|
|
1256
|
+
ucl_msgpack_get_next_container(parser);
|
|
1257
|
+
|
|
1258
|
+
if (parser->stack != NULL) {
|
|
1259
|
+
ucl_create_err(&parser->err, "incomplete container");
|
|
1260
|
+
|
|
1261
|
+
return false;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
return true;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
bool ucl_parse_msgpack(struct ucl_parser *parser)
|
|
1268
|
+
{
|
|
1269
|
+
ucl_object_t *container = NULL;
|
|
1270
|
+
const unsigned char *p;
|
|
1271
|
+
bool ret;
|
|
1272
|
+
|
|
1273
|
+
assert(parser != NULL);
|
|
1274
|
+
assert(parser->chunks != NULL);
|
|
1275
|
+
assert(parser->chunks->begin != NULL);
|
|
1276
|
+
assert(parser->chunks->remain != 0);
|
|
1277
|
+
|
|
1278
|
+
p = parser->chunks->begin;
|
|
1279
|
+
|
|
1280
|
+
if (parser->stack) {
|
|
1281
|
+
container = parser->stack->obj;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
/*
|
|
1285
|
+
* When we start parsing message pack chunk, we must ensure that we
|
|
1286
|
+
* have either a valid container or the top object inside message pack is
|
|
1287
|
+
* of container type
|
|
1288
|
+
*/
|
|
1289
|
+
if (container == NULL) {
|
|
1290
|
+
if ((*p & 0x80) != 0x80 && !(*p >= 0xdc && *p <= 0xdf)) {
|
|
1291
|
+
ucl_create_err(&parser->err, "bad top level object for msgpack");
|
|
1292
|
+
return false;
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
ret = ucl_msgpack_consume(parser);
|
|
1297
|
+
|
|
1298
|
+
if (ret && parser->top_obj == NULL) {
|
|
1299
|
+
parser->top_obj = parser->cur_obj;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
return ret;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
static ssize_t
|
|
1306
|
+
ucl_msgpack_parse_map(struct ucl_parser *parser,
|
|
1307
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
1308
|
+
const unsigned char *pos, size_t remain)
|
|
1309
|
+
{
|
|
1310
|
+
container->obj = parser->cur_obj;
|
|
1311
|
+
|
|
1312
|
+
return 0;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
static ssize_t
|
|
1316
|
+
ucl_msgpack_parse_array(struct ucl_parser *parser,
|
|
1317
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
1318
|
+
const unsigned char *pos, size_t remain)
|
|
1319
|
+
{
|
|
1320
|
+
container->obj = parser->cur_obj;
|
|
1321
|
+
|
|
1322
|
+
return 0;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
static ssize_t
|
|
1326
|
+
ucl_msgpack_parse_string(struct ucl_parser *parser,
|
|
1327
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
1328
|
+
const unsigned char *pos, size_t remain)
|
|
1329
|
+
{
|
|
1330
|
+
ucl_object_t *obj;
|
|
1331
|
+
|
|
1332
|
+
if (len > remain) {
|
|
1333
|
+
return -1;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
obj = ucl_object_new_full(UCL_STRING, parser->chunks->priority);
|
|
1337
|
+
obj->value.sv = pos;
|
|
1338
|
+
obj->len = len;
|
|
1339
|
+
|
|
1340
|
+
if (fmt >= msgpack_bin8 && fmt <= msgpack_bin32) {
|
|
1341
|
+
obj->flags |= UCL_OBJECT_BINARY;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
if (!(parser->flags & UCL_PARSER_ZEROCOPY)) {
|
|
1345
|
+
if (obj->flags & UCL_OBJECT_BINARY) {
|
|
1346
|
+
obj->trash_stack[UCL_TRASH_VALUE] = malloc(len);
|
|
1347
|
+
|
|
1348
|
+
if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
|
|
1349
|
+
memcpy(obj->trash_stack[UCL_TRASH_VALUE], pos, len);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
else {
|
|
1353
|
+
ucl_copy_value_trash(obj);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
parser->cur_obj = obj;
|
|
1358
|
+
|
|
1359
|
+
return len;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
static ssize_t
|
|
1363
|
+
ucl_msgpack_parse_int(struct ucl_parser *parser,
|
|
1364
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
1365
|
+
const unsigned char *pos, size_t remain)
|
|
1366
|
+
{
|
|
1367
|
+
ucl_object_t *obj;
|
|
1368
|
+
int8_t iv8;
|
|
1369
|
+
int16_t iv16;
|
|
1370
|
+
int32_t iv32;
|
|
1371
|
+
int64_t iv64;
|
|
1372
|
+
uint16_t uiv16;
|
|
1373
|
+
uint32_t uiv32;
|
|
1374
|
+
uint64_t uiv64;
|
|
1375
|
+
|
|
1376
|
+
|
|
1377
|
+
if (len > remain) {
|
|
1378
|
+
return -1;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
obj = ucl_object_new_full(UCL_INT, parser->chunks->priority);
|
|
1382
|
+
|
|
1383
|
+
switch (fmt) {
|
|
1384
|
+
case msgpack_positive_fixint:
|
|
1385
|
+
obj->value.iv = (*pos & 0x7f);
|
|
1386
|
+
len = 1;
|
|
1387
|
+
break;
|
|
1388
|
+
case msgpack_negative_fixint:
|
|
1389
|
+
obj->value.iv = -(*pos & 0x1f);
|
|
1390
|
+
len = 1;
|
|
1391
|
+
break;
|
|
1392
|
+
case msgpack_uint8:
|
|
1393
|
+
obj->value.iv = (unsigned char) *pos;
|
|
1394
|
+
len = 1;
|
|
1395
|
+
break;
|
|
1396
|
+
case msgpack_int8:
|
|
1397
|
+
memcpy(&iv8, pos, sizeof(iv8));
|
|
1398
|
+
obj->value.iv = iv8;
|
|
1399
|
+
len = 1;
|
|
1400
|
+
break;
|
|
1401
|
+
case msgpack_int16:
|
|
1402
|
+
memcpy(&iv16, pos, sizeof(iv16));
|
|
1403
|
+
iv16 = FROM_BE16(iv16);
|
|
1404
|
+
obj->value.iv = iv16;
|
|
1405
|
+
len = 2;
|
|
1406
|
+
break;
|
|
1407
|
+
case msgpack_uint16:
|
|
1408
|
+
memcpy(&uiv16, pos, sizeof(uiv16));
|
|
1409
|
+
uiv16 = FROM_BE16(uiv16);
|
|
1410
|
+
obj->value.iv = uiv16;
|
|
1411
|
+
len = 2;
|
|
1412
|
+
break;
|
|
1413
|
+
case msgpack_int32:
|
|
1414
|
+
memcpy(&iv32, pos, sizeof(iv32));
|
|
1415
|
+
iv32 = FROM_BE32(iv32);
|
|
1416
|
+
obj->value.iv = iv32;
|
|
1417
|
+
len = 4;
|
|
1418
|
+
break;
|
|
1419
|
+
case msgpack_uint32:
|
|
1420
|
+
memcpy(&uiv32, pos, sizeof(uiv32));
|
|
1421
|
+
uiv32 = FROM_BE32(uiv32);
|
|
1422
|
+
obj->value.iv = uiv32;
|
|
1423
|
+
len = 4;
|
|
1424
|
+
break;
|
|
1425
|
+
case msgpack_int64:
|
|
1426
|
+
memcpy(&iv64, pos, sizeof(iv64));
|
|
1427
|
+
iv64 = FROM_BE64(iv64);
|
|
1428
|
+
obj->value.iv = iv64;
|
|
1429
|
+
len = 8;
|
|
1430
|
+
break;
|
|
1431
|
+
case msgpack_uint64:
|
|
1432
|
+
memcpy(&uiv64, pos, sizeof(uiv64));
|
|
1433
|
+
uiv64 = FROM_BE64(uiv64);
|
|
1434
|
+
obj->value.iv = uiv64;
|
|
1435
|
+
len = 8;
|
|
1436
|
+
break;
|
|
1437
|
+
default:
|
|
1438
|
+
assert(0);
|
|
1439
|
+
break;
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
parser->cur_obj = obj;
|
|
1443
|
+
|
|
1444
|
+
return len;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
static ssize_t
|
|
1448
|
+
ucl_msgpack_parse_float(struct ucl_parser *parser,
|
|
1449
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
1450
|
+
const unsigned char *pos, size_t remain)
|
|
1451
|
+
{
|
|
1452
|
+
ucl_object_t *obj;
|
|
1453
|
+
union {
|
|
1454
|
+
uint32_t i;
|
|
1455
|
+
float f;
|
|
1456
|
+
} d;
|
|
1457
|
+
uint64_t uiv64;
|
|
1458
|
+
|
|
1459
|
+
if (len > remain) {
|
|
1460
|
+
return -1;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
obj = ucl_object_new_full(UCL_FLOAT, parser->chunks->priority);
|
|
1464
|
+
|
|
1465
|
+
switch (fmt) {
|
|
1466
|
+
case msgpack_float32:
|
|
1467
|
+
memcpy(&d.i, pos, sizeof(d.i));
|
|
1468
|
+
d.i = FROM_BE32(d.i);
|
|
1469
|
+
/* XXX: can be slow */
|
|
1470
|
+
obj->value.dv = d.f;
|
|
1471
|
+
len = 4;
|
|
1472
|
+
break;
|
|
1473
|
+
case msgpack_float64:
|
|
1474
|
+
memcpy(&uiv64, pos, sizeof(uiv64));
|
|
1475
|
+
uiv64 = FROM_BE64(uiv64);
|
|
1476
|
+
obj->value.iv = uiv64;
|
|
1477
|
+
len = 8;
|
|
1478
|
+
break;
|
|
1479
|
+
default:
|
|
1480
|
+
assert(0);
|
|
1481
|
+
break;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
parser->cur_obj = obj;
|
|
1485
|
+
|
|
1486
|
+
return len;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
static ssize_t
|
|
1490
|
+
ucl_msgpack_parse_bool(struct ucl_parser *parser,
|
|
1491
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
1492
|
+
const unsigned char *pos, size_t remain)
|
|
1493
|
+
{
|
|
1494
|
+
ucl_object_t *obj;
|
|
1495
|
+
|
|
1496
|
+
if (len > remain) {
|
|
1497
|
+
return -1;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
obj = ucl_object_new_full(UCL_BOOLEAN, parser->chunks->priority);
|
|
1501
|
+
|
|
1502
|
+
switch (fmt) {
|
|
1503
|
+
case msgpack_true:
|
|
1504
|
+
obj->value.iv = true;
|
|
1505
|
+
break;
|
|
1506
|
+
case msgpack_false:
|
|
1507
|
+
obj->value.iv = false;
|
|
1508
|
+
break;
|
|
1509
|
+
default:
|
|
1510
|
+
assert(0);
|
|
1511
|
+
break;
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
parser->cur_obj = obj;
|
|
1515
|
+
|
|
1516
|
+
return 1;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
static ssize_t
|
|
1520
|
+
ucl_msgpack_parse_null(struct ucl_parser *parser,
|
|
1521
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
1522
|
+
const unsigned char *pos, size_t remain)
|
|
1523
|
+
{
|
|
1524
|
+
ucl_object_t *obj;
|
|
1525
|
+
|
|
1526
|
+
if (len > remain) {
|
|
1527
|
+
return -1;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
obj = ucl_object_new_full(UCL_NULL, parser->chunks->priority);
|
|
1531
|
+
parser->cur_obj = obj;
|
|
1532
|
+
|
|
1533
|
+
return 1;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
static ssize_t
|
|
1537
|
+
ucl_msgpack_parse_ignore(struct ucl_parser *parser,
|
|
1538
|
+
struct ucl_stack *container, size_t len, enum ucl_msgpack_format fmt,
|
|
1539
|
+
const unsigned char *pos, size_t remain)
|
|
1540
|
+
{
|
|
1541
|
+
if (len > remain) {
|
|
1542
|
+
return -1;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
switch (fmt) {
|
|
1546
|
+
case msgpack_fixext1:
|
|
1547
|
+
len = 2;
|
|
1548
|
+
break;
|
|
1549
|
+
case msgpack_fixext2:
|
|
1550
|
+
len = 3;
|
|
1551
|
+
break;
|
|
1552
|
+
case msgpack_fixext4:
|
|
1553
|
+
len = 5;
|
|
1554
|
+
break;
|
|
1555
|
+
case msgpack_fixext8:
|
|
1556
|
+
len = 9;
|
|
1557
|
+
break;
|
|
1558
|
+
case msgpack_fixext16:
|
|
1559
|
+
len = 17;
|
|
1560
|
+
break;
|
|
1561
|
+
case msgpack_ext8:
|
|
1562
|
+
case msgpack_ext16:
|
|
1563
|
+
case msgpack_ext32:
|
|
1564
|
+
len = len + 1;
|
|
1565
|
+
break;
|
|
1566
|
+
default:
|
|
1567
|
+
ucl_create_err(&parser->err, "bad type: %x", (unsigned) fmt);
|
|
1568
|
+
return -1;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
parser->cur_obj = NULL;
|
|
1572
|
+
|
|
1573
|
+
return len;
|
|
1574
|
+
}
|