1 /*
2 * MessagePack unpacking routine template
3 *
4 * Copyright (C) 2008-2010 FURUHASHI Sadayuki
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #ifndef msgpack_unpack_func
20 #error msgpack_unpack_func template is not defined
21 #endif
22
23 #ifndef msgpack_unpack_callback
24 #error msgpack_unpack_callback template is not defined
25 #endif
26
27 #ifndef msgpack_unpack_struct
28 #error msgpack_unpack_struct template is not defined
29 #endif
30
31 #ifndef msgpack_unpack_struct_decl
32 #define msgpack_unpack_struct_decl(name) msgpack_unpack_struct(name)
33 #endif
34
35 #ifndef msgpack_unpack_object
36 #error msgpack_unpack_object type is not defined
37 #endif
38
39 #ifndef msgpack_unpack_user
40 #error msgpack_unpack_user type is not defined
41 #endif
42
43 #ifndef USE_CASE_RANGE
44 #if !defined(_MSC_VER)
45 #define USE_CASE_RANGE
46 #endif
47 #endif
48
msgpack_unpack_struct_decl(_stack)49 msgpack_unpack_struct_decl(_stack) {
50 msgpack_unpack_object obj;
51 size_t count;
52 unsigned int ct;
53 msgpack_unpack_object map_key;
54 };
55
msgpack_unpack_struct_decl(_context)56 msgpack_unpack_struct_decl(_context) {
57 msgpack_unpack_user user;
58 unsigned int cs;
59 unsigned int trail;
60 unsigned int top;
61 /*
62 msgpack_unpack_struct(_stack)* stack;
63 unsigned int stack_size;
64 msgpack_unpack_struct(_stack) embed_stack[MSGPACK_EMBED_STACK_SIZE];
65 */
66 msgpack_unpack_struct(_stack) stack[MSGPACK_EMBED_STACK_SIZE];
67 };
68
69
msgpack_unpack_func(void,_init)70 msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx)
71 {
72 ctx->cs = MSGPACK_CS_HEADER;
73 ctx->trail = 0;
74 ctx->top = 0;
75 /*
76 ctx->stack = ctx->embed_stack;
77 ctx->stack_size = MSGPACK_EMBED_STACK_SIZE;
78 */
79 ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user);
80 }
81
82 /*
83 msgpack_unpack_func(void, _destroy)(msgpack_unpack_struct(_context)* ctx)
84 {
85 if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) {
86 free(ctx->stack);
87 }
88 }
89 */
90
msgpack_unpack_func(msgpack_unpack_object,_data)91 msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx)
92 {
93 return (ctx)->stack[0].obj;
94 }
95
96
msgpack_unpack_func(int,_execute)97 msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off)
98 {
99 assert(len >= *off);
100 {
101 const unsigned char* p = (unsigned char*)data + *off;
102 const unsigned char* const pe = (unsigned char*)data + len;
103 const void* n = NULL;
104
105 unsigned int trail = ctx->trail;
106 unsigned int cs = ctx->cs;
107 unsigned int top = ctx->top;
108 msgpack_unpack_struct(_stack)* stack = ctx->stack;
109 /*
110 unsigned int stack_size = ctx->stack_size;
111 */
112 msgpack_unpack_user* user = &ctx->user;
113
114 msgpack_unpack_object obj;
115 msgpack_unpack_struct(_stack)* c = NULL;
116
117 int ret;
118
119 #define push_simple_value(func) \
120 if(msgpack_unpack_callback(func)(user, &obj) < 0) { goto _failed; } \
121 goto _push
122 #define push_fixed_value(func, arg) \
123 if(msgpack_unpack_callback(func)(user, arg, &obj) < 0) { goto _failed; } \
124 goto _push
125 #define push_variable_value(func, base, pos, len) \
126 if(msgpack_unpack_callback(func)(user, \
127 (const char*)base, (const char*)pos, len, &obj) < 0) { goto _failed; } \
128 goto _push
129
130 #define again_fixed_trail(_cs, trail_len) \
131 trail = trail_len; \
132 cs = _cs; \
133 goto _fixed_trail_again
134 #define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \
135 trail = trail_len; \
136 if(trail == 0) { goto ifzero; } \
137 cs = _cs; \
138 goto _fixed_trail_again
139
140 #define start_container(func, count_, ct_) \
141 if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */ \
142 if(msgpack_unpack_callback(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \
143 if((count_) == 0) { obj = stack[top].obj; goto _push; } \
144 stack[top].ct = ct_; \
145 stack[top].count = count_; \
146 ++top; \
147 /*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \
148 /*printf("stack push %d\n", top);*/ \
149 /* FIXME \
150 if(top >= stack_size) { \
151 if(stack_size == MSGPACK_EMBED_STACK_SIZE) { \
152 size_t csize = sizeof(msgpack_unpack_struct(_stack)) * MSGPACK_EMBED_STACK_SIZE; \
153 size_t nsize = csize * 2; \
154 msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)malloc(nsize); \
155 if(tmp == NULL) { goto _failed; } \
156 memcpy(tmp, ctx->stack, csize); \
157 ctx->stack = stack = tmp; \
158 ctx->stack_size = stack_size = MSGPACK_EMBED_STACK_SIZE * 2; \
159 } else { \
160 size_t nsize = sizeof(msgpack_unpack_struct(_stack)) * ctx->stack_size * 2; \
161 msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)realloc(ctx->stack, nsize); \
162 if(tmp == NULL) { goto _failed; } \
163 ctx->stack = stack = tmp; \
164 ctx->stack_size = stack_size = stack_size * 2; \
165 } \
166 } \
167 */ \
168 goto _header_again
169
170 #define NEXT_CS(p) \
171 ((unsigned int)*p & 0x1f)
172
173 #ifdef USE_CASE_RANGE
174 #define SWITCH_RANGE_BEGIN switch(*p) {
175 #define SWITCH_RANGE(FROM, TO) case FROM ... TO:
176 #define SWITCH_RANGE_DEFAULT default:
177 #define SWITCH_RANGE_END }
178 #else
179 #define SWITCH_RANGE_BEGIN { if(0) {
180 #define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) {
181 #define SWITCH_RANGE_DEFAULT } else {
182 #define SWITCH_RANGE_END } }
183 #endif
184
185 if(p == pe) { goto _out; }
186 do {
187 switch(cs) {
188 case MSGPACK_CS_HEADER:
189 SWITCH_RANGE_BEGIN
190 SWITCH_RANGE(0x00, 0x7f) // Positive Fixnum
191 push_fixed_value(_uint8, *(uint8_t*)p);
192 SWITCH_RANGE(0xe0, 0xff) // Negative Fixnum
193 push_fixed_value(_int8, *(int8_t*)p);
194 SWITCH_RANGE(0xc0, 0xdf) // Variable
195 switch(*p) {
196 case 0xc0: // nil
197 push_simple_value(_nil);
198 //case 0xc1: // string
199 // again_terminal_trail(NEXT_CS(p), p+1);
200 case 0xc2: // false
201 push_simple_value(_false);
202 case 0xc3: // true
203 push_simple_value(_true);
204 case 0xc4: // bin 8
205 case 0xc5: // bin 16
206 case 0xc6: // bin 32
207 again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
208 case 0xc7: // ext 8
209 case 0xc8: // ext 16
210 case 0xc9: // ext 32
211 again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) + 1) & 0x03));
212 case 0xca: // float
213 case 0xcb: // double
214 case 0xcc: // unsigned int 8
215 case 0xcd: // unsigned int 16
216 case 0xce: // unsigned int 32
217 case 0xcf: // unsigned int 64
218 case 0xd0: // signed int 8
219 case 0xd1: // signed int 16
220 case 0xd2: // signed int 32
221 case 0xd3: // signed int 64
222 again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
223 case 0xd4: // fixext 1
224 case 0xd5: // fixext 2
225 case 0xd6: // fixext 4
226 case 0xd7: // fixext 8
227 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE,
228 (1 << (((unsigned int)*p) & 0x03)) + 1, _ext_zero);
229 case 0xd8: // fixext 16
230 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero);
231
232 case 0xd9: // str 8
233 case 0xda: // str 16
234 case 0xdb: // str 32
235 again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) & 0x03) - 1));
236 case 0xdc: // array 16
237 case 0xdd: // array 32
238 case 0xde: // map 16
239 case 0xdf: // map 32
240 again_fixed_trail(NEXT_CS(p), 2u << (((unsigned int)*p) & 0x01));
241 default:
242 goto _failed;
243 }
244 SWITCH_RANGE(0xa0, 0xbf) // FixStr
245 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, ((unsigned int)*p & 0x1f), _str_zero);
246 SWITCH_RANGE(0x90, 0x9f) // FixArray
247 start_container(_array, ((unsigned int)*p) & 0x0f, MSGPACK_CT_ARRAY_ITEM);
248 SWITCH_RANGE(0x80, 0x8f) // FixMap
249 start_container(_map, ((unsigned int)*p) & 0x0f, MSGPACK_CT_MAP_KEY);
250
251 SWITCH_RANGE_DEFAULT
252 goto _failed;
253 SWITCH_RANGE_END
254 // end MSGPACK_CS_HEADER
255
256
257 _fixed_trail_again:
258 ++p;
259
260 default:
261 if((size_t)(pe - p) < trail) { goto _out; }
262 n = p; p += trail - 1;
263 switch(cs) {
264 //case MSGPACK_CS_
265 //case MSGPACK_CS_
266 case MSGPACK_CS_FLOAT: {
267 union { uint32_t i; float f; } mem;
268 _msgpack_load32(uint32_t, n, &mem.i);
269 push_fixed_value(_float, mem.f); }
270 case MSGPACK_CS_DOUBLE: {
271 union { uint64_t i; double f; } mem;
272 _msgpack_load64(uint64_t, n, &mem.i);
273 #if defined(TARGET_OS_IPHONE)
274 // ok
275 #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi
276 // https://github.com/msgpack/msgpack-perl/pull/1
277 mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
278 #endif
279 push_fixed_value(_double, mem.f); }
280 case MSGPACK_CS_UINT_8:
281 push_fixed_value(_uint8, *(uint8_t*)n);
282 case MSGPACK_CS_UINT_16:{
283 uint16_t tmp;
284 _msgpack_load16(uint16_t,n,&tmp);
285 push_fixed_value(_uint16, tmp);
286 }
287 case MSGPACK_CS_UINT_32:{
288 uint32_t tmp;
289 _msgpack_load32(uint32_t,n,&tmp);
290 push_fixed_value(_uint32, tmp);
291 }
292 case MSGPACK_CS_UINT_64:{
293 uint64_t tmp;
294 _msgpack_load64(uint64_t,n,&tmp);
295 push_fixed_value(_uint64, tmp);
296 }
297 case MSGPACK_CS_INT_8:
298 push_fixed_value(_int8, *(int8_t*)n);
299 case MSGPACK_CS_INT_16:{
300 int16_t tmp;
301 _msgpack_load16(int16_t,n,&tmp);
302 push_fixed_value(_int16, tmp);
303 }
304 case MSGPACK_CS_INT_32:{
305 int32_t tmp;
306 _msgpack_load32(int32_t,n,&tmp);
307 push_fixed_value(_int32, tmp);
308 }
309 case MSGPACK_CS_INT_64:{
310 int64_t tmp;
311 _msgpack_load64(int64_t,n,&tmp);
312 push_fixed_value(_int64, tmp);
313 }
314 case MSGPACK_CS_FIXEXT_1:
315 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 1+1, _ext_zero);
316 case MSGPACK_CS_FIXEXT_2:
317 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 2+1, _ext_zero);
318 case MSGPACK_CS_FIXEXT_4:
319 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 4+1, _ext_zero);
320 case MSGPACK_CS_FIXEXT_8:
321 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 8+1, _ext_zero);
322 case MSGPACK_CS_FIXEXT_16:
323 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero);
324 case MSGPACK_CS_STR_8:
325 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, *(uint8_t*)n, _str_zero);
326 case MSGPACK_CS_BIN_8:
327 again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, *(uint8_t*)n, _bin_zero);
328 case MSGPACK_CS_EXT_8:
329 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, (*(uint8_t*)n) + 1, _ext_zero);
330 case MSGPACK_CS_STR_16:{
331 uint16_t tmp;
332 _msgpack_load16(uint16_t,n,&tmp);
333 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero);
334 }
335 case MSGPACK_CS_BIN_16:{
336 uint16_t tmp;
337 _msgpack_load16(uint16_t,n,&tmp);
338 again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero);
339 }
340 case MSGPACK_CS_EXT_16:{
341 uint16_t tmp;
342 _msgpack_load16(uint16_t,n,&tmp);
343 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero);
344 }
345 case MSGPACK_CS_STR_32:{
346 uint32_t tmp;
347 _msgpack_load32(uint32_t,n,&tmp);
348 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero);
349 }
350 case MSGPACK_CS_BIN_32:{
351 uint32_t tmp;
352 _msgpack_load32(uint32_t,n,&tmp);
353 again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero);
354 }
355 case MSGPACK_CS_EXT_32:{
356 uint32_t tmp;
357 _msgpack_load32(uint32_t,n,&tmp);
358 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero);
359 }
360 case MSGPACK_ACS_STR_VALUE:
361 _str_zero:
362 push_variable_value(_str, data, n, trail);
363 case MSGPACK_ACS_BIN_VALUE:
364 _bin_zero:
365 push_variable_value(_bin, data, n, trail);
366 case MSGPACK_ACS_EXT_VALUE:
367 _ext_zero:
368 push_variable_value(_ext, data, n, trail);
369
370 case MSGPACK_CS_ARRAY_16:{
371 uint16_t tmp;
372 _msgpack_load16(uint16_t,n,&tmp);
373 start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM);
374 }
375 case MSGPACK_CS_ARRAY_32:{
376 /* FIXME security guard */
377 uint32_t tmp;
378 _msgpack_load32(uint32_t,n,&tmp);
379 start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM);
380 }
381
382 case MSGPACK_CS_MAP_16:{
383 uint16_t tmp;
384 _msgpack_load16(uint16_t,n,&tmp);
385 start_container(_map, tmp, MSGPACK_CT_MAP_KEY);
386 }
387 case MSGPACK_CS_MAP_32:{
388 /* FIXME security guard */
389 uint32_t tmp;
390 _msgpack_load32(uint32_t,n,&tmp);
391 start_container(_map, tmp, MSGPACK_CT_MAP_KEY);
392 }
393
394 default:
395 goto _failed;
396 }
397 }
398
399 _push:
400 if(top == 0) { goto _finish; }
401 c = &stack[top-1];
402 switch(c->ct) {
403 case MSGPACK_CT_ARRAY_ITEM:
404 if(msgpack_unpack_callback(_array_item)(user, &c->obj, obj) < 0) { goto _failed; }
405 if(--c->count == 0) {
406 obj = c->obj;
407 --top;
408 /*printf("stack pop %d\n", top);*/
409 goto _push;
410 }
411 goto _header_again;
412 case MSGPACK_CT_MAP_KEY:
413 c->map_key = obj;
414 c->ct = MSGPACK_CT_MAP_VALUE;
415 goto _header_again;
416 case MSGPACK_CT_MAP_VALUE:
417 if(msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj) < 0) { goto _failed; }
418 if(--c->count == 0) {
419 obj = c->obj;
420 --top;
421 /*printf("stack pop %d\n", top);*/
422 goto _push;
423 }
424 c->ct = MSGPACK_CT_MAP_KEY;
425 goto _header_again;
426
427 default:
428 goto _failed;
429 }
430
431 _header_again:
432 cs = MSGPACK_CS_HEADER;
433 ++p;
434 } while(p != pe);
435 goto _out;
436
437
438 _finish:
439 stack[0].obj = obj;
440 ++p;
441 ret = 1;
442 /*printf("-- finish --\n"); */
443 goto _end;
444
445 _failed:
446 /*printf("** FAILED **\n"); */
447 ret = -1;
448 goto _end;
449
450 _out:
451 ret = 0;
452 goto _end;
453
454 _end:
455 ctx->cs = cs;
456 ctx->trail = trail;
457 ctx->top = top;
458 *off = (size_t)(p - (const unsigned char*)data);
459
460 return ret;
461 }
462 }
463
464 #undef msgpack_unpack_func
465 #undef msgpack_unpack_callback
466 #undef msgpack_unpack_struct
467 #undef msgpack_unpack_object
468 #undef msgpack_unpack_user
469
470 #undef push_simple_value
471 #undef push_fixed_value
472 #undef push_variable_value
473 #undef again_fixed_trail
474 #undef again_fixed_trail_if_zero
475 #undef start_container
476
477 #undef NEXT_CS
478
479 #undef SWITCH_RANGE_BEGIN
480 #undef SWITCH_RANGE
481 #undef SWITCH_RANGE_DEFAULT
482 #undef SWITCH_RANGE_END
483