File Coverage

deps/msgpack-c/include/msgpack/unpack_template.h
Criterion Covered Total %
statement 74 136 54.4
branch 28 126 22.2
condition n/a
subroutine n/a
pod n/a
total 102 262 38.9


line stmt bran cond sub pod time code
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              
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              
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              
67 15           msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx)
68             {
69 15           ctx->cs = MSGPACK_CS_HEADER;
70 15           ctx->trail = 0;
71 15           ctx->top = 0;
72             /*
73             ctx->stack = ctx->embed_stack;
74             ctx->stack_size = MSGPACK_EMBED_STACK_SIZE;
75             */
76 15           ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user);
77 15           }
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              
88 9           msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx)
89             {
90 9           return (ctx)->stack[0].obj;
91             }
92              
93              
94 16           msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off)
95             {
96 16 50         assert(len >= *off);
97             {
98 16           const unsigned char* p = (unsigned char*)data + *off;
99 16           const unsigned char* const pe = (unsigned char*)data + len;
100 16           const void* n = NULL;
101              
102 16           unsigned int trail = ctx->trail;
103 16           unsigned int cs = ctx->cs;
104 16           unsigned int top = ctx->top;
105 16           msgpack_unpack_struct(_stack)* stack = ctx->stack;
106             /*
107             unsigned int stack_size = ctx->stack_size;
108             */
109 16           msgpack_unpack_user* user = &ctx->user;
110              
111             msgpack_unpack_object obj;
112 16           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 16 100         if(p == pe) { goto _out; }
169             do {
170 21 50         switch(cs) {
171             case MSGPACK_CS_HEADER:
172 21           SWITCH_RANGE_BEGIN
173             SWITCH_RANGE(0x00, 0x7f) // Positive Fixnum
174 1 50         push_fixed_value(_uint8, *(uint8_t*)p);
175             SWITCH_RANGE(0xe0, 0xff) // Negative Fixnum
176 0 0         push_fixed_value(_int8, *(int8_t*)p);
177             SWITCH_RANGE(0xc0, 0xdf) // Variable
178 16           switch(*p) {
179             case 0xc0: // nil
180 0 0         push_simple_value(_nil);
181             //case 0xc1: // string
182             // again_terminal_trail(NEXT_CS(p), p+1);
183             case 0xc2: // false
184 2 50         push_simple_value(_false);
185             case 0xc3: // true
186 2 50         push_simple_value(_true);
187             case 0xc4: // bin 8
188             case 0xc5: // bin 16
189             case 0xc6: // bin 32
190 10           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 1           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 0           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 1 50         again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE,
211             (1 << (((unsigned int)*p) & 0x03)) + 1, _ext_zero);
212             case 0xd8: // fixext 16
213 0 0         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 0           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 0           again_fixed_trail(NEXT_CS(p), 2u << (((unsigned int)*p) & 0x01));
224             default:
225 0           ret = MSGPACK_UNPACK_PARSE_ERROR;
226 0           goto _failed;
227             }
228             SWITCH_RANGE(0xa0, 0xbf) // FixStr
229 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, ((unsigned int)*p & 0x1f), _str_zero);
230             SWITCH_RANGE(0x90, 0x9f) // FixArray
231 2 50         start_container(_array, ((unsigned int)*p) & 0x0f, MSGPACK_CT_ARRAY_ITEM);
    50          
    50          
232             SWITCH_RANGE(0x80, 0x8f) // FixMap
233 2 50         start_container(_map, ((unsigned int)*p) & 0x0f, MSGPACK_CT_MAP_KEY);
    50          
    50          
234              
235             SWITCH_RANGE_DEFAULT
236 0           ret = MSGPACK_UNPACK_PARSE_ERROR;
237 0           goto _failed;
238             SWITCH_RANGE_END
239             // end MSGPACK_CS_HEADER
240              
241              
242             _fixed_trail_again:
243 23           ++p;
244             // fallthrough
245              
246             default:
247 23 50         if((size_t)(pe - p) < trail) { goto _out; }
248 23           n = p; p += trail - 1;
249 23           switch(cs) {
250             //case MSGPACK_CS_
251             //case MSGPACK_CS_
252             case MSGPACK_CS_FLOAT: {
253             union { uint32_t i; float f; } mem;
254 0           _msgpack_load32(uint32_t, n, &mem.i);
255 0 0         push_fixed_value(_float, mem.f); }
256             case MSGPACK_CS_DOUBLE: {
257             union { uint64_t i; double f; } mem;
258 0           _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 0 0         push_fixed_value(_double, mem.f); }
266             case MSGPACK_CS_UINT_8:
267 0 0         push_fixed_value(_uint8, *(uint8_t*)n);
268             case MSGPACK_CS_UINT_16:{
269             uint16_t tmp;
270 0           _msgpack_load16(uint16_t,n,&tmp);
271 0 0         push_fixed_value(_uint16, tmp);
272             }
273             case MSGPACK_CS_UINT_32:{
274             uint32_t tmp;
275 0           _msgpack_load32(uint32_t,n,&tmp);
276 0 0         push_fixed_value(_uint32, tmp);
277             }
278             case MSGPACK_CS_UINT_64:{
279             uint64_t tmp;
280 0           _msgpack_load64(uint64_t,n,&tmp);
281 0 0         push_fixed_value(_uint64, tmp);
282             }
283             case MSGPACK_CS_INT_8:
284 0 0         push_fixed_value(_int8, *(int8_t*)n);
285             case MSGPACK_CS_INT_16:{
286             int16_t tmp;
287 0           _msgpack_load16(int16_t,n,&tmp);
288 0 0         push_fixed_value(_int16, tmp);
289             }
290             case MSGPACK_CS_INT_32:{
291             int32_t tmp;
292 0           _msgpack_load32(int32_t,n,&tmp);
293 0 0         push_fixed_value(_int32, tmp);
294             }
295             case MSGPACK_CS_INT_64:{
296             int64_t tmp;
297 0           _msgpack_load64(int64_t,n,&tmp);
298 0 0         push_fixed_value(_int64, tmp);
299             }
300             case MSGPACK_CS_FIXEXT_1:
301 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 1+1, _ext_zero);
302             case MSGPACK_CS_FIXEXT_2:
303 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 2+1, _ext_zero);
304             case MSGPACK_CS_FIXEXT_4:
305 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 4+1, _ext_zero);
306             case MSGPACK_CS_FIXEXT_8:
307 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 8+1, _ext_zero);
308             case MSGPACK_CS_FIXEXT_16:
309 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero);
310             case MSGPACK_CS_STR_8:
311 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, *(uint8_t*)n, _str_zero);
312             case MSGPACK_CS_BIN_8:
313 10 50         again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, *(uint8_t*)n, _bin_zero);
314             case MSGPACK_CS_EXT_8:
315 1 50         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 0           _msgpack_load16(uint16_t,n,&tmp);
319 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero);
320             }
321             case MSGPACK_CS_BIN_16:{
322             uint16_t tmp;
323 0           _msgpack_load16(uint16_t,n,&tmp);
324 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero);
325             }
326             case MSGPACK_CS_EXT_16:{
327             uint16_t tmp;
328 0           _msgpack_load16(uint16_t,n,&tmp);
329 0 0         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 0           _msgpack_load32(uint32_t,n,&tmp);
334 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero);
335             }
336             case MSGPACK_CS_BIN_32:{
337             uint32_t tmp;
338 0           _msgpack_load32(uint32_t,n,&tmp);
339 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero);
340             }
341             case MSGPACK_CS_EXT_32:{
342             uint32_t tmp;
343 0           _msgpack_load32(uint32_t,n,&tmp);
344 0 0         again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero);
345             }
346             case MSGPACK_ACS_STR_VALUE:
347             _str_zero:
348 0 0         push_variable_value(_str, data, n, trail);
349             case MSGPACK_ACS_BIN_VALUE:
350             _bin_zero:
351 10 50         push_variable_value(_bin, data, n, trail);
352             case MSGPACK_ACS_EXT_VALUE:
353             _ext_zero:
354 2 50         push_variable_value(_ext, data, n, trail);
355              
356             case MSGPACK_CS_ARRAY_16:{
357             uint16_t tmp;
358 0           _msgpack_load16(uint16_t,n,&tmp);
359 0 0         start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM);
    0          
    0          
360             }
361             case MSGPACK_CS_ARRAY_32:{
362             /* FIXME security guard */
363             uint32_t tmp;
364 0           _msgpack_load32(uint32_t,n,&tmp);
365 0 0         start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM);
    0          
    0          
366             }
367              
368             case MSGPACK_CS_MAP_16:{
369             uint16_t tmp;
370 0           _msgpack_load16(uint16_t,n,&tmp);
371 0 0         start_container(_map, tmp, MSGPACK_CT_MAP_KEY);
    0          
    0          
372             }
373             case MSGPACK_CS_MAP_32:{
374             /* FIXME security guard */
375             uint32_t tmp;
376 0           _msgpack_load32(uint32_t,n,&tmp);
377 0 0         start_container(_map, tmp, MSGPACK_CT_MAP_KEY);
    0          
    0          
378             }
379              
380             default:
381 0           ret = MSGPACK_UNPACK_PARSE_ERROR;
382 0           goto _failed;
383             }
384             }
385              
386             _push:
387 21 100         if(top == 0) { goto _finish; }
388 12           c = &stack[top-1];
389 12           switch(c->ct) {
390             case MSGPACK_CT_ARRAY_ITEM:
391 4           ret = msgpack_unpack_callback(_array_item)(user, &c->obj, obj); \
392 4 50         if(ret < 0) { goto _failed; }
393 4 100         if(--c->count == 0) {
394 2           obj = c->obj;
395 2           --top;
396             /*printf("stack pop %d\n", top);*/
397 2           goto _push;
398             }
399 2           goto _header_again;
400             case MSGPACK_CT_MAP_KEY:
401 4           c->map_key = obj;
402 4           c->ct = MSGPACK_CT_MAP_VALUE;
403 4           goto _header_again;
404             case MSGPACK_CT_MAP_VALUE:
405 4           ret = msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj); \
406 4 50         if(ret < 0) { goto _failed; }
407 4 100         if(--c->count == 0) {
408 2           obj = c->obj;
409 2           --top;
410             /*printf("stack pop %d\n", top);*/
411 2           goto _push;
412             }
413 2           c->ct = MSGPACK_CT_MAP_KEY;
414 2           goto _header_again;
415              
416             default:
417 0           ret = MSGPACK_UNPACK_PARSE_ERROR;
418 0           goto _failed;
419             }
420              
421             _header_again:
422 12           cs = MSGPACK_CS_HEADER;
423 12           ++p;
424 12 50         } while(p != pe);
425 0           goto _out;
426              
427              
428             _finish:
429 9           stack[0].obj = obj;
430 9           ++p;
431 9           ret = 1;
432             /*printf("-- finish --\n"); */
433 9           goto _end;
434              
435             _failed:
436             /*printf("** FAILED **\n"); */
437 0           goto _end;
438              
439             _out:
440 7           ret = 0;
441 7           goto _end;
442              
443             _end:
444 16           ctx->cs = cs;
445 16           ctx->trail = trail;
446 16           ctx->top = top;
447 16           *off = (size_t)(p - (const unsigned char*)data);
448              
449 16           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