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