msgpack 0.4.7 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.gitignore +17 -0
  2. data/ChangeLog +47 -0
  3. data/README.rdoc +102 -0
  4. data/Rakefile +88 -0
  5. data/doclib/msgpack.rb +55 -0
  6. data/doclib/msgpack/buffer.rb +193 -0
  7. data/doclib/msgpack/core_ext.rb +101 -0
  8. data/doclib/msgpack/error.rb +14 -0
  9. data/doclib/msgpack/packer.rb +131 -0
  10. data/doclib/msgpack/unpacker.rb +130 -0
  11. data/ext/msgpack/buffer.c +679 -0
  12. data/ext/msgpack/buffer.h +442 -0
  13. data/ext/msgpack/buffer_class.c +507 -0
  14. data/ext/msgpack/buffer_class.h +32 -0
  15. data/ext/msgpack/compat.h +112 -0
  16. data/ext/msgpack/core_ext.c +129 -0
  17. data/ext/{pack.h → msgpack/core_ext.h} +7 -7
  18. data/ext/msgpack/extconf.rb +17 -0
  19. data/ext/msgpack/packer.c +137 -0
  20. data/ext/msgpack/packer.h +319 -0
  21. data/ext/msgpack/packer_class.c +285 -0
  22. data/ext/{unpack.h → msgpack/packer_class.h} +11 -7
  23. data/ext/msgpack/rbinit.c +33 -0
  24. data/ext/msgpack/rmem.c +110 -0
  25. data/ext/msgpack/rmem.h +100 -0
  26. data/ext/msgpack/sysdep.h +115 -0
  27. data/ext/msgpack/sysdep_endian.h +50 -0
  28. data/ext/msgpack/sysdep_types.h +46 -0
  29. data/ext/msgpack/unpacker.c +669 -0
  30. data/ext/msgpack/unpacker.h +112 -0
  31. data/ext/msgpack/unpacker_class.c +376 -0
  32. data/{msgpack/pack_define.h → ext/msgpack/unpacker_class.h} +12 -8
  33. data/lib/msgpack.rb +10 -0
  34. data/{ext → lib/msgpack}/version.rb +1 -1
  35. data/msgpack.gemspec +25 -0
  36. data/spec/buffer_io_spec.rb +237 -0
  37. data/spec/buffer_spec.rb +572 -0
  38. data/{test → spec}/cases.json +0 -0
  39. data/{test/cases.mpac → spec/cases.msg} +0 -0
  40. data/{test/cases_compact.mpac → spec/cases_compact.msg} +0 -0
  41. data/spec/cases_spec.rb +39 -0
  42. data/spec/format_spec.rb +225 -0
  43. data/spec/packer_spec.rb +127 -0
  44. data/spec/random_compat.rb +24 -0
  45. data/spec/spec_helper.rb +21 -0
  46. data/spec/unpacker_spec.rb +128 -0
  47. metadata +171 -34
  48. data/ext/compat.h +0 -99
  49. data/ext/extconf.rb +0 -7
  50. data/ext/pack.c +0 -314
  51. data/ext/rbinit.c +0 -66
  52. data/ext/unpack.c +0 -1001
  53. data/msgpack/pack_template.h +0 -771
  54. data/msgpack/sysdep.h +0 -195
  55. data/msgpack/unpack_define.h +0 -93
  56. data/msgpack/unpack_template.h +0 -413
  57. data/test/test_cases.rb +0 -46
  58. data/test/test_encoding.rb +0 -68
  59. data/test/test_helper.rb +0 -10
  60. data/test/test_pack_unpack.rb +0 -308
@@ -0,0 +1,669 @@
1
+ /*
2
+ * MessagePack for Ruby
3
+ *
4
+ * Copyright (C) 2008-2012 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
+ #include "unpacker.h"
20
+
21
+ #ifdef COMPAT_HAVE_ENCODING /* see compat.h*/
22
+ static int s_enc_utf8;
23
+ #endif
24
+
25
+ void msgpack_unpacker_static_init()
26
+ {
27
+ #ifdef COMPAT_HAVE_ENCODING
28
+ s_enc_utf8 = rb_utf8_encindex();
29
+ #endif
30
+ }
31
+
32
+ void msgpack_unpacker_static_destroy()
33
+ { }
34
+
35
+ #define HEAD_BYTE_REQUIRED 0xc6
36
+
37
+ void msgpack_unpacker_init(msgpack_unpacker_t* uk)
38
+ {
39
+ memset(uk, 0, sizeof(msgpack_unpacker_t));
40
+
41
+ msgpack_buffer_init(UNPACKER_BUFFER_(uk));
42
+
43
+ uk->head_byte = HEAD_BYTE_REQUIRED;
44
+
45
+ uk->last_object = Qnil;
46
+ uk->reading_raw = Qnil;
47
+
48
+ uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));
49
+ uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
50
+ }
51
+
52
+ void msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
53
+ {
54
+ free(uk->stack);
55
+ msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
56
+ }
57
+
58
+ void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
59
+ {
60
+ rb_gc_mark(uk->last_object);
61
+ rb_gc_mark(uk->reading_raw);
62
+
63
+ msgpack_unpacker_stack_t* s = uk->stack;
64
+ msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
65
+ for(; s < send; s++) {
66
+ rb_gc_mark(s->object);
67
+ rb_gc_mark(s->key);
68
+ }
69
+
70
+ /* See MessagePack_Buffer_wrap */
71
+ /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
72
+ rb_gc_mark(uk->buffer_ref);
73
+ }
74
+
75
+ void msgpack_unpacker_reset(msgpack_unpacker_t* uk)
76
+ {
77
+ msgpack_buffer_clear(UNPACKER_BUFFER_(uk));
78
+
79
+ uk->head_byte = HEAD_BYTE_REQUIRED;
80
+
81
+ memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack_depth);
82
+ uk->stack_depth = 0;
83
+
84
+ uk->last_object = Qnil;
85
+ uk->reading_raw = Qnil;
86
+ uk->reading_raw_remaining = 0;
87
+ }
88
+
89
+
90
+ /* head byte functions */
91
+ static int read_head_byte(msgpack_unpacker_t* uk)
92
+ {
93
+ int r = msgpack_buffer_read_1(UNPACKER_BUFFER_(uk));
94
+ if(r == -1) {
95
+ return PRIMITIVE_EOF;
96
+ }
97
+ return uk->head_byte = r;
98
+ }
99
+
100
+ static inline int get_head_byte(msgpack_unpacker_t* uk)
101
+ {
102
+ int b = uk->head_byte;
103
+ if(b == HEAD_BYTE_REQUIRED) {
104
+ b = read_head_byte(uk);
105
+ }
106
+ return b;
107
+ }
108
+
109
+ static inline void reset_head_byte(msgpack_unpacker_t* uk)
110
+ {
111
+ uk->head_byte = HEAD_BYTE_REQUIRED;
112
+ }
113
+
114
+ static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
115
+ {
116
+ uk->last_object = object;
117
+ reset_head_byte(uk);
118
+ return PRIMITIVE_OBJECT_COMPLETE;
119
+ }
120
+
121
+ static inline int object_complete_string(msgpack_unpacker_t* uk, VALUE str)
122
+ {
123
+ // TODO ruby 2.0 has String#b method
124
+ #ifdef COMPAT_HAVE_ENCODING
125
+ //str_modifiable(str);
126
+ ENCODING_SET(str, s_enc_utf8);
127
+ #endif
128
+ return object_complete(uk, str);
129
+ }
130
+
131
+ /* stack funcs */
132
+ static inline msgpack_unpacker_stack_t* _msgpack_unpacker_stack_top(msgpack_unpacker_t* uk)
133
+ {
134
+ return &uk->stack[uk->stack_depth-1];
135
+ }
136
+
137
+ static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
138
+ {
139
+ reset_head_byte(uk);
140
+
141
+ if(uk->stack_capacity - uk->stack_depth <= 0) {
142
+ return PRIMITIVE_STACK_TOO_DEEP;
143
+ }
144
+
145
+ msgpack_unpacker_stack_t* next = &uk->stack[uk->stack_depth];
146
+ next->count = count;
147
+ next->type = type;
148
+ next->object = object;
149
+ next->key = Qnil;
150
+
151
+ uk->stack_depth++;
152
+ return PRIMITIVE_CONTAINER_START;
153
+ }
154
+
155
+ static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
156
+ {
157
+ return --uk->stack_depth;
158
+ }
159
+
160
+ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
161
+ {
162
+ return uk->stack_depth == 0;
163
+ }
164
+
165
+ #ifdef USE_CASE_RANGE
166
+
167
+ #define SWITCH_RANGE_BEGIN(BYTE) { switch(BYTE) {
168
+ #define SWITCH_RANGE(BYTE, FROM, TO) } case FROM ... TO: {
169
+ #define SWITCH_RANGE_DEFAULT } default: {
170
+ #define SWITCH_RANGE_END } }
171
+
172
+ #else
173
+
174
+ #define SWITCH_RANGE_BEGIN(BYTE) { if(0) {
175
+ #define SWITCH_RANGE(BYTE, FROM, TO) } else if(FROM <= (BYTE) && (BYTE) <= TO) {
176
+ #define SWITCH_RANGE_DEFAULT } else {
177
+ #define SWITCH_RANGE_END } }
178
+
179
+ #endif
180
+
181
+
182
+ #define READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, n) \
183
+ union msgpack_buffer_cast_block_t* cb = msgpack_buffer_read_cast_block(UNPACKER_BUFFER_(uk), n); \
184
+ if(cb == NULL) { \
185
+ return PRIMITIVE_EOF; \
186
+ }
187
+
188
+ static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
189
+ {
190
+ if(uk->stack_depth > 0) {
191
+ msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
192
+ if(top->type == STACK_TYPE_MAP_KEY) {
193
+ return true;
194
+ }
195
+ }
196
+ return false;
197
+ }
198
+
199
+ static int read_raw_body_cont(msgpack_unpacker_t* uk)
200
+ {
201
+ size_t length = uk->reading_raw_remaining;
202
+
203
+ if(uk->reading_raw == Qnil) {
204
+ uk->reading_raw = rb_str_buf_new(length);
205
+ }
206
+
207
+ do {
208
+ size_t n = msgpack_buffer_read_to_string(UNPACKER_BUFFER_(uk), uk->reading_raw, length);
209
+ if(n == 0) {
210
+ return PRIMITIVE_EOF;
211
+ }
212
+ /* update reading_raw_remaining everytime because
213
+ * msgpack_buffer_read_to_string raises IOError */
214
+ uk->reading_raw_remaining = length = length - n;
215
+ } while(length > 0);
216
+
217
+ object_complete_string(uk, uk->reading_raw);
218
+ uk->reading_raw = Qnil;
219
+ return PRIMITIVE_OBJECT_COMPLETE;
220
+ }
221
+
222
+ static inline int read_raw_body_begin(msgpack_unpacker_t* uk)
223
+ {
224
+ /* assuming uk->reading_raw == Qnil */
225
+
226
+ /* try optimized read */
227
+ size_t length = uk->reading_raw_remaining;
228
+ if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
229
+ /* don't use zerocopy for hash keys but get a frozen string directly
230
+ * because rb_hash_aset freezes keys and it causes copying */
231
+ bool frozen = is_reading_map_key(uk);
232
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, frozen);
233
+ object_complete_string(uk, string);
234
+ uk->reading_raw_remaining = 0;
235
+ return PRIMITIVE_OBJECT_COMPLETE;
236
+ }
237
+
238
+ return read_raw_body_cont(uk);
239
+ }
240
+
241
+ static int read_primitive(msgpack_unpacker_t* uk)
242
+ {
243
+ if(uk->reading_raw_remaining > 0) {
244
+ return read_raw_body_cont(uk);
245
+ }
246
+
247
+ int b = get_head_byte(uk);
248
+ if(b < 0) {
249
+ return b;
250
+ }
251
+
252
+ SWITCH_RANGE_BEGIN(b)
253
+ SWITCH_RANGE(b, 0x00, 0x7f) // Positive Fixnum
254
+ return object_complete(uk, INT2FIX(b));
255
+
256
+ SWITCH_RANGE(b, 0xe0, 0xff) // Negative Fixnum
257
+ return object_complete(uk, INT2FIX((int8_t)b));
258
+
259
+ SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw
260
+ int count = b & 0x1f;
261
+ if(count == 0) {
262
+ return object_complete_string(uk, rb_str_buf_new(0));
263
+ }
264
+ /* read_raw_body_begin sets uk->reading_raw */
265
+ uk->reading_raw_remaining = count;
266
+ return read_raw_body_begin(uk);
267
+
268
+ SWITCH_RANGE(b, 0x90, 0x9f) // FixArray
269
+ int count = b & 0x0f;
270
+ if(count == 0) {
271
+ return object_complete(uk, rb_ary_new());
272
+ }
273
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
274
+
275
+ SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
276
+ int count = b & 0x0f;
277
+ if(count == 0) {
278
+ return object_complete(uk, rb_hash_new());
279
+ }
280
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
281
+
282
+ SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
283
+ switch(b) {
284
+ case 0xc0: // nil
285
+ return object_complete(uk, Qnil);
286
+
287
+ //case 0xc1: // string
288
+
289
+ case 0xc2: // false
290
+ return object_complete(uk, Qfalse);
291
+
292
+ case 0xc3: // true
293
+ return object_complete(uk, Qtrue);
294
+
295
+ //case 0xc4:
296
+ //case 0xc5:
297
+ //case 0xc6:
298
+ //case 0xc7:
299
+ //case 0xc8:
300
+ //case 0xc9:
301
+
302
+ case 0xca: // float
303
+ {
304
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
305
+ cb->u32 = _msgpack_be_float(cb->u32);
306
+ return object_complete(uk, rb_float_new(cb->f));
307
+ }
308
+
309
+ case 0xcb: // double
310
+ {
311
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
312
+ cb->u64 = _msgpack_be_double(cb->u64);
313
+ return object_complete(uk, rb_float_new(cb->d));
314
+ }
315
+
316
+ case 0xcc: // unsigned int 8
317
+ {
318
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
319
+ uint8_t u8 = cb->u8;
320
+ return object_complete(uk, INT2FIX((int)u8));
321
+ }
322
+
323
+ case 0xcd: // unsigned int 16
324
+ {
325
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
326
+ uint16_t u16 = _msgpack_be16(cb->u16);
327
+ return object_complete(uk, INT2FIX((int)u16));
328
+ }
329
+
330
+ case 0xce: // unsigned int 32
331
+ {
332
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
333
+ uint32_t u32 = _msgpack_be32(cb->u32);
334
+ return object_complete(uk, ULONG2NUM((unsigned long)u32));
335
+ }
336
+
337
+ case 0xcf: // unsigned int 64
338
+ {
339
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
340
+ uint64_t u64 = _msgpack_be64(cb->u64);
341
+ return object_complete(uk, rb_ull2inum(u64));
342
+ }
343
+
344
+ case 0xd0: // signed int 8
345
+ {
346
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
347
+ int8_t i8 = cb->i8;
348
+ return object_complete(uk, INT2FIX((int)i8));
349
+ }
350
+
351
+ case 0xd1: // signed int 16
352
+ {
353
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
354
+ int16_t i16 = _msgpack_be16(cb->i16);
355
+ return object_complete(uk, INT2FIX((int)i16));
356
+ }
357
+
358
+ case 0xd2: // signed int 32
359
+ {
360
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
361
+ int32_t i32 = _msgpack_be32(cb->i32);
362
+ return object_complete(uk, LONG2FIX((long)i32));
363
+ }
364
+
365
+ case 0xd3: // signed int 64
366
+ {
367
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
368
+ int64_t i64 = _msgpack_be64(cb->i64);
369
+ return object_complete(uk, rb_ll2inum(i64));
370
+ }
371
+
372
+ //case 0xd4:
373
+ //case 0xd5:
374
+ //case 0xd6: // big integer 16
375
+ //case 0xd7: // big integer 32
376
+ //case 0xd8: // big float 16
377
+ //case 0xd9: // big float 32
378
+
379
+ case 0xda: // raw 16
380
+ {
381
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
382
+ uint16_t count = _msgpack_be16(cb->u16);
383
+ if(count == 0) {
384
+ return object_complete_string(uk, rb_str_buf_new(0));
385
+ }
386
+ /* read_raw_body_begin sets uk->reading_raw */
387
+ uk->reading_raw_remaining = count;
388
+ return read_raw_body_begin(uk);
389
+ }
390
+
391
+ case 0xdb: // raw 32
392
+ {
393
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
394
+ uint32_t count = _msgpack_be32(cb->u32);
395
+ if(count == 0) {
396
+ return object_complete_string(uk, rb_str_buf_new(0));
397
+ }
398
+ /* read_raw_body_begin sets uk->reading_raw */
399
+ uk->reading_raw_remaining = count;
400
+ return read_raw_body_begin(uk);
401
+ }
402
+
403
+ case 0xdc: // array 16
404
+ {
405
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
406
+ uint16_t count = _msgpack_be16(cb->u16);
407
+ if(count == 0) {
408
+ return object_complete(uk, rb_ary_new());
409
+ }
410
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
411
+ }
412
+
413
+ case 0xdd: // array 32
414
+ {
415
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
416
+ uint32_t count = _msgpack_be32(cb->u32);
417
+ if(count == 0) {
418
+ return object_complete(uk, rb_ary_new());
419
+ }
420
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
421
+ }
422
+
423
+ case 0xde: // map 16
424
+ {
425
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
426
+ uint16_t count = _msgpack_be16(cb->u16);
427
+ if(count == 0) {
428
+ return object_complete(uk, rb_hash_new());
429
+ }
430
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
431
+ }
432
+
433
+ case 0xdf: // map 32
434
+ {
435
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
436
+ uint32_t count = _msgpack_be32(cb->u32);
437
+ if(count == 0) {
438
+ return object_complete(uk, rb_hash_new());
439
+ }
440
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
441
+ }
442
+
443
+ default:
444
+ return PRIMITIVE_INVALID_BYTE;
445
+ }
446
+
447
+ SWITCH_RANGE_DEFAULT
448
+ return PRIMITIVE_INVALID_BYTE;
449
+
450
+ SWITCH_RANGE_END
451
+ }
452
+
453
+ int msgpack_unpacker_read_array_header(msgpack_unpacker_t* uk, uint32_t* result_size)
454
+ {
455
+ int b = get_head_byte(uk);
456
+ if(b < 0) {
457
+ return b;
458
+ }
459
+
460
+ if(0x90 < b && b < 0x9f) {
461
+ *result_size = b & 0x0f;
462
+
463
+ } else if(b == 0xdc) {
464
+ /* array 16 */
465
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
466
+ *result_size = _msgpack_be16(cb->u16);
467
+
468
+ } else if(b == 0xdd) {
469
+ /* array 32 */
470
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
471
+ *result_size = _msgpack_be32(cb->u32);
472
+
473
+ } else {
474
+ return PRIMITIVE_UNEXPECTED_TYPE;
475
+ }
476
+
477
+ return 0;
478
+ }
479
+
480
+ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_size)
481
+ {
482
+ int b = get_head_byte(uk);
483
+ if(b < 0) {
484
+ return b;
485
+ }
486
+
487
+ if(0x80 < b && b < 0x8f) {
488
+ *result_size = b & 0x0f;
489
+
490
+ } else if(b == 0xde) {
491
+ /* map 16 */
492
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
493
+ *result_size = _msgpack_be16(cb->u16);
494
+
495
+ } else if(b == 0xdf) {
496
+ /* map 32 */
497
+ READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
498
+ *result_size = _msgpack_be32(cb->u32);
499
+
500
+ } else {
501
+ return PRIMITIVE_UNEXPECTED_TYPE;
502
+ }
503
+
504
+ return 0;
505
+ }
506
+
507
+ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
508
+ {
509
+ while(true) {
510
+ int r = read_primitive(uk);
511
+ if(r < 0) {
512
+ return r;
513
+ }
514
+ if(r == PRIMITIVE_CONTAINER_START) {
515
+ continue;
516
+ }
517
+ /* PRIMITIVE_OBJECT_COMPLETE */
518
+
519
+ if(msgpack_unpacker_stack_is_empty(uk)) {
520
+ return PRIMITIVE_OBJECT_COMPLETE;
521
+ }
522
+
523
+ container_completed:
524
+ {
525
+ msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
526
+ switch(top->type) {
527
+ case STACK_TYPE_ARRAY:
528
+ rb_ary_push(top->object, uk->last_object);
529
+ break;
530
+ case STACK_TYPE_MAP_KEY:
531
+ top->key = uk->last_object;
532
+ top->type = STACK_TYPE_MAP_VALUE;
533
+ break;
534
+ case STACK_TYPE_MAP_VALUE:
535
+ rb_hash_aset(top->object, top->key, uk->last_object);
536
+ top->type = STACK_TYPE_MAP_KEY;
537
+ break;
538
+ }
539
+ size_t count = --top->count;
540
+
541
+ if(count == 0) {
542
+ object_complete(uk, top->object);
543
+ if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
544
+ return PRIMITIVE_OBJECT_COMPLETE;
545
+ }
546
+ goto container_completed;
547
+ }
548
+ }
549
+ }
550
+ }
551
+
552
+ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
553
+ {
554
+ while(true) {
555
+ int r = read_primitive(uk);
556
+ if(r < 0) {
557
+ return r;
558
+ }
559
+ if(r == PRIMITIVE_CONTAINER_START) {
560
+ continue;
561
+ }
562
+ /* PRIMITIVE_OBJECT_COMPLETE */
563
+
564
+ if(msgpack_unpacker_stack_is_empty(uk)) {
565
+ return PRIMITIVE_OBJECT_COMPLETE;
566
+ }
567
+
568
+ container_completed:
569
+ {
570
+ msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
571
+
572
+ /* this section optimized out */
573
+ // TODO object_complete still creates objects which should be optimized out
574
+
575
+ size_t count = --top->count;
576
+
577
+ if(count == 0) {
578
+ object_complete(uk, Qnil);
579
+ if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
580
+ return PRIMITIVE_OBJECT_COMPLETE;
581
+ }
582
+ goto container_completed;
583
+ }
584
+ }
585
+ }
586
+ }
587
+
588
+ int msgpack_unpacker_peek_next_object_type(msgpack_unpacker_t* uk)
589
+ {
590
+ int b = get_head_byte(uk);
591
+ if(b < 0) {
592
+ return b;
593
+ }
594
+
595
+ SWITCH_RANGE_BEGIN(b)
596
+ SWITCH_RANGE(b, 0x00, 0x7f) // Positive Fixnum
597
+ return TYPE_INTEGER;
598
+
599
+ SWITCH_RANGE(b, 0xe0, 0xff) // Negative Fixnum
600
+ return TYPE_INTEGER;
601
+
602
+ SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw
603
+ return TYPE_RAW;
604
+
605
+ SWITCH_RANGE(b, 0x90, 0x9f) // FixArray
606
+ return TYPE_ARRAY;
607
+
608
+ SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
609
+ return TYPE_MAP;
610
+
611
+ SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
612
+ switch(b) {
613
+ case 0xc0: // nil
614
+ return TYPE_NIL;
615
+
616
+ case 0xc2: // false
617
+ case 0xc3: // true
618
+ return TYPE_BOOLEAN;
619
+
620
+ case 0xca: // float
621
+ case 0xcb: // double
622
+ return TYPE_FLOAT;
623
+
624
+ case 0xcc: // unsigned int 8
625
+ case 0xcd: // unsigned int 16
626
+ case 0xce: // unsigned int 32
627
+ case 0xcf: // unsigned int 64
628
+ return TYPE_INTEGER;
629
+
630
+ case 0xd0: // signed int 8
631
+ case 0xd1: // signed int 16
632
+ case 0xd2: // signed int 32
633
+ case 0xd3: // signed int 64
634
+ return TYPE_INTEGER;
635
+
636
+ case 0xda: // raw 16
637
+ case 0xdb: // raw 32
638
+ return TYPE_RAW;
639
+
640
+ case 0xdc: // array 16
641
+ case 0xdd: // array 32
642
+ return TYPE_ARRAY;
643
+
644
+ case 0xde: // map 16
645
+ case 0xdf: // map 32
646
+ return TYPE_MAP;
647
+
648
+ default:
649
+ return PRIMITIVE_INVALID_BYTE;
650
+ }
651
+
652
+ SWITCH_RANGE_DEFAULT
653
+ return PRIMITIVE_INVALID_BYTE;
654
+
655
+ SWITCH_RANGE_END
656
+ }
657
+
658
+ int msgpack_unpacker_skip_nil(msgpack_unpacker_t* uk)
659
+ {
660
+ int b = get_head_byte(uk);
661
+ if(b < 0) {
662
+ return b;
663
+ }
664
+ if(b == 0xc0) {
665
+ return 1;
666
+ }
667
+ return 0;
668
+ }
669
+