msgpack 1.5.4 → 1.8.1

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 +64 -1
  3. data/README.md +49 -13
  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 +75 -58
  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 +219 -127
  26. data/ext/msgpack/unpacker.h +29 -18
  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 +15 -5
  38. metadata +26 -53
  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 -664
  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,102 +19,147 @@
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
- static inline VALUE rb_hash_new_capa(long capa)
70
+ static inline VALUE rb_hash_new_capa_inline(long capa)
39
71
  {
40
72
  return rb_hash_new();
41
73
  }
74
+ #define rb_hash_new_capa rb_hash_new_capa_inline
42
75
  #endif
43
76
 
44
- void msgpack_unpacker_static_init()
77
+ static inline int16_t initial_buffer_size(long size)
45
78
  {
46
- #ifdef UNPACKER_STACK_RMEM
47
- msgpack_rmem_init(&s_stack_rmem);
48
- #endif
79
+ return (size > INITIAL_BUFFER_CAPACITY_MAX) ? INITIAL_BUFFER_CAPACITY_MAX : size;
80
+ }
81
+
82
+ void msgpack_unpacker_static_init(void)
83
+ {
84
+ assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
49
85
 
50
- s_call = rb_intern("call");
86
+ msgpack_rmem_init(&s_stack_rmem);
51
87
  }
52
88
 
53
- void msgpack_unpacker_static_destroy()
89
+ void msgpack_unpacker_static_destroy(void)
54
90
  {
55
- #ifdef UNPACKER_STACK_RMEM
56
91
  msgpack_rmem_destroy(&s_stack_rmem);
57
- #endif
58
92
  }
59
93
 
60
94
  #define HEAD_BYTE_REQUIRED 0xc1
61
95
 
62
- static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
63
- #ifdef UNPACKER_STACK_RMEM
64
- return msgpack_rmem_alloc(&s_stack_rmem);
65
- /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
66
- #else
67
- /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
68
- return xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
69
- #endif
96
+ static inline bool _msgpack_unpacker_stack_init(msgpack_unpacker_stack_t *stack) {
97
+ if (!stack->data) {
98
+ stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
99
+ stack->data = msgpack_rmem_alloc(&s_stack_rmem);
100
+ stack->depth = 0;
101
+ return true;
102
+ }
103
+ return false;
70
104
  }
71
105
 
72
- msgpack_unpacker_t* _msgpack_unpacker_new(void)
73
- {
74
- msgpack_unpacker_t* uk = ZALLOC_N(msgpack_unpacker_t, 1);
106
+ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
107
+ if (stack->data) {
108
+ if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
109
+ rb_bug("Failed to free an rmem pointer, memory leak?");
110
+ }
111
+ stack->data = NULL;
112
+ stack->depth = 0;
113
+ }
114
+ }
75
115
 
116
+ #define STACK_INIT(uk) bool stack_allocated = _msgpack_unpacker_stack_init(&uk->stack);
117
+ #define STACK_FREE(uk) if (stack_allocated) { _msgpack_unpacker_free_stack(&uk->stack); }
118
+
119
+ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
120
+ {
76
121
  msgpack_buffer_init(UNPACKER_BUFFER_(uk));
77
122
 
78
123
  uk->head_byte = HEAD_BYTE_REQUIRED;
79
124
 
80
125
  uk->last_object = Qnil;
81
126
  uk->reading_raw = Qnil;
127
+ }
82
128
 
83
- uk->stack = _msgpack_unpacker_new_stack();
84
- uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
85
-
86
- return uk;
129
+ void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
130
+ {
131
+ _msgpack_unpacker_free_stack(&uk->stack);
132
+ msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
87
133
  }
88
134
 
89
- static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
90
- #ifdef UNPACKER_STACK_RMEM
91
- msgpack_rmem_free(&s_stack_rmem, stack);
92
- #else
93
- xfree(stack);
94
- #endif
135
+ void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
136
+ {
137
+ if (stack->data) {
138
+ msgpack_unpacker_stack_entry_t* s = stack->data;
139
+ msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
140
+ for(; s < send; s++) {
141
+ rb_gc_mark(s->object);
142
+ rb_gc_mark(s->key);
143
+ }
144
+ }
95
145
  }
96
146
 
97
- void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
147
+ void msgpack_unpacker_mark_key_cache(msgpack_key_cache_t *cache)
98
148
  {
99
- _msgpack_unpacker_free_stack(uk->stack);
100
- msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
149
+ const VALUE *entries = &cache->entries[0];
150
+ rb_gc_mark_locations(entries, entries + cache->length);
101
151
  }
102
152
 
103
153
  void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
104
154
  {
105
155
  rb_gc_mark(uk->last_object);
106
156
  rb_gc_mark(uk->reading_raw);
107
-
108
- msgpack_unpacker_stack_t* s = uk->stack;
109
- msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
110
- for(; s < send; s++) {
111
- rb_gc_mark(s->object);
112
- rb_gc_mark(s->key);
113
- }
114
-
157
+ msgpack_unpacker_mark_stack(&uk->stack);
158
+ msgpack_unpacker_mark_key_cache(&uk->key_cache);
115
159
  /* See MessagePack_Buffer_wrap */
116
160
  /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
117
161
  rb_gc_mark(uk->buffer_ref);
162
+ rb_gc_mark(uk->self);
118
163
  }
119
164
 
120
165
  void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
@@ -123,9 +168,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
123
168
 
124
169
  uk->head_byte = HEAD_BYTE_REQUIRED;
125
170
 
126
- /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack_depth);*/
127
- uk->stack_depth = 0;
128
-
171
+ /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack.depth);*/
172
+ uk->stack.depth = 0;
129
173
  uk->last_object = Qnil;
130
174
  uk->reading_raw = Qnil;
131
175
  uk->reading_raw_remaining = 0;
@@ -188,7 +232,13 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
188
232
 
189
233
  if(proc != Qnil) {
190
234
  VALUE obj;
191
- obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
235
+ VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
236
+ int raised;
237
+ obj = protected_proc_call(proc, 1, &arg, &raised);
238
+ if (raised) {
239
+ uk->last_object = rb_errinfo();
240
+ return PRIMITIVE_RECURSIVE_RAISED;
241
+ }
192
242
  return object_complete(uk, obj);
193
243
  }
194
244
 
@@ -201,37 +251,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
201
251
  }
202
252
 
203
253
  /* stack funcs */
204
- static inline msgpack_unpacker_stack_t* _msgpack_unpacker_stack_top(msgpack_unpacker_t* uk)
254
+ static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
205
255
  {
206
- return &uk->stack[uk->stack_depth-1];
256
+ return &uk->stack.data[uk->stack.depth-1];
207
257
  }
208
258
 
209
259
  static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
210
260
  {
211
261
  reset_head_byte(uk);
212
262
 
213
- if(uk->stack_capacity - uk->stack_depth <= 0) {
263
+ if(uk->stack.capacity - uk->stack.depth <= 0) {
214
264
  return PRIMITIVE_STACK_TOO_DEEP;
215
265
  }
216
266
 
217
- msgpack_unpacker_stack_t* next = &uk->stack[uk->stack_depth];
267
+ msgpack_unpacker_stack_entry_t* next = &uk->stack.data[uk->stack.depth];
218
268
  next->count = count;
219
269
  next->type = type;
220
270
  next->object = object;
221
271
  next->key = Qnil;
222
272
 
223
- uk->stack_depth++;
273
+ uk->stack.depth++;
224
274
  return PRIMITIVE_CONTAINER_START;
225
275
  }
226
276
 
227
- static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
277
+ static inline size_t msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
228
278
  {
229
- return --uk->stack_depth;
279
+ return --uk->stack.depth;
230
280
  }
231
281
 
232
282
  static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
233
283
  {
234
- return uk->stack_depth == 0;
284
+ return uk->stack.depth == 0;
235
285
  }
236
286
 
237
287
  #ifdef USE_CASE_RANGE
@@ -250,17 +300,30 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
250
300
 
251
301
  #endif
252
302
 
303
+ union msgpack_buffer_cast_block_t {
304
+ char buffer[8];
305
+ uint8_t u8;
306
+ uint16_t u16;
307
+ uint32_t u32;
308
+ uint64_t u64;
309
+ int8_t i8;
310
+ int16_t i16;
311
+ int32_t i32;
312
+ int64_t i64;
313
+ float f;
314
+ double d;
315
+ };
253
316
 
254
317
  #define READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, n) \
255
- union msgpack_buffer_cast_block_t* cb = msgpack_buffer_read_cast_block(UNPACKER_BUFFER_(uk), n); \
256
- if(cb == NULL) { \
318
+ union msgpack_buffer_cast_block_t cb; \
319
+ if (!msgpack_buffer_read_all(UNPACKER_BUFFER_(uk), (char *)&cb.buffer, n)) { \
257
320
  return PRIMITIVE_EOF; \
258
321
  }
259
322
 
260
323
  static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
261
324
  {
262
- if(uk->stack_depth > 0) {
263
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
325
+ if(uk->stack.depth > 0) {
326
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
264
327
  if(top->type == STACK_TYPE_MAP_KEY) {
265
328
  return true;
266
329
  }
@@ -273,7 +336,8 @@ static int read_raw_body_cont(msgpack_unpacker_t* uk)
273
336
  size_t length = uk->reading_raw_remaining;
274
337
 
275
338
  if(uk->reading_raw == Qnil) {
276
- uk->reading_raw = rb_str_buf_new(length);
339
+ size_t buffered_size = msgpack_buffer_all_readable_size(UNPACKER_BUFFER_(uk));
340
+ uk->reading_raw = rb_str_buf_new(length > buffered_size ? buffered_size : length);
277
341
  }
278
342
 
279
343
  do {
@@ -314,20 +378,15 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
314
378
  reset_head_byte(uk);
315
379
  uk->reading_raw_remaining = 0;
316
380
 
317
- msgpack_unpacker_stack_t* stack = uk->stack;
318
- size_t stack_depth = uk->stack_depth;
319
- size_t stack_capacity = uk->stack_capacity;
320
-
321
- uk->stack = _msgpack_unpacker_new_stack();
322
- uk->stack_depth = 0;
323
- uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
324
-
325
- obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
381
+ _msgpack_unpacker_stack_push(uk, STACK_TYPE_RECURSIVE, 1, Qnil);
382
+ int raised;
383
+ obj = protected_proc_call(proc, 1, &uk->self, &raised);
384
+ msgpack_unpacker_stack_pop(uk);
326
385
 
327
- _msgpack_unpacker_free_stack(uk->stack);
328
- uk->stack = stack;
329
- uk->stack_depth = stack_depth;
330
- uk->stack_capacity = stack_capacity;
386
+ if (raised) {
387
+ uk->last_object = rb_errinfo();
388
+ return PRIMITIVE_RECURSIVE_RAISED;
389
+ }
331
390
 
332
391
  return object_complete(uk, obj);
333
392
  }
@@ -337,15 +396,32 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
337
396
  size_t length = uk->reading_raw_remaining;
338
397
  if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
339
398
  int ret;
340
- if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
399
+ if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type)) {
341
400
  VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
342
401
  ret = object_complete_symbol(uk, symbol);
402
+ } else if (is_reading_map_key(uk) && raw_type == RAW_TYPE_STRING) {
403
+ /* don't use zerocopy for hash keys but get a frozen string directly
404
+ * because rb_hash_aset freezes keys and it causes copying */
405
+ VALUE key;
406
+ if (uk->symbolize_keys) {
407
+ if (uk->use_key_cache) {
408
+ key = msgpack_buffer_read_top_as_interned_symbol(UNPACKER_BUFFER_(uk), &uk->key_cache, length);
409
+ } else {
410
+ key = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, true);
411
+ }
412
+ ret = object_complete_symbol(uk, key);
413
+ } else {
414
+ if (uk->use_key_cache) {
415
+ key = msgpack_buffer_read_top_as_interned_string(UNPACKER_BUFFER_(uk), &uk->key_cache, length);
416
+ } else {
417
+ key = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, true, true);
418
+ }
419
+
420
+ ret = object_complete(uk, key);
421
+ }
343
422
  } else {
344
423
  bool will_freeze = uk->freeze;
345
424
  if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
346
- /* don't use zerocopy for hash keys but get a frozen string directly
347
- * because rb_hash_aset freezes keys and it causes copying */
348
- will_freeze = will_freeze || is_reading_map_key(uk);
349
425
  VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
350
426
  ret = object_complete(uk, string);
351
427
  } else {
@@ -390,14 +466,14 @@ static int read_primitive(msgpack_unpacker_t* uk)
390
466
  if(count == 0) {
391
467
  return object_complete(uk, rb_ary_new());
392
468
  }
393
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
469
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
394
470
 
395
471
  SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
396
472
  int count = b & 0x0f;
397
473
  if(count == 0) {
398
474
  return object_complete(uk, rb_hash_new());
399
475
  }
400
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
476
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
401
477
 
402
478
  SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
403
479
  switch(b) {
@@ -415,8 +491,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
415
491
  case 0xc7: // ext 8
416
492
  {
417
493
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
418
- uint8_t length = cb->u8;
419
- int ext_type = (signed char) cb->buffer[1];
494
+ uint8_t length = cb.u8;
495
+ int ext_type = (signed char) cb.buffer[1];
420
496
  if(length == 0) {
421
497
  return object_complete_ext(uk, ext_type, Qnil);
422
498
  }
@@ -427,8 +503,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
427
503
  case 0xc8: // ext 16
428
504
  {
429
505
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 3);
430
- uint16_t length = _msgpack_be16(cb->u16);
431
- int ext_type = (signed char) cb->buffer[2];
506
+ uint16_t length = _msgpack_be16(cb.u16);
507
+ int ext_type = (signed char) cb.buffer[2];
432
508
  if(length == 0) {
433
509
  return object_complete_ext(uk, ext_type, Qnil);
434
510
  }
@@ -439,8 +515,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
439
515
  case 0xc9: // ext 32
440
516
  {
441
517
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 5);
442
- uint32_t length = _msgpack_be32(cb->u32);
443
- int ext_type = (signed char) cb->buffer[4];
518
+ uint32_t length = _msgpack_be32(cb.u32);
519
+ int ext_type = (signed char) cb.buffer[4];
444
520
  if(length == 0) {
445
521
  return object_complete_ext(uk, ext_type, Qnil);
446
522
  }
@@ -451,77 +527,77 @@ static int read_primitive(msgpack_unpacker_t* uk)
451
527
  case 0xca: // float
452
528
  {
453
529
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
454
- cb->u32 = _msgpack_be_float(cb->u32);
455
- return object_complete(uk, rb_float_new(cb->f));
530
+ cb.u32 = _msgpack_be_float(cb.u32);
531
+ return object_complete(uk, rb_float_new(cb.f));
456
532
  }
457
533
 
458
534
  case 0xcb: // double
459
535
  {
460
536
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
461
- cb->u64 = _msgpack_be_double(cb->u64);
462
- return object_complete(uk, rb_float_new(cb->d));
537
+ cb.u64 = _msgpack_be_double(cb.u64);
538
+ return object_complete(uk, rb_float_new(cb.d));
463
539
  }
464
540
 
465
541
  case 0xcc: // unsigned int 8
466
542
  {
467
543
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
468
- uint8_t u8 = cb->u8;
544
+ uint8_t u8 = cb.u8;
469
545
  return object_complete(uk, INT2NUM((int)u8));
470
546
  }
471
547
 
472
548
  case 0xcd: // unsigned int 16
473
549
  {
474
550
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
475
- uint16_t u16 = _msgpack_be16(cb->u16);
551
+ uint16_t u16 = _msgpack_be16(cb.u16);
476
552
  return object_complete(uk, INT2NUM((int)u16));
477
553
  }
478
554
 
479
555
  case 0xce: // unsigned int 32
480
556
  {
481
557
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
482
- uint32_t u32 = _msgpack_be32(cb->u32);
558
+ uint32_t u32 = _msgpack_be32(cb.u32);
483
559
  return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
484
560
  }
485
561
 
486
562
  case 0xcf: // unsigned int 64
487
563
  {
488
564
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
489
- uint64_t u64 = _msgpack_be64(cb->u64);
565
+ uint64_t u64 = _msgpack_be64(cb.u64);
490
566
  return object_complete(uk, rb_ull2inum(u64));
491
567
  }
492
568
 
493
569
  case 0xd0: // signed int 8
494
570
  {
495
571
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
496
- int8_t i8 = cb->i8;
572
+ int8_t i8 = cb.i8;
497
573
  return object_complete(uk, INT2NUM((int)i8));
498
574
  }
499
575
 
500
576
  case 0xd1: // signed int 16
501
577
  {
502
578
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
503
- int16_t i16 = _msgpack_be16(cb->i16);
579
+ int16_t i16 = _msgpack_be16(cb.i16);
504
580
  return object_complete(uk, INT2NUM((int)i16));
505
581
  }
506
582
 
507
583
  case 0xd2: // signed int 32
508
584
  {
509
585
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
510
- int32_t i32 = _msgpack_be32(cb->i32);
586
+ int32_t i32 = _msgpack_be32(cb.i32);
511
587
  return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
512
588
  }
513
589
 
514
590
  case 0xd3: // signed int 64
515
591
  {
516
592
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
517
- int64_t i64 = _msgpack_be64(cb->i64);
593
+ int64_t i64 = _msgpack_be64(cb.i64);
518
594
  return object_complete(uk, rb_ll2inum(i64));
519
595
  }
520
596
 
521
597
  case 0xd4: // fixext 1
522
598
  {
523
599
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
524
- int ext_type = cb->i8;
600
+ int ext_type = cb.i8;
525
601
  uk->reading_raw_remaining = 1;
526
602
  return read_raw_body_begin(uk, ext_type);
527
603
  }
@@ -529,7 +605,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
529
605
  case 0xd5: // fixext 2
530
606
  {
531
607
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
532
- int ext_type = cb->i8;
608
+ int ext_type = cb.i8;
533
609
  uk->reading_raw_remaining = 2;
534
610
  return read_raw_body_begin(uk, ext_type);
535
611
  }
@@ -537,7 +613,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
537
613
  case 0xd6: // fixext 4
538
614
  {
539
615
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
540
- int ext_type = cb->i8;
616
+ int ext_type = cb.i8;
541
617
  uk->reading_raw_remaining = 4;
542
618
  return read_raw_body_begin(uk, ext_type);
543
619
  }
@@ -545,7 +621,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
545
621
  case 0xd7: // fixext 8
546
622
  {
547
623
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
548
- int ext_type = cb->i8;
624
+ int ext_type = cb.i8;
549
625
  uk->reading_raw_remaining = 8;
550
626
  return read_raw_body_begin(uk, ext_type);
551
627
  }
@@ -553,7 +629,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
553
629
  case 0xd8: // fixext 16
554
630
  {
555
631
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
556
- int ext_type = cb->i8;
632
+ int ext_type = cb.i8;
557
633
  uk->reading_raw_remaining = 16;
558
634
  return read_raw_body_begin(uk, ext_type);
559
635
  }
@@ -562,7 +638,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
562
638
  case 0xd9: // raw 8 / str 8
563
639
  {
564
640
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
565
- uint8_t count = cb->u8;
641
+ uint8_t count = cb.u8;
566
642
  /* read_raw_body_begin sets uk->reading_raw */
567
643
  uk->reading_raw_remaining = count;
568
644
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -571,7 +647,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
571
647
  case 0xda: // raw 16 / str 16
572
648
  {
573
649
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
574
- uint16_t count = _msgpack_be16(cb->u16);
650
+ uint16_t count = _msgpack_be16(cb.u16);
575
651
  /* read_raw_body_begin sets uk->reading_raw */
576
652
  uk->reading_raw_remaining = count;
577
653
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -580,7 +656,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
580
656
  case 0xdb: // raw 32 / str 32
581
657
  {
582
658
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
583
- uint32_t count = _msgpack_be32(cb->u32);
659
+ uint32_t count = _msgpack_be32(cb.u32);
584
660
  /* read_raw_body_begin sets uk->reading_raw */
585
661
  uk->reading_raw_remaining = count;
586
662
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -589,7 +665,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
589
665
  case 0xc4: // bin 8
590
666
  {
591
667
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
592
- uint8_t count = cb->u8;
668
+ uint8_t count = cb.u8;
593
669
  /* read_raw_body_begin sets uk->reading_raw */
594
670
  uk->reading_raw_remaining = count;
595
671
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -598,7 +674,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
598
674
  case 0xc5: // bin 16
599
675
  {
600
676
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
601
- uint16_t count = _msgpack_be16(cb->u16);
677
+ uint16_t count = _msgpack_be16(cb.u16);
602
678
  /* read_raw_body_begin sets uk->reading_raw */
603
679
  uk->reading_raw_remaining = count;
604
680
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -607,7 +683,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
607
683
  case 0xc6: // bin 32
608
684
  {
609
685
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
610
- uint32_t count = _msgpack_be32(cb->u32);
686
+ uint32_t count = _msgpack_be32(cb.u32);
611
687
  /* read_raw_body_begin sets uk->reading_raw */
612
688
  uk->reading_raw_remaining = count;
613
689
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -616,41 +692,41 @@ static int read_primitive(msgpack_unpacker_t* uk)
616
692
  case 0xdc: // array 16
617
693
  {
618
694
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
619
- uint16_t count = _msgpack_be16(cb->u16);
695
+ uint16_t count = _msgpack_be16(cb.u16);
620
696
  if(count == 0) {
621
697
  return object_complete(uk, rb_ary_new());
622
698
  }
623
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
699
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
624
700
  }
625
701
 
626
702
  case 0xdd: // array 32
627
703
  {
628
704
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
629
- uint32_t count = _msgpack_be32(cb->u32);
705
+ uint32_t count = _msgpack_be32(cb.u32);
630
706
  if(count == 0) {
631
707
  return object_complete(uk, rb_ary_new());
632
708
  }
633
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
709
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
634
710
  }
635
711
 
636
712
  case 0xde: // map 16
637
713
  {
638
714
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
639
- uint16_t count = _msgpack_be16(cb->u16);
715
+ uint16_t count = _msgpack_be16(cb.u16);
640
716
  if(count == 0) {
641
717
  return object_complete(uk, rb_hash_new());
642
718
  }
643
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
719
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
644
720
  }
645
721
 
646
722
  case 0xdf: // map 32
647
723
  {
648
724
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
649
- uint32_t count = _msgpack_be32(cb->u32);
725
+ uint32_t count = _msgpack_be32(cb.u32);
650
726
  if(count == 0) {
651
727
  return object_complete(uk, rb_hash_new());
652
728
  }
653
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
729
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
654
730
  }
655
731
 
656
732
  default:
@@ -676,12 +752,12 @@ int msgpack_unpacker_read_array_header(msgpack_unpacker_t* uk, uint32_t* result_
676
752
  } else if(b == 0xdc) {
677
753
  /* array 16 */
678
754
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
679
- *result_size = _msgpack_be16(cb->u16);
755
+ *result_size = _msgpack_be16(cb.u16);
680
756
 
681
757
  } else if(b == 0xdd) {
682
758
  /* array 32 */
683
759
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
684
- *result_size = _msgpack_be32(cb->u32);
760
+ *result_size = _msgpack_be32(cb.u32);
685
761
 
686
762
  } else {
687
763
  return PRIMITIVE_UNEXPECTED_TYPE;
@@ -704,12 +780,12 @@ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_si
704
780
  } else if(b == 0xde) {
705
781
  /* map 16 */
706
782
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
707
- *result_size = _msgpack_be16(cb->u16);
783
+ *result_size = _msgpack_be16(cb.u16);
708
784
 
709
785
  } else if(b == 0xdf) {
710
786
  /* map 32 */
711
787
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
712
- *result_size = _msgpack_be32(cb->u32);
788
+ *result_size = _msgpack_be32(cb.u32);
713
789
 
714
790
  } else {
715
791
  return PRIMITIVE_UNEXPECTED_TYPE;
@@ -721,9 +797,15 @@ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_si
721
797
 
722
798
  int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
723
799
  {
800
+ STACK_INIT(uk);
801
+
724
802
  while(true) {
725
803
  int r = read_primitive(uk);
726
804
  if(r < 0) {
805
+ if (r != PRIMITIVE_EOF) {
806
+ // We keep the stack on EOF as the parsing may be resumed.
807
+ STACK_FREE(uk);
808
+ }
727
809
  return r;
728
810
  }
729
811
  if(r == PRIMITIVE_CONTAINER_START) {
@@ -732,12 +814,13 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
732
814
  /* PRIMITIVE_OBJECT_COMPLETE */
733
815
 
734
816
  if(msgpack_unpacker_stack_is_empty(uk)) {
817
+ STACK_FREE(uk);
735
818
  return PRIMITIVE_OBJECT_COMPLETE;
736
819
  }
737
820
 
738
821
  container_completed:
739
822
  {
740
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
823
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
741
824
  switch(top->type) {
742
825
  case STACK_TYPE_ARRAY:
743
826
  rb_ary_push(top->object, uk->last_object);
@@ -755,12 +838,16 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
755
838
  }
756
839
  top->type = STACK_TYPE_MAP_KEY;
757
840
  break;
841
+ case STACK_TYPE_RECURSIVE:
842
+ STACK_FREE(uk);
843
+ return PRIMITIVE_OBJECT_COMPLETE;
758
844
  }
759
845
  size_t count = --top->count;
760
846
 
761
847
  if(count == 0) {
762
848
  object_complete(uk, top->object);
763
849
  if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
850
+ STACK_FREE(uk);
764
851
  return PRIMITIVE_OBJECT_COMPLETE;
765
852
  }
766
853
  goto container_completed;
@@ -771,9 +858,12 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
771
858
 
772
859
  int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
773
860
  {
861
+ STACK_INIT(uk);
862
+
774
863
  while(true) {
775
864
  int r = read_primitive(uk);
776
865
  if(r < 0) {
866
+ STACK_FREE(uk);
777
867
  return r;
778
868
  }
779
869
  if(r == PRIMITIVE_CONTAINER_START) {
@@ -782,12 +872,13 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
782
872
  /* PRIMITIVE_OBJECT_COMPLETE */
783
873
 
784
874
  if(msgpack_unpacker_stack_is_empty(uk)) {
875
+ STACK_FREE(uk);
785
876
  return PRIMITIVE_OBJECT_COMPLETE;
786
877
  }
787
878
 
788
879
  container_completed:
789
880
  {
790
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
881
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
791
882
 
792
883
  /* this section optimized out */
793
884
  // TODO object_complete still creates objects which should be optimized out
@@ -797,6 +888,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
797
888
  if(count == 0) {
798
889
  object_complete(uk, Qnil);
799
890
  if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
891
+ STACK_FREE(uk);
800
892
  return PRIMITIVE_OBJECT_COMPLETE;
801
893
  }
802
894
  goto container_completed;