| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * MessagePack unpacking routine template | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-06-26 13:21:10 +09:00
										 |  |  |  * Copyright (C) 2008-2010 FURUHASHI Sadayuki | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  |  * | 
					
						
							|  |  |  |  *    Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  *    you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  *    You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *        http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *    Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  *    distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  *    See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  *    limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-17 10:43:22 +09:00
										 |  |  | #ifndef USE_CASE_RANGE
 | 
					
						
							|  |  |  | #if !defined(_MSC_VER)
 | 
					
						
							|  |  |  | #define USE_CASE_RANGE
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:12:20 +09:00
										 |  |  | typedef struct unpack_stack { | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     PyObject* obj; | 
					
						
							| 
									
										
										
										
											2015-11-07 16:30:18 +09:00
										 |  |  |     Py_ssize_t size; | 
					
						
							|  |  |  |     Py_ssize_t count; | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     unsigned int ct; | 
					
						
							|  |  |  |     PyObject* map_key; | 
					
						
							| 
									
										
										
										
											2013-02-27 21:12:20 +09:00
										 |  |  | } unpack_stack; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:12:20 +09:00
										 |  |  | struct unpack_context { | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     unpack_user user; | 
					
						
							|  |  |  |     unsigned int cs; | 
					
						
							|  |  |  |     unsigned int trail; | 
					
						
							|  |  |  |     unsigned int top; | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |     unpack_stack* stack; | 
					
						
							|  |  |  |     unsigned int stack_size; | 
					
						
							|  |  |  |     unpack_stack embed_stack[MSGPACK_EMBED_STACK_SIZE]; | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     unpack_stack stack[MSGPACK_EMBED_STACK_SIZE]; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:12:20 +09:00
										 |  |  | static inline void unpack_init(unpack_context* ctx) | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     ctx->cs = CS_HEADER; | 
					
						
							|  |  |  |     ctx->trail = 0; | 
					
						
							|  |  |  |     ctx->top = 0; | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |     ctx->stack = ctx->embed_stack; | 
					
						
							|  |  |  |     ctx->stack_size = MSGPACK_EMBED_STACK_SIZE; | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     ctx->stack[0].obj = unpack_callback_root(&ctx->user); | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-26 13:21:10 +09:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:12:20 +09:00
										 |  |  | static inline void unpack_destroy(unpack_context* ctx) | 
					
						
							| 
									
										
										
										
											2013-02-23 18:01:43 +09:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) { | 
					
						
							|  |  |  |         free(ctx->stack); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-02-23 18:01:43 +09:00
										 |  |  | } | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2012-06-26 13:21:10 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:12:20 +09:00
										 |  |  | static inline PyObject* unpack_data(unpack_context* ctx) | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     return (ctx)->stack[0].obj; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-09 01:50:40 +09:00
										 |  |  | static inline void unpack_clear(unpack_context *ctx) | 
					
						
							| 
									
										
										
										
											2015-11-08 12:38:38 +09:00
										 |  |  | { | 
					
						
							|  |  |  |     Py_CLEAR(ctx->stack[0].obj); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-25 00:30:15 +10:00
										 |  |  | template <bool construct> | 
					
						
							| 
									
										
										
										
											2015-11-07 16:30:18 +09:00
										 |  |  | static inline int unpack_execute(unpack_context* ctx, const char* data, Py_ssize_t len, Py_ssize_t* off) | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     assert(len >= *off); | 
					
						
							| 
									
										
										
										
											2012-06-26 13:21:10 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     const unsigned char* p = (unsigned char*)data + *off; | 
					
						
							|  |  |  |     const unsigned char* const pe = (unsigned char*)data + len; | 
					
						
							|  |  |  |     const void* n = NULL; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     unsigned int trail = ctx->trail; | 
					
						
							|  |  |  |     unsigned int cs = ctx->cs; | 
					
						
							|  |  |  |     unsigned int top = ctx->top; | 
					
						
							|  |  |  |     unpack_stack* stack = ctx->stack; | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |     unsigned int stack_size = ctx->stack_size; | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     unpack_user* user = &ctx->user; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-07 16:30:18 +09:00
										 |  |  |     PyObject* obj = NULL; | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     unpack_stack* c = NULL; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     int ret; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-22 22:57:00 +10:00
										 |  |  | #define construct_cb(name) \
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:12:20 +09:00
										 |  |  |     construct && unpack_callback ## name | 
					
						
							| 
									
										
										
										
											2012-09-22 22:57:00 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | #define push_simple_value(func) \
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     if(construct_cb(func)(user, &obj) < 0) { goto _failed; } \ | 
					
						
							|  |  |  |     goto _push | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | #define push_fixed_value(func, arg) \
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     if(construct_cb(func)(user, arg, &obj) < 0) { goto _failed; } \ | 
					
						
							|  |  |  |     goto _push | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | #define push_variable_value(func, base, pos, len) \
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     if(construct_cb(func)(user, \ | 
					
						
							|  |  |  |         (const char*)base, (const char*)pos, len, &obj) < 0) { goto _failed; } \ | 
					
						
							|  |  |  |     goto _push | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define again_fixed_trail(_cs, trail_len) \
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     trail = trail_len; \ | 
					
						
							|  |  |  |     cs = _cs; \ | 
					
						
							|  |  |  |     goto _fixed_trail_again | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | #define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     trail = trail_len; \ | 
					
						
							|  |  |  |     if(trail == 0) { goto ifzero; } \ | 
					
						
							|  |  |  |     cs = _cs; \ | 
					
						
							|  |  |  |     goto _fixed_trail_again | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define start_container(func, count_, ct_) \
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */ \ | 
					
						
							|  |  |  |     if(construct_cb(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \ | 
					
						
							|  |  |  |     if((count_) == 0) { obj = stack[top].obj; \ | 
					
						
							|  |  |  |         if (construct_cb(func##_end)(user, &obj) < 0) { goto _failed; } \ | 
					
						
							|  |  |  |         goto _push; } \ | 
					
						
							|  |  |  |     stack[top].ct = ct_; \ | 
					
						
							|  |  |  |     stack[top].size  = count_; \ | 
					
						
							|  |  |  |     stack[top].count = 0; \ | 
					
						
							|  |  |  |     ++top; \ | 
					
						
							|  |  |  |     /*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \ | 
					
						
							|  |  |  |     /*printf("stack push %d\n", top);*/ \ | 
					
						
							|  |  |  |     /* FIXME \
 | 
					
						
							|  |  |  |     if(top >= stack_size) { \ | 
					
						
							|  |  |  |         if(stack_size == MSGPACK_EMBED_STACK_SIZE) { \ | 
					
						
							|  |  |  |             size_t csize = sizeof(unpack_stack) * MSGPACK_EMBED_STACK_SIZE; \ | 
					
						
							|  |  |  |             size_t nsize = csize * 2; \ | 
					
						
							|  |  |  |             unpack_stack* tmp = (unpack_stack*)malloc(nsize); \ | 
					
						
							|  |  |  |             if(tmp == NULL) { goto _failed; } \ | 
					
						
							|  |  |  |             memcpy(tmp, ctx->stack, csize); \ | 
					
						
							|  |  |  |             ctx->stack = stack = tmp; \ | 
					
						
							|  |  |  |             ctx->stack_size = stack_size = MSGPACK_EMBED_STACK_SIZE * 2; \ | 
					
						
							|  |  |  |         } else { \ | 
					
						
							|  |  |  |             size_t nsize = sizeof(unpack_stack) * ctx->stack_size * 2; \ | 
					
						
							|  |  |  |             unpack_stack* tmp = (unpack_stack*)realloc(ctx->stack, nsize); \ | 
					
						
							|  |  |  |             if(tmp == NULL) { goto _failed; } \ | 
					
						
							|  |  |  |             ctx->stack = stack = tmp; \ | 
					
						
							|  |  |  |             ctx->stack_size = stack_size = stack_size * 2; \ | 
					
						
							|  |  |  |         } \ | 
					
						
							|  |  |  |     } \ | 
					
						
							|  |  |  |     */ \ | 
					
						
							|  |  |  |     goto _header_again | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 08:35:08 +09:00
										 |  |  | #define NEXT_CS(p)  ((unsigned int)*p & 0x1f)
 | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-17 10:43:22 +09:00
										 |  |  | #ifdef USE_CASE_RANGE
 | 
					
						
							|  |  |  | #define SWITCH_RANGE_BEGIN     switch(*p) {
 | 
					
						
							|  |  |  | #define SWITCH_RANGE(FROM, TO) case FROM ... TO:
 | 
					
						
							|  |  |  | #define SWITCH_RANGE_DEFAULT   default:
 | 
					
						
							|  |  |  | #define SWITCH_RANGE_END       }
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define SWITCH_RANGE_BEGIN     { if(0) {
 | 
					
						
							|  |  |  | #define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) {
 | 
					
						
							|  |  |  | #define SWITCH_RANGE_DEFAULT   } else {
 | 
					
						
							|  |  |  | #define SWITCH_RANGE_END       } }
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     if(p == pe) { goto _out; } | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         switch(cs) { | 
					
						
							|  |  |  |         case CS_HEADER: | 
					
						
							|  |  |  |             SWITCH_RANGE_BEGIN | 
					
						
							|  |  |  |             SWITCH_RANGE(0x00, 0x7f)  // Positive Fixnum
 | 
					
						
							|  |  |  |                 push_fixed_value(_uint8, *(uint8_t*)p); | 
					
						
							|  |  |  |             SWITCH_RANGE(0xe0, 0xff)  // Negative Fixnum
 | 
					
						
							|  |  |  |                 push_fixed_value(_int8, *(int8_t*)p); | 
					
						
							|  |  |  |             SWITCH_RANGE(0xc0, 0xdf)  // Variable
 | 
					
						
							|  |  |  |                 switch(*p) { | 
					
						
							|  |  |  |                 case 0xc0:  // nil
 | 
					
						
							|  |  |  |                     push_simple_value(_nil); | 
					
						
							| 
									
										
										
										
											2013-10-20 22:59:27 +09:00
										 |  |  |                 //case 0xc1:  // never used
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |                 case 0xc2:  // false
 | 
					
						
							|  |  |  |                     push_simple_value(_false); | 
					
						
							|  |  |  |                 case 0xc3:  // true
 | 
					
						
							|  |  |  |                     push_simple_value(_true); | 
					
						
							| 
									
										
										
										
											2013-10-20 22:59:27 +09:00
										 |  |  |                 case 0xc4:  // bin 8
 | 
					
						
							|  |  |  |                     again_fixed_trail(NEXT_CS(p), 1); | 
					
						
							|  |  |  |                 case 0xc5:  // bin 16
 | 
					
						
							|  |  |  |                     again_fixed_trail(NEXT_CS(p), 2); | 
					
						
							|  |  |  |                 case 0xc6:  // bin 32
 | 
					
						
							|  |  |  |                     again_fixed_trail(NEXT_CS(p), 4); | 
					
						
							| 
									
										
										
										
											2013-10-19 18:04:30 +02:00
										 |  |  |                 case 0xc7:  // ext 8
 | 
					
						
							|  |  |  |                     again_fixed_trail(NEXT_CS(p), 1); | 
					
						
							|  |  |  |                 case 0xc8:  // ext 16
 | 
					
						
							|  |  |  |                     again_fixed_trail(NEXT_CS(p), 2); | 
					
						
							|  |  |  |                 case 0xc9:  // ext 32
 | 
					
						
							|  |  |  |                     again_fixed_trail(NEXT_CS(p), 4); | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |                 case 0xca:  // float
 | 
					
						
							|  |  |  |                 case 0xcb:  // double
 | 
					
						
							|  |  |  |                 case 0xcc:  // unsigned int  8
 | 
					
						
							|  |  |  |                 case 0xcd:  // unsigned int 16
 | 
					
						
							|  |  |  |                 case 0xce:  // unsigned int 32
 | 
					
						
							|  |  |  |                 case 0xcf:  // unsigned int 64
 | 
					
						
							|  |  |  |                 case 0xd0:  // signed int  8
 | 
					
						
							|  |  |  |                 case 0xd1:  // signed int 16
 | 
					
						
							|  |  |  |                 case 0xd2:  // signed int 32
 | 
					
						
							|  |  |  |                 case 0xd3:  // signed int 64
 | 
					
						
							|  |  |  |                     again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03)); | 
					
						
							| 
									
										
										
										
											2013-10-19 17:27:16 +02:00
										 |  |  |                 case 0xd4:  // fixext 1
 | 
					
						
							|  |  |  |                 case 0xd5:  // fixext 2
 | 
					
						
							|  |  |  |                 case 0xd6:  // fixext 4
 | 
					
						
							|  |  |  |                 case 0xd7:  // fixext 8
 | 
					
						
							|  |  |  |                     again_fixed_trail_if_zero(ACS_EXT_VALUE,  | 
					
						
							|  |  |  |                                               (1 << (((unsigned int)*p) & 0x03))+1, | 
					
						
							|  |  |  |                                               _ext_zero); | 
					
						
							|  |  |  |                 case 0xd8:  // fixext 16
 | 
					
						
							|  |  |  |                     again_fixed_trail_if_zero(ACS_EXT_VALUE, 16+1, _ext_zero); | 
					
						
							| 
									
										
										
										
											2013-10-20 22:59:27 +09:00
										 |  |  |                 case 0xd9:  // str 8
 | 
					
						
							|  |  |  |                     again_fixed_trail(NEXT_CS(p), 1); | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |                 case 0xda:  // raw 16
 | 
					
						
							|  |  |  |                 case 0xdb:  // raw 32
 | 
					
						
							|  |  |  |                 case 0xdc:  // array 16
 | 
					
						
							|  |  |  |                 case 0xdd:  // array 32
 | 
					
						
							|  |  |  |                 case 0xde:  // map 16
 | 
					
						
							|  |  |  |                 case 0xdf:  // map 32
 | 
					
						
							|  |  |  |                     again_fixed_trail(NEXT_CS(p), 2 << (((unsigned int)*p) & 0x01)); | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     goto _failed; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             SWITCH_RANGE(0xa0, 0xbf)  // FixRaw
 | 
					
						
							|  |  |  |                 again_fixed_trail_if_zero(ACS_RAW_VALUE, ((unsigned int)*p & 0x1f), _raw_zero); | 
					
						
							|  |  |  |             SWITCH_RANGE(0x90, 0x9f)  // FixArray
 | 
					
						
							|  |  |  |                 start_container(_array, ((unsigned int)*p) & 0x0f, CT_ARRAY_ITEM); | 
					
						
							|  |  |  |             SWITCH_RANGE(0x80, 0x8f)  // FixMap
 | 
					
						
							|  |  |  |                 start_container(_map, ((unsigned int)*p) & 0x0f, CT_MAP_KEY); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             SWITCH_RANGE_DEFAULT | 
					
						
							|  |  |  |                 goto _failed; | 
					
						
							|  |  |  |             SWITCH_RANGE_END | 
					
						
							|  |  |  |             // end CS_HEADER
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         _fixed_trail_again: | 
					
						
							|  |  |  |             ++p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             if((size_t)(pe - p) < trail) { goto _out; } | 
					
						
							|  |  |  |             n = p;  p += trail - 1; | 
					
						
							|  |  |  |             switch(cs) { | 
					
						
							| 
									
										
										
										
											2013-10-19 18:04:30 +02:00
										 |  |  |             case CS_EXT_8: | 
					
						
							|  |  |  |                 again_fixed_trail_if_zero(ACS_EXT_VALUE, *(uint8_t*)n+1, _ext_zero); | 
					
						
							|  |  |  |             case CS_EXT_16: | 
					
						
							|  |  |  |                 again_fixed_trail_if_zero(ACS_EXT_VALUE, | 
					
						
							|  |  |  |                                           _msgpack_load16(uint16_t,n)+1, | 
					
						
							|  |  |  |                                           _ext_zero); | 
					
						
							|  |  |  |             case CS_EXT_32: | 
					
						
							|  |  |  |                 again_fixed_trail_if_zero(ACS_EXT_VALUE, | 
					
						
							|  |  |  |                                           _msgpack_load32(uint32_t,n)+1, | 
					
						
							|  |  |  |                                           _ext_zero); | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |             case CS_FLOAT: { | 
					
						
							|  |  |  |                     union { uint32_t i; float f; } mem; | 
					
						
							|  |  |  |                     mem.i = _msgpack_load32(uint32_t,n); | 
					
						
							|  |  |  |                     push_fixed_value(_float, mem.f); } | 
					
						
							|  |  |  |             case CS_DOUBLE: { | 
					
						
							|  |  |  |                     union { uint64_t i; double f; } mem; | 
					
						
							|  |  |  |                     mem.i = _msgpack_load64(uint64_t,n); | 
					
						
							| 
									
										
										
										
											2012-06-26 13:21:10 +09:00
										 |  |  | #if defined(__arm__) && !(__ARM_EABI__) // arm-oabi
 | 
					
						
							| 
									
										
										
										
											2013-02-23 18:01:43 +09:00
										 |  |  |                     // https://github.com/msgpack/msgpack-perl/pull/1
 | 
					
						
							|  |  |  |                     mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL); | 
					
						
							| 
									
										
										
										
											2012-06-26 13:21:10 +09:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |                     push_fixed_value(_double, mem.f); } | 
					
						
							|  |  |  |             case CS_UINT_8: | 
					
						
							|  |  |  |                 push_fixed_value(_uint8, *(uint8_t*)n); | 
					
						
							|  |  |  |             case CS_UINT_16: | 
					
						
							|  |  |  |                 push_fixed_value(_uint16, _msgpack_load16(uint16_t,n)); | 
					
						
							|  |  |  |             case CS_UINT_32: | 
					
						
							|  |  |  |                 push_fixed_value(_uint32, _msgpack_load32(uint32_t,n)); | 
					
						
							|  |  |  |             case CS_UINT_64: | 
					
						
							|  |  |  |                 push_fixed_value(_uint64, _msgpack_load64(uint64_t,n)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case CS_INT_8: | 
					
						
							|  |  |  |                 push_fixed_value(_int8, *(int8_t*)n); | 
					
						
							|  |  |  |             case CS_INT_16: | 
					
						
							|  |  |  |                 push_fixed_value(_int16, _msgpack_load16(int16_t,n)); | 
					
						
							|  |  |  |             case CS_INT_32: | 
					
						
							|  |  |  |                 push_fixed_value(_int32, _msgpack_load32(int32_t,n)); | 
					
						
							|  |  |  |             case CS_INT_64: | 
					
						
							|  |  |  |                 push_fixed_value(_int64, _msgpack_load64(int64_t,n)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 08:35:08 +09:00
										 |  |  |             case CS_BIN_8: | 
					
						
							|  |  |  |                 again_fixed_trail_if_zero(ACS_BIN_VALUE, *(uint8_t*)n, _bin_zero); | 
					
						
							|  |  |  |             case CS_BIN_16: | 
					
						
							|  |  |  |                 again_fixed_trail_if_zero(ACS_BIN_VALUE, _msgpack_load16(uint16_t,n), _bin_zero); | 
					
						
							|  |  |  |             case CS_BIN_32: | 
					
						
							|  |  |  |                 again_fixed_trail_if_zero(ACS_BIN_VALUE, _msgpack_load32(uint32_t,n), _bin_zero); | 
					
						
							|  |  |  |             case ACS_BIN_VALUE: | 
					
						
							|  |  |  |             _bin_zero: | 
					
						
							|  |  |  |                 push_variable_value(_bin, data, n, trail); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case CS_RAW_8: | 
					
						
							|  |  |  |                 again_fixed_trail_if_zero(ACS_RAW_VALUE, *(uint8_t*)n, _raw_zero); | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |             case CS_RAW_16: | 
					
						
							|  |  |  |                 again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load16(uint16_t,n), _raw_zero); | 
					
						
							|  |  |  |             case CS_RAW_32: | 
					
						
							|  |  |  |                 again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load32(uint32_t,n), _raw_zero); | 
					
						
							|  |  |  |             case ACS_RAW_VALUE: | 
					
						
							|  |  |  |             _raw_zero: | 
					
						
							|  |  |  |                 push_variable_value(_raw, data, n, trail); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-19 17:27:16 +02:00
										 |  |  |             case ACS_EXT_VALUE: | 
					
						
							|  |  |  |             _ext_zero: | 
					
						
							|  |  |  |                 push_variable_value(_ext, data, n, trail); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |             case CS_ARRAY_16: | 
					
						
							|  |  |  |                 start_container(_array, _msgpack_load16(uint16_t,n), CT_ARRAY_ITEM); | 
					
						
							|  |  |  |             case CS_ARRAY_32: | 
					
						
							|  |  |  |                 /* FIXME security guard */ | 
					
						
							|  |  |  |                 start_container(_array, _msgpack_load32(uint32_t,n), CT_ARRAY_ITEM); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             case CS_MAP_16: | 
					
						
							|  |  |  |                 start_container(_map, _msgpack_load16(uint16_t,n), CT_MAP_KEY); | 
					
						
							|  |  |  |             case CS_MAP_32: | 
					
						
							|  |  |  |                 /* FIXME security guard */ | 
					
						
							|  |  |  |                 start_container(_map, _msgpack_load32(uint32_t,n), CT_MAP_KEY); | 
					
						
							| 
									
										
										
										
											2013-10-20 23:06:02 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |             default: | 
					
						
							|  |  |  |                 goto _failed; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | _push: | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     if(top == 0) { goto _finish; } | 
					
						
							|  |  |  |     c = &stack[top-1]; | 
					
						
							|  |  |  |     switch(c->ct) { | 
					
						
							|  |  |  |     case CT_ARRAY_ITEM: | 
					
						
							|  |  |  |         if(construct_cb(_array_item)(user, c->count, &c->obj, obj) < 0) { goto _failed; } | 
					
						
							|  |  |  |         if(++c->count == c->size) { | 
					
						
							|  |  |  |             obj = c->obj; | 
					
						
							|  |  |  |             if (construct_cb(_array_end)(user, &obj) < 0) { goto _failed; } | 
					
						
							|  |  |  |             --top; | 
					
						
							|  |  |  |             /*printf("stack pop %d\n", top);*/ | 
					
						
							|  |  |  |             goto _push; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         goto _header_again; | 
					
						
							|  |  |  |     case CT_MAP_KEY: | 
					
						
							|  |  |  |         c->map_key = obj; | 
					
						
							|  |  |  |         c->ct = CT_MAP_VALUE; | 
					
						
							|  |  |  |         goto _header_again; | 
					
						
							|  |  |  |     case CT_MAP_VALUE: | 
					
						
							|  |  |  |         if(construct_cb(_map_item)(user, c->count, &c->obj, c->map_key, obj) < 0) { goto _failed; } | 
					
						
							|  |  |  |         if(++c->count == c->size) { | 
					
						
							|  |  |  |             obj = c->obj; | 
					
						
							|  |  |  |             if (construct_cb(_map_end)(user, &obj) < 0) { goto _failed; } | 
					
						
							|  |  |  |             --top; | 
					
						
							|  |  |  |             /*printf("stack pop %d\n", top);*/ | 
					
						
							|  |  |  |             goto _push; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         c->ct = CT_MAP_KEY; | 
					
						
							|  |  |  |         goto _header_again; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         goto _failed; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | _header_again: | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |         cs = CS_HEADER; | 
					
						
							|  |  |  |         ++p; | 
					
						
							|  |  |  |     } while(p != pe); | 
					
						
							|  |  |  |     goto _out; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _finish: | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     if (!construct) | 
					
						
							|  |  |  |         unpack_callback_nil(user, &obj); | 
					
						
							|  |  |  |     stack[0].obj = obj; | 
					
						
							|  |  |  |     ++p; | 
					
						
							|  |  |  |     ret = 1; | 
					
						
							|  |  |  |     /*printf("-- finish --\n"); */ | 
					
						
							|  |  |  |     goto _end; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | _failed: | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     /*printf("** FAILED **\n"); */ | 
					
						
							|  |  |  |     ret = -1; | 
					
						
							|  |  |  |     goto _end; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | _out: | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     ret = 0; | 
					
						
							|  |  |  |     goto _end; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | _end: | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     ctx->cs = cs; | 
					
						
							|  |  |  |     ctx->trail = trail; | 
					
						
							|  |  |  |     ctx->top = top; | 
					
						
							|  |  |  |     *off = p - (const unsigned char*)data; | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2012-09-22 22:57:00 +10:00
										 |  |  | #undef construct_cb
 | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-25 01:18:33 +10:00
										 |  |  | #undef SWITCH_RANGE_BEGIN
 | 
					
						
							|  |  |  | #undef SWITCH_RANGE
 | 
					
						
							|  |  |  | #undef SWITCH_RANGE_DEFAULT
 | 
					
						
							|  |  |  | #undef SWITCH_RANGE_END
 | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | #undef push_simple_value
 | 
					
						
							|  |  |  | #undef push_fixed_value
 | 
					
						
							|  |  |  | #undef push_variable_value
 | 
					
						
							|  |  |  | #undef again_fixed_trail
 | 
					
						
							|  |  |  | #undef again_fixed_trail_if_zero
 | 
					
						
							|  |  |  | #undef start_container
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-25 01:18:33 +10:00
										 |  |  | template <unsigned int fixed_offset, unsigned int var_offset> | 
					
						
							| 
									
										
										
										
											2015-11-07 16:30:18 +09:00
										 |  |  | static inline int unpack_container_header(unpack_context* ctx, const char* data, Py_ssize_t len, Py_ssize_t* off) | 
					
						
							| 
									
										
										
										
											2012-09-25 01:18:33 +10:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     assert(len >= *off); | 
					
						
							|  |  |  |     uint32_t size; | 
					
						
							|  |  |  |     const unsigned char *const p = (unsigned char*)data + *off; | 
					
						
							| 
									
										
										
										
											2012-09-25 01:18:33 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define inc_offset(inc) \
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     if (len - *off < inc) \ | 
					
						
							|  |  |  |         return 0; \ | 
					
						
							|  |  |  |     *off += inc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (*p) { | 
					
						
							|  |  |  |     case var_offset: | 
					
						
							|  |  |  |         inc_offset(3); | 
					
						
							|  |  |  |         size = _msgpack_load16(uint16_t, p + 1); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case var_offset + 1: | 
					
						
							|  |  |  |         inc_offset(5); | 
					
						
							|  |  |  |         size = _msgpack_load32(uint32_t, p + 1); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-09-25 01:18:33 +10:00
										 |  |  | #ifdef USE_CASE_RANGE
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     case fixed_offset + 0x0 ... fixed_offset + 0xf: | 
					
						
							| 
									
										
										
										
											2012-09-25 01:18:33 +10:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     case fixed_offset + 0x0: | 
					
						
							|  |  |  |     case fixed_offset + 0x1: | 
					
						
							|  |  |  |     case fixed_offset + 0x2: | 
					
						
							|  |  |  |     case fixed_offset + 0x3: | 
					
						
							|  |  |  |     case fixed_offset + 0x4: | 
					
						
							|  |  |  |     case fixed_offset + 0x5: | 
					
						
							|  |  |  |     case fixed_offset + 0x6: | 
					
						
							|  |  |  |     case fixed_offset + 0x7: | 
					
						
							|  |  |  |     case fixed_offset + 0x8: | 
					
						
							|  |  |  |     case fixed_offset + 0x9: | 
					
						
							|  |  |  |     case fixed_offset + 0xa: | 
					
						
							|  |  |  |     case fixed_offset + 0xb: | 
					
						
							|  |  |  |     case fixed_offset + 0xc: | 
					
						
							|  |  |  |     case fixed_offset + 0xd: | 
					
						
							|  |  |  |     case fixed_offset + 0xe: | 
					
						
							|  |  |  |     case fixed_offset + 0xf: | 
					
						
							| 
									
										
										
										
											2012-09-25 01:18:33 +10:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |         ++*off; | 
					
						
							|  |  |  |         size = ((unsigned int)*p) & 0x0f; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "Unexpected type header on stream"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2013-02-23 18:11:46 +09:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  |     unpack_callback_uint32(&ctx->user, size, &ctx->stack[0].obj); | 
					
						
							|  |  |  |     return 1; | 
					
						
							| 
									
										
										
										
											2012-09-25 01:18:33 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef SWITCH_RANGE_BEGIN
 | 
					
						
							|  |  |  | #undef SWITCH_RANGE
 | 
					
						
							|  |  |  | #undef SWITCH_RANGE_DEFAULT
 | 
					
						
							|  |  |  | #undef SWITCH_RANGE_END
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:12:20 +09:00
										 |  |  | static const execute_fn unpack_construct = &unpack_execute<true>; | 
					
						
							|  |  |  | static const execute_fn unpack_skip = &unpack_execute<false>; | 
					
						
							|  |  |  | static const execute_fn read_array_header = &unpack_container_header<0x90, 0xdc>; | 
					
						
							|  |  |  | static const execute_fn read_map_header = &unpack_container_header<0x80, 0xde>; | 
					
						
							| 
									
										
										
										
											2012-09-25 00:30:15 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-24 01:38:48 +09:00
										 |  |  | #undef NEXT_CS
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-27 21:24:25 +09:00
										 |  |  | /* vim: set ts=4 sw=4 sts=4 expandtab  */ |