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