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