msgpack 1.5.6 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +50 -0
  3. data/README.md +48 -12
  4. data/ext/java/org/msgpack/jruby/Buffer.java +3 -3
  5. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +11 -20
  6. data/ext/java/org/msgpack/jruby/ExtensionValue.java +1 -1
  7. data/ext/java/org/msgpack/jruby/Factory.java +11 -50
  8. data/ext/java/org/msgpack/jruby/Packer.java +9 -24
  9. data/ext/java/org/msgpack/jruby/Unpacker.java +15 -32
  10. data/ext/msgpack/buffer.c +69 -56
  11. data/ext/msgpack/buffer.h +138 -44
  12. data/ext/msgpack/buffer_class.c +132 -31
  13. data/ext/msgpack/buffer_class.h +1 -0
  14. data/ext/msgpack/extconf.rb +20 -30
  15. data/ext/msgpack/factory_class.c +75 -86
  16. data/ext/msgpack/packer.c +13 -16
  17. data/ext/msgpack/packer.h +24 -21
  18. data/ext/msgpack/packer_class.c +72 -98
  19. data/ext/msgpack/packer_class.h +11 -0
  20. data/ext/msgpack/packer_ext_registry.c +31 -28
  21. data/ext/msgpack/packer_ext_registry.h +10 -14
  22. data/ext/msgpack/rbinit.c +1 -1
  23. data/ext/msgpack/rmem.c +3 -4
  24. data/ext/msgpack/sysdep.h +5 -2
  25. data/ext/msgpack/unpacker.c +201 -113
  26. data/ext/msgpack/unpacker.h +22 -15
  27. data/ext/msgpack/unpacker_class.c +87 -92
  28. data/ext/msgpack/unpacker_class.h +11 -0
  29. data/ext/msgpack/unpacker_ext_registry.c +4 -16
  30. data/ext/msgpack/unpacker_ext_registry.h +3 -7
  31. data/lib/msgpack/buffer.rb +9 -0
  32. data/lib/msgpack/factory.rb +90 -63
  33. data/lib/msgpack/packer.rb +10 -1
  34. data/lib/msgpack/unpacker.rb +14 -1
  35. data/lib/msgpack/version.rb +1 -1
  36. data/lib/msgpack.rb +1 -0
  37. data/msgpack.gemspec +8 -3
  38. metadata +21 -51
  39. data/.github/workflows/ci.yaml +0 -57
  40. data/.gitignore +0 -23
  41. data/.rubocop.yml +0 -36
  42. data/Gemfile +0 -9
  43. data/Rakefile +0 -70
  44. data/appveyor.yml +0 -18
  45. data/bench/bench.rb +0 -78
  46. data/doclib/msgpack/buffer.rb +0 -193
  47. data/doclib/msgpack/core_ext.rb +0 -101
  48. data/doclib/msgpack/error.rb +0 -19
  49. data/doclib/msgpack/extension_value.rb +0 -9
  50. data/doclib/msgpack/factory.rb +0 -145
  51. data/doclib/msgpack/packer.rb +0 -209
  52. data/doclib/msgpack/time.rb +0 -22
  53. data/doclib/msgpack/timestamp.rb +0 -44
  54. data/doclib/msgpack/unpacker.rb +0 -183
  55. data/doclib/msgpack.rb +0 -87
  56. data/msgpack.org.md +0 -46
  57. data/spec/bigint_spec.rb +0 -26
  58. data/spec/cases.json +0 -1
  59. data/spec/cases.msg +0 -0
  60. data/spec/cases_compact.msg +0 -0
  61. data/spec/cases_spec.rb +0 -39
  62. data/spec/cruby/buffer_io_spec.rb +0 -255
  63. data/spec/cruby/buffer_packer.rb +0 -29
  64. data/spec/cruby/buffer_spec.rb +0 -575
  65. data/spec/cruby/buffer_unpacker.rb +0 -19
  66. data/spec/cruby/unpacker_spec.rb +0 -70
  67. data/spec/ext_value_spec.rb +0 -99
  68. data/spec/exttypes.rb +0 -51
  69. data/spec/factory_spec.rb +0 -688
  70. data/spec/format_spec.rb +0 -301
  71. data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
  72. data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
  73. data/spec/jruby/unpacker_spec.rb +0 -186
  74. data/spec/msgpack_spec.rb +0 -214
  75. data/spec/pack_spec.rb +0 -61
  76. data/spec/packer_spec.rb +0 -575
  77. data/spec/random_compat.rb +0 -24
  78. data/spec/spec_helper.rb +0 -71
  79. data/spec/timestamp_spec.rb +0 -159
  80. data/spec/unpack_spec.rb +0 -57
  81. data/spec/unpacker_spec.rb +0 -859
@@ -19,20 +19,52 @@
19
19
  #include "unpacker.h"
20
20
  #include "rmem.h"
21
21
  #include "extension_value_class.h"
22
+ #include <assert.h>
23
+ #include <limits.h>
22
24
 
23
- #if !defined(DISABLE_RMEM) && !defined(DISABLE_UNPACKER_STACK_RMEM) && \
24
- MSGPACK_UNPACKER_STACK_CAPACITY * MSGPACK_UNPACKER_STACK_SIZE <= MSGPACK_RMEM_PAGE_SIZE
25
- #define UNPACKER_STACK_RMEM
25
+ #if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
26
+ #define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
26
27
  #endif
27
28
 
29
+ #ifndef HAVE_RB_GC_MARK_LOCATIONS
30
+ // For TruffleRuby
31
+ void rb_gc_mark_locations(const VALUE *start, const VALUE *end)
32
+ {
33
+ VALUE *value = start;
34
+
35
+ while (value < end) {
36
+ rb_gc_mark(*value);
37
+ value++;
38
+ }
39
+ }
40
+ #endif
41
+
42
+ struct protected_proc_call_args {
43
+ VALUE proc;
44
+ int argc;
45
+ VALUE *argv;
46
+ };
47
+
48
+ static VALUE protected_proc_call_safe(VALUE _args) {
49
+ struct protected_proc_call_args *args = (struct protected_proc_call_args *)_args;
50
+
51
+ return rb_proc_call_with_block(args->proc, args->argc, args->argv, Qnil);
52
+ }
53
+
54
+ static VALUE protected_proc_call(VALUE proc, int argc, VALUE *argv, int *raised) {
55
+ struct protected_proc_call_args args = {
56
+ .proc = proc,
57
+ .argc = argc,
58
+ .argv = argv,
59
+ };
60
+ return rb_protect(protected_proc_call_safe, (VALUE)&args, raised);
61
+ }
62
+
28
63
  static int RAW_TYPE_STRING = 256;
29
64
  static int RAW_TYPE_BINARY = 257;
65
+ static int16_t INITIAL_BUFFER_CAPACITY_MAX = SHRT_MAX;
30
66
 
31
- static ID s_call;
32
-
33
- #ifdef UNPACKER_STACK_RMEM
34
67
  static msgpack_rmem_t s_stack_rmem;
35
- #endif
36
68
 
37
69
  #if !defined(HAVE_RB_HASH_NEW_CAPA)
38
70
  static inline VALUE rb_hash_new_capa(long capa)
@@ -41,89 +73,92 @@ static inline VALUE rb_hash_new_capa(long capa)
41
73
  }
42
74
  #endif
43
75
 
44
- void msgpack_unpacker_static_init()
76
+ static inline int16_t initial_buffer_size(long size)
45
77
  {
46
- #ifdef UNPACKER_STACK_RMEM
47
- msgpack_rmem_init(&s_stack_rmem);
48
- #endif
78
+ return (size > INITIAL_BUFFER_CAPACITY_MAX) ? INITIAL_BUFFER_CAPACITY_MAX : size;
79
+ }
49
80
 
50
- s_call = rb_intern("call");
81
+ void msgpack_unpacker_static_init(void)
82
+ {
83
+ assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
84
+
85
+ msgpack_rmem_init(&s_stack_rmem);
51
86
  }
52
87
 
53
- void msgpack_unpacker_static_destroy()
88
+ void msgpack_unpacker_static_destroy(void)
54
89
  {
55
- #ifdef UNPACKER_STACK_RMEM
56
90
  msgpack_rmem_destroy(&s_stack_rmem);
57
- #endif
58
91
  }
59
92
 
60
93
  #define HEAD_BYTE_REQUIRED 0xc1
61
94
 
62
- static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
63
- msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
64
- stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
65
- #ifdef UNPACKER_STACK_RMEM
66
- stack->data = msgpack_rmem_alloc(&s_stack_rmem);
67
- /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
68
- #else
69
- /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_entry_t));*/
70
- stack->data = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_entry_t));
71
- #endif
72
- return stack;
95
+ static inline bool _msgpack_unpacker_stack_init(msgpack_unpacker_stack_t *stack) {
96
+ if (!stack->data) {
97
+ stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
98
+ stack->data = msgpack_rmem_alloc(&s_stack_rmem);
99
+ stack->depth = 0;
100
+ return true;
101
+ }
102
+ return false;
73
103
  }
74
104
 
75
- msgpack_unpacker_t* _msgpack_unpacker_new(void)
76
- {
77
- msgpack_unpacker_t* uk = ZALLOC_N(msgpack_unpacker_t, 1);
105
+ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
106
+ if (stack->data) {
107
+ if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
108
+ rb_bug("Failed to free an rmem pointer, memory leak?");
109
+ }
110
+ stack->data = NULL;
111
+ stack->depth = 0;
112
+ }
113
+ }
78
114
 
115
+ #define STACK_INIT(uk) bool stack_allocated = _msgpack_unpacker_stack_init(&uk->stack);
116
+ #define STACK_FREE(uk) if (stack_allocated) { _msgpack_unpacker_free_stack(&uk->stack); }
117
+
118
+ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
119
+ {
79
120
  msgpack_buffer_init(UNPACKER_BUFFER_(uk));
80
121
 
81
122
  uk->head_byte = HEAD_BYTE_REQUIRED;
82
123
 
83
124
  uk->last_object = Qnil;
84
125
  uk->reading_raw = Qnil;
85
-
86
- uk->stack = _msgpack_unpacker_new_stack();
87
-
88
- return uk;
89
- }
90
-
91
- static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
92
- #ifdef UNPACKER_STACK_RMEM
93
- msgpack_rmem_free(&s_stack_rmem, stack->data);
94
- #else
95
- xfree(stack->data);
96
- #endif
97
- xfree(stack);
98
126
  }
99
127
 
100
128
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
101
129
  {
102
- _msgpack_unpacker_free_stack(uk->stack);
130
+ _msgpack_unpacker_free_stack(&uk->stack);
103
131
  msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
104
132
  }
105
133
 
106
134
  void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
107
135
  {
108
- while (stack) {
136
+ if (stack->data) {
109
137
  msgpack_unpacker_stack_entry_t* s = stack->data;
110
138
  msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
111
139
  for(; s < send; s++) {
112
140
  rb_gc_mark(s->object);
113
141
  rb_gc_mark(s->key);
114
142
  }
115
- stack = stack->parent;
116
143
  }
117
144
  }
118
145
 
146
+ void msgpack_unpacker_mark_key_cache(msgpack_key_cache_t *cache)
147
+ {
148
+ const VALUE *entries = &cache->entries[0];
149
+ rb_gc_mark_locations(entries, entries + cache->length);
150
+ }
151
+
119
152
  void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
120
153
  {
121
154
  rb_gc_mark(uk->last_object);
122
155
  rb_gc_mark(uk->reading_raw);
123
- msgpack_unpacker_mark_stack(uk->stack);
156
+ msgpack_unpacker_mark_stack(&uk->stack);
157
+ msgpack_unpacker_mark_key_cache(&uk->key_cache);
124
158
  /* See MessagePack_Buffer_wrap */
125
159
  /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
126
160
  rb_gc_mark(uk->buffer_ref);
161
+ rb_gc_mark(uk->self);
127
162
  }
128
163
 
129
164
  void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
@@ -132,8 +167,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
132
167
 
133
168
  uk->head_byte = HEAD_BYTE_REQUIRED;
134
169
 
135
- /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
136
- uk->stack->depth = 0;
170
+ /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack.depth);*/
171
+ uk->stack.depth = 0;
137
172
  uk->last_object = Qnil;
138
173
  uk->reading_raw = Qnil;
139
174
  uk->reading_raw_remaining = 0;
@@ -196,7 +231,13 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
196
231
 
197
232
  if(proc != Qnil) {
198
233
  VALUE obj;
199
- obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
234
+ VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
235
+ int raised;
236
+ obj = protected_proc_call(proc, 1, &arg, &raised);
237
+ if (raised) {
238
+ uk->last_object = rb_errinfo();
239
+ return PRIMITIVE_RECURSIVE_RAISED;
240
+ }
200
241
  return object_complete(uk, obj);
201
242
  }
202
243
 
@@ -211,35 +252,35 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
211
252
  /* stack funcs */
212
253
  static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
213
254
  {
214
- return &uk->stack->data[uk->stack->depth-1];
255
+ return &uk->stack.data[uk->stack.depth-1];
215
256
  }
216
257
 
217
258
  static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
218
259
  {
219
260
  reset_head_byte(uk);
220
261
 
221
- if(uk->stack->capacity - uk->stack->depth <= 0) {
262
+ if(uk->stack.capacity - uk->stack.depth <= 0) {
222
263
  return PRIMITIVE_STACK_TOO_DEEP;
223
264
  }
224
265
 
225
- msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
266
+ msgpack_unpacker_stack_entry_t* next = &uk->stack.data[uk->stack.depth];
226
267
  next->count = count;
227
268
  next->type = type;
228
269
  next->object = object;
229
270
  next->key = Qnil;
230
271
 
231
- uk->stack->depth++;
272
+ uk->stack.depth++;
232
273
  return PRIMITIVE_CONTAINER_START;
233
274
  }
234
275
 
235
- static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
276
+ static inline size_t msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
236
277
  {
237
- return --uk->stack->depth;
278
+ return --uk->stack.depth;
238
279
  }
239
280
 
240
281
  static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
241
282
  {
242
- return uk->stack->depth == 0;
283
+ return uk->stack.depth == 0;
243
284
  }
244
285
 
245
286
  #ifdef USE_CASE_RANGE
@@ -258,16 +299,29 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
258
299
 
259
300
  #endif
260
301
 
302
+ union msgpack_buffer_cast_block_t {
303
+ char buffer[8];
304
+ uint8_t u8;
305
+ uint16_t u16;
306
+ uint32_t u32;
307
+ uint64_t u64;
308
+ int8_t i8;
309
+ int16_t i16;
310
+ int32_t i32;
311
+ int64_t i64;
312
+ float f;
313
+ double d;
314
+ };
261
315
 
262
316
  #define READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, n) \
263
- union msgpack_buffer_cast_block_t* cb = msgpack_buffer_read_cast_block(UNPACKER_BUFFER_(uk), n); \
264
- if(cb == NULL) { \
317
+ union msgpack_buffer_cast_block_t cb; \
318
+ if (!msgpack_buffer_read_all(UNPACKER_BUFFER_(uk), (char *)&cb.buffer, n)) { \
265
319
  return PRIMITIVE_EOF; \
266
320
  }
267
321
 
268
322
  static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
269
323
  {
270
- if(uk->stack->depth > 0) {
324
+ if(uk->stack.depth > 0) {
271
325
  msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
272
326
  if(top->type == STACK_TYPE_MAP_KEY) {
273
327
  return true;
@@ -322,14 +376,15 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
322
376
  reset_head_byte(uk);
323
377
  uk->reading_raw_remaining = 0;
324
378
 
325
- msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
326
- child_stack->parent = uk->stack;
327
- uk->stack = child_stack;
328
-
329
- obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
379
+ _msgpack_unpacker_stack_push(uk, STACK_TYPE_RECURSIVE, 1, Qnil);
380
+ int raised;
381
+ obj = protected_proc_call(proc, 1, &uk->self, &raised);
382
+ msgpack_unpacker_stack_pop(uk);
330
383
 
331
- uk->stack = child_stack->parent;
332
- _msgpack_unpacker_free_stack(child_stack);
384
+ if (raised) {
385
+ uk->last_object = rb_errinfo();
386
+ return PRIMITIVE_RECURSIVE_RAISED;
387
+ }
333
388
 
334
389
  return object_complete(uk, obj);
335
390
  }
@@ -339,15 +394,32 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
339
394
  size_t length = uk->reading_raw_remaining;
340
395
  if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
341
396
  int ret;
342
- if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
397
+ if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type)) {
343
398
  VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
344
399
  ret = object_complete_symbol(uk, symbol);
400
+ } else if (is_reading_map_key(uk) && raw_type == RAW_TYPE_STRING) {
401
+ /* don't use zerocopy for hash keys but get a frozen string directly
402
+ * because rb_hash_aset freezes keys and it causes copying */
403
+ VALUE key;
404
+ if (uk->symbolize_keys) {
405
+ if (uk->use_key_cache) {
406
+ key = msgpack_buffer_read_top_as_interned_symbol(UNPACKER_BUFFER_(uk), &uk->key_cache, length);
407
+ } else {
408
+ key = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, true);
409
+ }
410
+ ret = object_complete_symbol(uk, key);
411
+ } else {
412
+ if (uk->use_key_cache) {
413
+ key = msgpack_buffer_read_top_as_interned_string(UNPACKER_BUFFER_(uk), &uk->key_cache, length);
414
+ } else {
415
+ key = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, true, true);
416
+ }
417
+
418
+ ret = object_complete(uk, key);
419
+ }
345
420
  } else {
346
421
  bool will_freeze = uk->freeze;
347
422
  if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
348
- /* don't use zerocopy for hash keys but get a frozen string directly
349
- * because rb_hash_aset freezes keys and it causes copying */
350
- will_freeze = will_freeze || is_reading_map_key(uk);
351
423
  VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
352
424
  ret = object_complete(uk, string);
353
425
  } else {
@@ -392,14 +464,14 @@ static int read_primitive(msgpack_unpacker_t* uk)
392
464
  if(count == 0) {
393
465
  return object_complete(uk, rb_ary_new());
394
466
  }
395
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
467
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
396
468
 
397
469
  SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
398
470
  int count = b & 0x0f;
399
471
  if(count == 0) {
400
472
  return object_complete(uk, rb_hash_new());
401
473
  }
402
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
474
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
403
475
 
404
476
  SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
405
477
  switch(b) {
@@ -417,8 +489,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
417
489
  case 0xc7: // ext 8
418
490
  {
419
491
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
420
- uint8_t length = cb->u8;
421
- int ext_type = (signed char) cb->buffer[1];
492
+ uint8_t length = cb.u8;
493
+ int ext_type = (signed char) cb.buffer[1];
422
494
  if(length == 0) {
423
495
  return object_complete_ext(uk, ext_type, Qnil);
424
496
  }
@@ -429,8 +501,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
429
501
  case 0xc8: // ext 16
430
502
  {
431
503
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 3);
432
- uint16_t length = _msgpack_be16(cb->u16);
433
- int ext_type = (signed char) cb->buffer[2];
504
+ uint16_t length = _msgpack_be16(cb.u16);
505
+ int ext_type = (signed char) cb.buffer[2];
434
506
  if(length == 0) {
435
507
  return object_complete_ext(uk, ext_type, Qnil);
436
508
  }
@@ -441,8 +513,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
441
513
  case 0xc9: // ext 32
442
514
  {
443
515
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 5);
444
- uint32_t length = _msgpack_be32(cb->u32);
445
- int ext_type = (signed char) cb->buffer[4];
516
+ uint32_t length = _msgpack_be32(cb.u32);
517
+ int ext_type = (signed char) cb.buffer[4];
446
518
  if(length == 0) {
447
519
  return object_complete_ext(uk, ext_type, Qnil);
448
520
  }
@@ -453,77 +525,77 @@ static int read_primitive(msgpack_unpacker_t* uk)
453
525
  case 0xca: // float
454
526
  {
455
527
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
456
- cb->u32 = _msgpack_be_float(cb->u32);
457
- return object_complete(uk, rb_float_new(cb->f));
528
+ cb.u32 = _msgpack_be_float(cb.u32);
529
+ return object_complete(uk, rb_float_new(cb.f));
458
530
  }
459
531
 
460
532
  case 0xcb: // double
461
533
  {
462
534
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
463
- cb->u64 = _msgpack_be_double(cb->u64);
464
- return object_complete(uk, rb_float_new(cb->d));
535
+ cb.u64 = _msgpack_be_double(cb.u64);
536
+ return object_complete(uk, rb_float_new(cb.d));
465
537
  }
466
538
 
467
539
  case 0xcc: // unsigned int 8
468
540
  {
469
541
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
470
- uint8_t u8 = cb->u8;
542
+ uint8_t u8 = cb.u8;
471
543
  return object_complete(uk, INT2NUM((int)u8));
472
544
  }
473
545
 
474
546
  case 0xcd: // unsigned int 16
475
547
  {
476
548
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
477
- uint16_t u16 = _msgpack_be16(cb->u16);
549
+ uint16_t u16 = _msgpack_be16(cb.u16);
478
550
  return object_complete(uk, INT2NUM((int)u16));
479
551
  }
480
552
 
481
553
  case 0xce: // unsigned int 32
482
554
  {
483
555
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
484
- uint32_t u32 = _msgpack_be32(cb->u32);
556
+ uint32_t u32 = _msgpack_be32(cb.u32);
485
557
  return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
486
558
  }
487
559
 
488
560
  case 0xcf: // unsigned int 64
489
561
  {
490
562
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
491
- uint64_t u64 = _msgpack_be64(cb->u64);
563
+ uint64_t u64 = _msgpack_be64(cb.u64);
492
564
  return object_complete(uk, rb_ull2inum(u64));
493
565
  }
494
566
 
495
567
  case 0xd0: // signed int 8
496
568
  {
497
569
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
498
- int8_t i8 = cb->i8;
570
+ int8_t i8 = cb.i8;
499
571
  return object_complete(uk, INT2NUM((int)i8));
500
572
  }
501
573
 
502
574
  case 0xd1: // signed int 16
503
575
  {
504
576
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
505
- int16_t i16 = _msgpack_be16(cb->i16);
577
+ int16_t i16 = _msgpack_be16(cb.i16);
506
578
  return object_complete(uk, INT2NUM((int)i16));
507
579
  }
508
580
 
509
581
  case 0xd2: // signed int 32
510
582
  {
511
583
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
512
- int32_t i32 = _msgpack_be32(cb->i32);
584
+ int32_t i32 = _msgpack_be32(cb.i32);
513
585
  return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
514
586
  }
515
587
 
516
588
  case 0xd3: // signed int 64
517
589
  {
518
590
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
519
- int64_t i64 = _msgpack_be64(cb->i64);
591
+ int64_t i64 = _msgpack_be64(cb.i64);
520
592
  return object_complete(uk, rb_ll2inum(i64));
521
593
  }
522
594
 
523
595
  case 0xd4: // fixext 1
524
596
  {
525
597
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
526
- int ext_type = cb->i8;
598
+ int ext_type = cb.i8;
527
599
  uk->reading_raw_remaining = 1;
528
600
  return read_raw_body_begin(uk, ext_type);
529
601
  }
@@ -531,7 +603,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
531
603
  case 0xd5: // fixext 2
532
604
  {
533
605
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
534
- int ext_type = cb->i8;
606
+ int ext_type = cb.i8;
535
607
  uk->reading_raw_remaining = 2;
536
608
  return read_raw_body_begin(uk, ext_type);
537
609
  }
@@ -539,7 +611,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
539
611
  case 0xd6: // fixext 4
540
612
  {
541
613
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
542
- int ext_type = cb->i8;
614
+ int ext_type = cb.i8;
543
615
  uk->reading_raw_remaining = 4;
544
616
  return read_raw_body_begin(uk, ext_type);
545
617
  }
@@ -547,7 +619,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
547
619
  case 0xd7: // fixext 8
548
620
  {
549
621
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
550
- int ext_type = cb->i8;
622
+ int ext_type = cb.i8;
551
623
  uk->reading_raw_remaining = 8;
552
624
  return read_raw_body_begin(uk, ext_type);
553
625
  }
@@ -555,7 +627,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
555
627
  case 0xd8: // fixext 16
556
628
  {
557
629
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
558
- int ext_type = cb->i8;
630
+ int ext_type = cb.i8;
559
631
  uk->reading_raw_remaining = 16;
560
632
  return read_raw_body_begin(uk, ext_type);
561
633
  }
@@ -564,7 +636,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
564
636
  case 0xd9: // raw 8 / str 8
565
637
  {
566
638
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
567
- uint8_t count = cb->u8;
639
+ uint8_t count = cb.u8;
568
640
  /* read_raw_body_begin sets uk->reading_raw */
569
641
  uk->reading_raw_remaining = count;
570
642
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -573,7 +645,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
573
645
  case 0xda: // raw 16 / str 16
574
646
  {
575
647
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
576
- uint16_t count = _msgpack_be16(cb->u16);
648
+ uint16_t count = _msgpack_be16(cb.u16);
577
649
  /* read_raw_body_begin sets uk->reading_raw */
578
650
  uk->reading_raw_remaining = count;
579
651
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -582,7 +654,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
582
654
  case 0xdb: // raw 32 / str 32
583
655
  {
584
656
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
585
- uint32_t count = _msgpack_be32(cb->u32);
657
+ uint32_t count = _msgpack_be32(cb.u32);
586
658
  /* read_raw_body_begin sets uk->reading_raw */
587
659
  uk->reading_raw_remaining = count;
588
660
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -591,7 +663,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
591
663
  case 0xc4: // bin 8
592
664
  {
593
665
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
594
- uint8_t count = cb->u8;
666
+ uint8_t count = cb.u8;
595
667
  /* read_raw_body_begin sets uk->reading_raw */
596
668
  uk->reading_raw_remaining = count;
597
669
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -600,7 +672,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
600
672
  case 0xc5: // bin 16
601
673
  {
602
674
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
603
- uint16_t count = _msgpack_be16(cb->u16);
675
+ uint16_t count = _msgpack_be16(cb.u16);
604
676
  /* read_raw_body_begin sets uk->reading_raw */
605
677
  uk->reading_raw_remaining = count;
606
678
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -609,7 +681,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
609
681
  case 0xc6: // bin 32
610
682
  {
611
683
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
612
- uint32_t count = _msgpack_be32(cb->u32);
684
+ uint32_t count = _msgpack_be32(cb.u32);
613
685
  /* read_raw_body_begin sets uk->reading_raw */
614
686
  uk->reading_raw_remaining = count;
615
687
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -618,41 +690,41 @@ static int read_primitive(msgpack_unpacker_t* uk)
618
690
  case 0xdc: // array 16
619
691
  {
620
692
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
621
- uint16_t count = _msgpack_be16(cb->u16);
693
+ uint16_t count = _msgpack_be16(cb.u16);
622
694
  if(count == 0) {
623
695
  return object_complete(uk, rb_ary_new());
624
696
  }
625
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
697
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
626
698
  }
627
699
 
628
700
  case 0xdd: // array 32
629
701
  {
630
702
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
631
- uint32_t count = _msgpack_be32(cb->u32);
703
+ uint32_t count = _msgpack_be32(cb.u32);
632
704
  if(count == 0) {
633
705
  return object_complete(uk, rb_ary_new());
634
706
  }
635
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
707
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
636
708
  }
637
709
 
638
710
  case 0xde: // map 16
639
711
  {
640
712
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
641
- uint16_t count = _msgpack_be16(cb->u16);
713
+ uint16_t count = _msgpack_be16(cb.u16);
642
714
  if(count == 0) {
643
715
  return object_complete(uk, rb_hash_new());
644
716
  }
645
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
717
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
646
718
  }
647
719
 
648
720
  case 0xdf: // map 32
649
721
  {
650
722
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
651
- uint32_t count = _msgpack_be32(cb->u32);
723
+ uint32_t count = _msgpack_be32(cb.u32);
652
724
  if(count == 0) {
653
725
  return object_complete(uk, rb_hash_new());
654
726
  }
655
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
727
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
656
728
  }
657
729
 
658
730
  default:
@@ -678,12 +750,12 @@ int msgpack_unpacker_read_array_header(msgpack_unpacker_t* uk, uint32_t* result_
678
750
  } else if(b == 0xdc) {
679
751
  /* array 16 */
680
752
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
681
- *result_size = _msgpack_be16(cb->u16);
753
+ *result_size = _msgpack_be16(cb.u16);
682
754
 
683
755
  } else if(b == 0xdd) {
684
756
  /* array 32 */
685
757
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
686
- *result_size = _msgpack_be32(cb->u32);
758
+ *result_size = _msgpack_be32(cb.u32);
687
759
 
688
760
  } else {
689
761
  return PRIMITIVE_UNEXPECTED_TYPE;
@@ -706,12 +778,12 @@ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_si
706
778
  } else if(b == 0xde) {
707
779
  /* map 16 */
708
780
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
709
- *result_size = _msgpack_be16(cb->u16);
781
+ *result_size = _msgpack_be16(cb.u16);
710
782
 
711
783
  } else if(b == 0xdf) {
712
784
  /* map 32 */
713
785
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
714
- *result_size = _msgpack_be32(cb->u32);
786
+ *result_size = _msgpack_be32(cb.u32);
715
787
 
716
788
  } else {
717
789
  return PRIMITIVE_UNEXPECTED_TYPE;
@@ -723,9 +795,15 @@ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_si
723
795
 
724
796
  int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
725
797
  {
798
+ STACK_INIT(uk);
799
+
726
800
  while(true) {
727
801
  int r = read_primitive(uk);
728
802
  if(r < 0) {
803
+ if (r != PRIMITIVE_EOF) {
804
+ // We keep the stack on EOF as the parsing may be resumed.
805
+ STACK_FREE(uk);
806
+ }
729
807
  return r;
730
808
  }
731
809
  if(r == PRIMITIVE_CONTAINER_START) {
@@ -734,6 +812,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
734
812
  /* PRIMITIVE_OBJECT_COMPLETE */
735
813
 
736
814
  if(msgpack_unpacker_stack_is_empty(uk)) {
815
+ STACK_FREE(uk);
737
816
  return PRIMITIVE_OBJECT_COMPLETE;
738
817
  }
739
818
 
@@ -757,12 +836,16 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
757
836
  }
758
837
  top->type = STACK_TYPE_MAP_KEY;
759
838
  break;
839
+ case STACK_TYPE_RECURSIVE:
840
+ STACK_FREE(uk);
841
+ return PRIMITIVE_OBJECT_COMPLETE;
760
842
  }
761
843
  size_t count = --top->count;
762
844
 
763
845
  if(count == 0) {
764
846
  object_complete(uk, top->object);
765
847
  if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
848
+ STACK_FREE(uk);
766
849
  return PRIMITIVE_OBJECT_COMPLETE;
767
850
  }
768
851
  goto container_completed;
@@ -773,9 +856,12 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
773
856
 
774
857
  int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
775
858
  {
859
+ STACK_INIT(uk);
860
+
776
861
  while(true) {
777
862
  int r = read_primitive(uk);
778
863
  if(r < 0) {
864
+ STACK_FREE(uk);
779
865
  return r;
780
866
  }
781
867
  if(r == PRIMITIVE_CONTAINER_START) {
@@ -784,6 +870,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
784
870
  /* PRIMITIVE_OBJECT_COMPLETE */
785
871
 
786
872
  if(msgpack_unpacker_stack_is_empty(uk)) {
873
+ STACK_FREE(uk);
787
874
  return PRIMITIVE_OBJECT_COMPLETE;
788
875
  }
789
876
 
@@ -799,6 +886,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
799
886
  if(count == 0) {
800
887
  object_complete(uk, Qnil);
801
888
  if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
889
+ STACK_FREE(uk);
802
890
  return PRIMITIVE_OBJECT_COMPLETE;
803
891
  }
804
892
  goto container_completed;