msgpack 1.4.2 → 1.7.3

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +89 -0
  3. data/README.md +73 -13
  4. data/ext/java/org/msgpack/jruby/Buffer.java +26 -19
  5. data/ext/java/org/msgpack/jruby/Decoder.java +29 -21
  6. data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
  7. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +43 -64
  8. data/ext/java/org/msgpack/jruby/ExtensionValue.java +6 -9
  9. data/ext/java/org/msgpack/jruby/Factory.java +43 -42
  10. data/ext/java/org/msgpack/jruby/Packer.java +37 -40
  11. data/ext/java/org/msgpack/jruby/Unpacker.java +80 -73
  12. data/ext/msgpack/buffer.c +54 -74
  13. data/ext/msgpack/buffer.h +21 -18
  14. data/ext/msgpack/buffer_class.c +161 -52
  15. data/ext/msgpack/buffer_class.h +1 -0
  16. data/ext/msgpack/compat.h +0 -99
  17. data/ext/msgpack/extconf.rb +25 -46
  18. data/ext/msgpack/factory_class.c +143 -87
  19. data/ext/msgpack/packer.c +66 -43
  20. data/ext/msgpack/packer.h +25 -20
  21. data/ext/msgpack/packer_class.c +102 -130
  22. data/ext/msgpack/packer_class.h +11 -0
  23. data/ext/msgpack/packer_ext_registry.c +35 -40
  24. data/ext/msgpack/packer_ext_registry.h +41 -38
  25. data/ext/msgpack/rbinit.c +1 -1
  26. data/ext/msgpack/rmem.c +3 -4
  27. data/ext/msgpack/sysdep.h +5 -2
  28. data/ext/msgpack/unpacker.c +136 -111
  29. data/ext/msgpack/unpacker.h +16 -13
  30. data/ext/msgpack/unpacker_class.c +86 -126
  31. data/ext/msgpack/unpacker_class.h +11 -0
  32. data/ext/msgpack/unpacker_ext_registry.c +40 -28
  33. data/ext/msgpack/unpacker_ext_registry.h +21 -18
  34. data/lib/msgpack/bigint.rb +69 -0
  35. data/lib/msgpack/buffer.rb +9 -0
  36. data/lib/msgpack/factory.rb +140 -10
  37. data/lib/msgpack/packer.rb +10 -1
  38. data/lib/msgpack/symbol.rb +21 -4
  39. data/lib/msgpack/time.rb +1 -1
  40. data/lib/msgpack/unpacker.rb +14 -1
  41. data/lib/msgpack/version.rb +1 -1
  42. data/lib/msgpack.rb +6 -7
  43. data/msgpack.gemspec +8 -5
  44. metadata +37 -82
  45. data/.gitignore +0 -23
  46. data/.rubocop.yml +0 -36
  47. data/.travis.yml +0 -39
  48. data/Gemfile +0 -9
  49. data/Rakefile +0 -71
  50. data/appveyor.yml +0 -18
  51. data/bench/pack.rb +0 -23
  52. data/bench/pack_log.rb +0 -33
  53. data/bench/pack_log_long.rb +0 -65
  54. data/bench/pack_symbols.rb +0 -28
  55. data/bench/run.sh +0 -14
  56. data/bench/run_long.sh +0 -35
  57. data/bench/run_symbols.sh +0 -26
  58. data/bench/unpack.rb +0 -21
  59. data/bench/unpack_log.rb +0 -34
  60. data/bench/unpack_log_long.rb +0 -67
  61. data/doclib/msgpack/buffer.rb +0 -193
  62. data/doclib/msgpack/core_ext.rb +0 -101
  63. data/doclib/msgpack/error.rb +0 -19
  64. data/doclib/msgpack/extension_value.rb +0 -9
  65. data/doclib/msgpack/factory.rb +0 -101
  66. data/doclib/msgpack/packer.rb +0 -208
  67. data/doclib/msgpack/time.rb +0 -22
  68. data/doclib/msgpack/timestamp.rb +0 -44
  69. data/doclib/msgpack/unpacker.rb +0 -183
  70. data/doclib/msgpack.rb +0 -87
  71. data/msgpack.org.md +0 -46
  72. data/spec/cases.json +0 -1
  73. data/spec/cases.msg +0 -0
  74. data/spec/cases_compact.msg +0 -0
  75. data/spec/cases_spec.rb +0 -39
  76. data/spec/cruby/buffer_io_spec.rb +0 -255
  77. data/spec/cruby/buffer_packer.rb +0 -29
  78. data/spec/cruby/buffer_spec.rb +0 -575
  79. data/spec/cruby/buffer_unpacker.rb +0 -19
  80. data/spec/cruby/unpacker_spec.rb +0 -70
  81. data/spec/ext_value_spec.rb +0 -99
  82. data/spec/exttypes.rb +0 -51
  83. data/spec/factory_spec.rb +0 -367
  84. data/spec/format_spec.rb +0 -301
  85. data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
  86. data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
  87. data/spec/jruby/unpacker_spec.rb +0 -186
  88. data/spec/msgpack_spec.rb +0 -214
  89. data/spec/pack_spec.rb +0 -61
  90. data/spec/packer_spec.rb +0 -557
  91. data/spec/random_compat.rb +0 -24
  92. data/spec/spec_helper.rb +0 -55
  93. data/spec/timestamp_spec.rb +0 -121
  94. data/spec/unpack_spec.rb +0 -57
  95. data/spec/unpacker_spec.rb +0 -819
@@ -19,43 +19,55 @@
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
 
28
29
  static int RAW_TYPE_STRING = 256;
29
30
  static int RAW_TYPE_BINARY = 257;
31
+ static int16_t INITIAL_BUFFER_CAPACITY_MAX = SHRT_MAX;
30
32
 
31
- static ID s_call;
32
-
33
- #ifdef UNPACKER_STACK_RMEM
34
33
  static msgpack_rmem_t s_stack_rmem;
35
- #endif
36
34
 
37
- void msgpack_unpacker_static_init()
35
+ #if !defined(HAVE_RB_HASH_NEW_CAPA)
36
+ static inline VALUE rb_hash_new_capa(long capa)
38
37
  {
39
- #ifdef UNPACKER_STACK_RMEM
40
- msgpack_rmem_init(&s_stack_rmem);
38
+ return rb_hash_new();
39
+ }
41
40
  #endif
42
41
 
43
- s_call = rb_intern("call");
42
+ static inline int16_t initial_buffer_size(long size)
43
+ {
44
+ return (size > INITIAL_BUFFER_CAPACITY_MAX) ? INITIAL_BUFFER_CAPACITY_MAX : size;
45
+ }
46
+
47
+ void msgpack_unpacker_static_init(void)
48
+ {
49
+ assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
50
+
51
+ msgpack_rmem_init(&s_stack_rmem);
44
52
  }
45
53
 
46
- void msgpack_unpacker_static_destroy()
54
+ void msgpack_unpacker_static_destroy(void)
47
55
  {
48
- #ifdef UNPACKER_STACK_RMEM
49
56
  msgpack_rmem_destroy(&s_stack_rmem);
50
- #endif
51
57
  }
52
58
 
53
59
  #define HEAD_BYTE_REQUIRED 0xc1
54
60
 
61
+ static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
62
+ msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
63
+ stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
64
+ stack->data = msgpack_rmem_alloc(&s_stack_rmem);
65
+ /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
66
+ return stack;
67
+ }
68
+
55
69
  void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
56
70
  {
57
- memset(uk, 0, sizeof(msgpack_unpacker_t));
58
-
59
71
  msgpack_buffer_init(UNPACKER_BUFFER_(uk));
60
72
 
61
73
  uk->head_byte = HEAD_BYTE_REQUIRED;
@@ -63,42 +75,44 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
63
75
  uk->last_object = Qnil;
64
76
  uk->reading_raw = Qnil;
65
77
 
66
- #ifdef UNPACKER_STACK_RMEM
67
- uk->stack = msgpack_rmem_alloc(&s_stack_rmem);
68
- /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
69
- #else
70
- /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
71
- uk->stack = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
72
- #endif
73
- uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
78
+ uk->stack = _msgpack_unpacker_new_stack();
79
+ }
80
+
81
+ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
82
+ if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
83
+ rb_bug("Failed to free an rmem pointer, memory leak?");
84
+ }
85
+ xfree(stack);
74
86
  }
75
87
 
76
88
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
77
89
  {
78
- #ifdef UNPACKER_STACK_RMEM
79
- msgpack_rmem_free(&s_stack_rmem, uk->stack);
80
- #else
81
- xfree(uk->stack);
82
- #endif
83
-
90
+ _msgpack_unpacker_free_stack(uk->stack);
84
91
  msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
85
92
  }
86
93
 
94
+ void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
95
+ {
96
+ while (stack) {
97
+ msgpack_unpacker_stack_entry_t* s = stack->data;
98
+ msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
99
+ for(; s < send; s++) {
100
+ rb_gc_mark(s->object);
101
+ rb_gc_mark(s->key);
102
+ }
103
+ stack = stack->parent;
104
+ }
105
+ }
106
+
87
107
  void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
88
108
  {
89
109
  rb_gc_mark(uk->last_object);
90
110
  rb_gc_mark(uk->reading_raw);
91
-
92
- msgpack_unpacker_stack_t* s = uk->stack;
93
- msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
94
- for(; s < send; s++) {
95
- rb_gc_mark(s->object);
96
- rb_gc_mark(s->key);
97
- }
98
-
111
+ msgpack_unpacker_mark_stack(uk->stack);
99
112
  /* See MessagePack_Buffer_wrap */
100
113
  /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
101
114
  rb_gc_mark(uk->buffer_ref);
115
+ rb_gc_mark(uk->self);
102
116
  }
103
117
 
104
118
  void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
@@ -107,9 +121,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
107
121
 
108
122
  uk->head_byte = HEAD_BYTE_REQUIRED;
109
123
 
110
- /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack_depth);*/
111
- uk->stack_depth = 0;
112
-
124
+ /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
125
+ uk->stack->depth = 0;
113
126
  uk->last_object = Qnil;
114
127
  uk->reading_raw = Qnil;
115
128
  uk->reading_raw_remaining = 0;
@@ -151,16 +164,34 @@ static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
151
164
  return PRIMITIVE_OBJECT_COMPLETE;
152
165
  }
153
166
 
167
+ static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
168
+ {
169
+ uk->last_object = object;
170
+ reset_head_byte(uk);
171
+ return PRIMITIVE_OBJECT_COMPLETE;
172
+ }
173
+
154
174
  static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
155
175
  {
156
- VALUE proc = msgpack_unpacker_ext_registry_lookup(&uk->ext_registry, ext_type);
176
+ if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
177
+ if (RB_UNLIKELY(NIL_P(str))) { // empty extension is returned as Qnil
178
+ return object_complete_symbol(uk, ID2SYM(rb_intern3("", 0, rb_utf8_encoding())));
179
+ }
180
+ return object_complete_symbol(uk, rb_str_intern(str));
181
+ }
182
+
183
+ int ext_flags;
184
+ VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
185
+
157
186
  if(proc != Qnil) {
158
- VALUE obj = rb_funcall(proc, s_call, 1, str);
187
+ VALUE obj;
188
+ VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
189
+ obj = rb_proc_call_with_block(proc, 1, &arg, Qnil);
159
190
  return object_complete(uk, obj);
160
191
  }
161
192
 
162
193
  if(uk->allow_unknown_ext) {
163
- VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
194
+ VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
164
195
  return object_complete(uk, obj);
165
196
  }
166
197
 
@@ -168,37 +199,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
168
199
  }
169
200
 
170
201
  /* stack funcs */
171
- static inline msgpack_unpacker_stack_t* _msgpack_unpacker_stack_top(msgpack_unpacker_t* uk)
202
+ static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
172
203
  {
173
- return &uk->stack[uk->stack_depth-1];
204
+ return &uk->stack->data[uk->stack->depth-1];
174
205
  }
175
206
 
176
207
  static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
177
208
  {
178
209
  reset_head_byte(uk);
179
210
 
180
- if(uk->stack_capacity - uk->stack_depth <= 0) {
211
+ if(uk->stack->capacity - uk->stack->depth <= 0) {
181
212
  return PRIMITIVE_STACK_TOO_DEEP;
182
213
  }
183
214
 
184
- msgpack_unpacker_stack_t* next = &uk->stack[uk->stack_depth];
215
+ msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
185
216
  next->count = count;
186
217
  next->type = type;
187
218
  next->object = object;
188
219
  next->key = Qnil;
189
220
 
190
- uk->stack_depth++;
221
+ uk->stack->depth++;
191
222
  return PRIMITIVE_CONTAINER_START;
192
223
  }
193
224
 
194
225
  static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
195
226
  {
196
- return --uk->stack_depth;
227
+ return --uk->stack->depth;
197
228
  }
198
229
 
199
230
  static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
200
231
  {
201
- return uk->stack_depth == 0;
232
+ return uk->stack->depth == 0;
202
233
  }
203
234
 
204
235
  #ifdef USE_CASE_RANGE
@@ -226,8 +257,8 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
226
257
 
227
258
  static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
228
259
  {
229
- if(uk->stack_depth > 0) {
230
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
260
+ if(uk->stack->depth > 0) {
261
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
231
262
  if(top->type == STACK_TYPE_MAP_KEY) {
232
263
  return true;
233
264
  }
@@ -270,25 +301,50 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
270
301
  {
271
302
  /* assuming uk->reading_raw == Qnil */
272
303
 
304
+ int ext_flags;
305
+ VALUE proc;
306
+
307
+ if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
308
+ proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
309
+ if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
310
+ VALUE obj;
311
+ uk->last_object = Qnil;
312
+ reset_head_byte(uk);
313
+ uk->reading_raw_remaining = 0;
314
+
315
+ msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
316
+ child_stack->parent = uk->stack;
317
+ uk->stack = child_stack;
318
+
319
+ obj = rb_proc_call_with_block(proc, 1, &uk->self, Qnil);
320
+
321
+ uk->stack = child_stack->parent;
322
+ _msgpack_unpacker_free_stack(child_stack);
323
+
324
+ return object_complete(uk, obj);
325
+ }
326
+ }
327
+
273
328
  /* try optimized read */
274
329
  size_t length = uk->reading_raw_remaining;
275
330
  if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
276
- /* don't use zerocopy for hash keys but get a frozen string directly
277
- * because rb_hash_aset freezes keys and it causes copying */
278
- bool will_freeze = uk->freeze || is_reading_map_key(uk);
279
- VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
280
331
  int ret;
281
- if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
282
- ret = object_complete(uk, string);
332
+ if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
333
+ VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
334
+ ret = object_complete_symbol(uk, symbol);
283
335
  } else {
284
- ret = object_complete_ext(uk, raw_type, string);
285
- }
286
-
287
- # if !HASH_ASET_DEDUPE
288
- if(will_freeze) {
289
- rb_obj_freeze(string);
336
+ bool will_freeze = uk->freeze;
337
+ if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
338
+ /* don't use zerocopy for hash keys but get a frozen string directly
339
+ * because rb_hash_aset freezes keys and it causes copying */
340
+ will_freeze = will_freeze || is_reading_map_key(uk);
341
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
342
+ ret = object_complete(uk, string);
343
+ } else {
344
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, false, false);
345
+ ret = object_complete_ext(uk, raw_type, string);
346
+ }
290
347
  }
291
- # endif
292
348
  uk->reading_raw_remaining = 0;
293
349
  return ret;
294
350
  }
@@ -317,9 +373,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
317
373
 
318
374
  SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
319
375
  int count = b & 0x1f;
320
- if(count == 0) {
321
- return object_complete(uk, rb_utf8_str_new_static("", 0));
322
- }
323
376
  /* read_raw_body_begin sets uk->reading_raw */
324
377
  uk->reading_raw_remaining = count;
325
378
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -329,14 +382,14 @@ static int read_primitive(msgpack_unpacker_t* uk)
329
382
  if(count == 0) {
330
383
  return object_complete(uk, rb_ary_new());
331
384
  }
332
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
385
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
333
386
 
334
387
  SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
335
388
  int count = b & 0x0f;
336
389
  if(count == 0) {
337
390
  return object_complete(uk, rb_hash_new());
338
391
  }
339
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
392
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
340
393
 
341
394
  SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
342
395
  switch(b) {
@@ -357,7 +410,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
357
410
  uint8_t length = cb->u8;
358
411
  int ext_type = (signed char) cb->buffer[1];
359
412
  if(length == 0) {
360
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
413
+ return object_complete_ext(uk, ext_type, Qnil);
361
414
  }
362
415
  uk->reading_raw_remaining = length;
363
416
  return read_raw_body_begin(uk, ext_type);
@@ -369,7 +422,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
369
422
  uint16_t length = _msgpack_be16(cb->u16);
370
423
  int ext_type = (signed char) cb->buffer[2];
371
424
  if(length == 0) {
372
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
425
+ return object_complete_ext(uk, ext_type, Qnil);
373
426
  }
374
427
  uk->reading_raw_remaining = length;
375
428
  return read_raw_body_begin(uk, ext_type);
@@ -381,7 +434,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
381
434
  uint32_t length = _msgpack_be32(cb->u32);
382
435
  int ext_type = (signed char) cb->buffer[4];
383
436
  if(length == 0) {
384
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
437
+ return object_complete_ext(uk, ext_type, Qnil);
385
438
  }
386
439
  uk->reading_raw_remaining = length;
387
440
  return read_raw_body_begin(uk, ext_type);
@@ -419,7 +472,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
419
472
  {
420
473
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
421
474
  uint32_t u32 = _msgpack_be32(cb->u32);
422
- return object_complete(uk, ULONG2NUM((unsigned long)u32));
475
+ return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
423
476
  }
424
477
 
425
478
  case 0xcf: // unsigned int 64
@@ -447,7 +500,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
447
500
  {
448
501
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
449
502
  int32_t i32 = _msgpack_be32(cb->i32);
450
- return object_complete(uk, LONG2NUM((long)i32));
503
+ return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
451
504
  }
452
505
 
453
506
  case 0xd3: // signed int 64
@@ -502,9 +555,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
502
555
  {
503
556
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
504
557
  uint8_t count = cb->u8;
505
- if(count == 0) {
506
- return object_complete(uk, rb_utf8_str_new_static("", 0));
507
- }
508
558
  /* read_raw_body_begin sets uk->reading_raw */
509
559
  uk->reading_raw_remaining = count;
510
560
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -514,9 +564,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
514
564
  {
515
565
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
516
566
  uint16_t count = _msgpack_be16(cb->u16);
517
- if(count == 0) {
518
- return object_complete(uk, rb_utf8_str_new_static("", 0));
519
- }
520
567
  /* read_raw_body_begin sets uk->reading_raw */
521
568
  uk->reading_raw_remaining = count;
522
569
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -526,9 +573,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
526
573
  {
527
574
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
528
575
  uint32_t count = _msgpack_be32(cb->u32);
529
- if(count == 0) {
530
- return object_complete(uk, rb_utf8_str_new_static("", 0));
531
- }
532
576
  /* read_raw_body_begin sets uk->reading_raw */
533
577
  uk->reading_raw_remaining = count;
534
578
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -538,9 +582,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
538
582
  {
539
583
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
540
584
  uint8_t count = cb->u8;
541
- if(count == 0) {
542
- return object_complete(uk, rb_str_new_static("", 0));
543
- }
544
585
  /* read_raw_body_begin sets uk->reading_raw */
545
586
  uk->reading_raw_remaining = count;
546
587
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -550,9 +591,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
550
591
  {
551
592
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
552
593
  uint16_t count = _msgpack_be16(cb->u16);
553
- if(count == 0) {
554
- return object_complete(uk, rb_str_new_static("", 0));
555
- }
556
594
  /* read_raw_body_begin sets uk->reading_raw */
557
595
  uk->reading_raw_remaining = count;
558
596
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -562,9 +600,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
562
600
  {
563
601
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
564
602
  uint32_t count = _msgpack_be32(cb->u32);
565
- if(count == 0) {
566
- return object_complete(uk, rb_str_new_static("", 0));
567
- }
568
603
  /* read_raw_body_begin sets uk->reading_raw */
569
604
  uk->reading_raw_remaining = count;
570
605
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -577,7 +612,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
577
612
  if(count == 0) {
578
613
  return object_complete(uk, rb_ary_new());
579
614
  }
580
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
615
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
581
616
  }
582
617
 
583
618
  case 0xdd: // array 32
@@ -587,7 +622,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
587
622
  if(count == 0) {
588
623
  return object_complete(uk, rb_ary_new());
589
624
  }
590
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
625
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
591
626
  }
592
627
 
593
628
  case 0xde: // map 16
@@ -597,7 +632,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
597
632
  if(count == 0) {
598
633
  return object_complete(uk, rb_hash_new());
599
634
  }
600
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
635
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
601
636
  }
602
637
 
603
638
  case 0xdf: // map 32
@@ -607,7 +642,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
607
642
  if(count == 0) {
608
643
  return object_complete(uk, rb_hash_new());
609
644
  }
610
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
645
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
611
646
  }
612
647
 
613
648
  default:
@@ -694,7 +729,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
694
729
 
695
730
  container_completed:
696
731
  {
697
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
732
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
698
733
  switch(top->type) {
699
734
  case STACK_TYPE_ARRAY:
700
735
  rb_ary_push(top->object, uk->last_object);
@@ -705,18 +740,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
705
740
  break;
706
741
  case STACK_TYPE_MAP_VALUE:
707
742
  if(uk->symbolize_keys && rb_type(top->key) == T_STRING) {
708
- /* here uses rb_intern_str instead of rb_intern so that Ruby VM can GC unused symbols */
709
- #ifdef HAVE_RB_STR_INTERN
710
- /* rb_str_intern is added since MRI 2.2.0 */
743
+ /* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
711
744
  rb_hash_aset(top->object, rb_str_intern(top->key), uk->last_object);
712
- #else
713
- #ifndef HAVE_RB_INTERN_STR
714
- /* MRI 1.8 doesn't have rb_intern_str or rb_intern2 */
715
- rb_hash_aset(top->object, ID2SYM(rb_intern(RSTRING_PTR(top->key))), uk->last_object);
716
- #else
717
- rb_hash_aset(top->object, ID2SYM(rb_intern_str(top->key)), uk->last_object);
718
- #endif
719
- #endif
720
745
  } else {
721
746
  rb_hash_aset(top->object, top->key, uk->last_object);
722
747
  }
@@ -754,7 +779,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
754
779
 
755
780
  container_completed:
756
781
  {
757
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
782
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
758
783
 
759
784
  /* this section optimized out */
760
785
  // TODO object_complete still creates objects which should be optimized out
@@ -21,12 +21,11 @@
21
21
  #include "buffer.h"
22
22
  #include "unpacker_ext_registry.h"
23
23
 
24
- #ifndef MSGPACK_UNPACKER_STACK_CAPACITY
25
24
  #define MSGPACK_UNPACKER_STACK_CAPACITY 128
26
- #endif
27
25
 
28
26
  struct msgpack_unpacker_t;
29
27
  typedef struct msgpack_unpacker_t msgpack_unpacker_t;
28
+ typedef struct msgpack_unpacker_stack_t msgpack_unpacker_stack_t;
30
29
 
31
30
  enum stack_type_t {
32
31
  STACK_TYPE_ARRAY,
@@ -39,19 +38,21 @@ typedef struct {
39
38
  enum stack_type_t type;
40
39
  VALUE object;
41
40
  VALUE key;
42
- } msgpack_unpacker_stack_t;
41
+ } msgpack_unpacker_stack_entry_t;
43
42
 
44
- #define MSGPACK_UNPACKER_STACK_SIZE (8+4+8+8) /* assumes size_t <= 64bit, enum <= 32bit, VALUE <= 64bit */
43
+ struct msgpack_unpacker_stack_t {
44
+ size_t depth;
45
+ size_t capacity;
46
+ msgpack_unpacker_stack_entry_t *data;
47
+ msgpack_unpacker_stack_t *parent;
48
+ };
45
49
 
46
50
  struct msgpack_unpacker_t {
47
51
  msgpack_buffer_t buffer;
48
-
52
+ msgpack_unpacker_stack_t *stack;
49
53
  unsigned int head_byte;
50
54
 
51
- msgpack_unpacker_stack_t* stack;
52
- size_t stack_depth;
53
- size_t stack_capacity;
54
-
55
+ VALUE self;
55
56
  VALUE last_object;
56
57
 
57
58
  VALUE reading_raw;
@@ -60,12 +61,14 @@ struct msgpack_unpacker_t {
60
61
 
61
62
  VALUE buffer_ref;
62
63
 
63
- msgpack_unpacker_ext_registry_t ext_registry;
64
+ msgpack_unpacker_ext_registry_t *ext_registry;
64
65
 
65
66
  /* options */
66
67
  bool symbolize_keys;
67
68
  bool freeze;
68
69
  bool allow_unknown_ext;
70
+ bool optimized_symbol_ext_type;
71
+ int symbol_ext_type;
69
72
  };
70
73
 
71
74
  #define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
@@ -80,11 +83,11 @@ enum msgpack_unpacker_object_type {
80
83
  TYPE_MAP,
81
84
  };
82
85
 
83
- void msgpack_unpacker_static_init();
86
+ void msgpack_unpacker_static_init(void);
84
87
 
85
- void msgpack_unpacker_static_destroy();
88
+ void msgpack_unpacker_static_destroy(void);
86
89
 
87
- void _msgpack_unpacker_init(msgpack_unpacker_t* uk);
90
+ void _msgpack_unpacker_init(msgpack_unpacker_t*);
88
91
 
89
92
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk);
90
93