msgpack 1.4.2 → 1.6.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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +57 -0
  3. data/ChangeLog +60 -0
  4. data/README.md +25 -1
  5. data/Rakefile +1 -2
  6. data/bench/bench.rb +78 -0
  7. data/bin/console +8 -0
  8. data/doclib/msgpack/factory.rb +47 -3
  9. data/doclib/msgpack/packer.rb +5 -4
  10. data/doclib/msgpack/unpacker.rb +2 -2
  11. data/ext/java/org/msgpack/jruby/Buffer.java +23 -16
  12. data/ext/java/org/msgpack/jruby/Decoder.java +29 -21
  13. data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
  14. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +37 -49
  15. data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
  16. data/ext/java/org/msgpack/jruby/Factory.java +47 -7
  17. data/ext/java/org/msgpack/jruby/Packer.java +29 -17
  18. data/ext/java/org/msgpack/jruby/Unpacker.java +66 -42
  19. data/ext/msgpack/buffer.c +38 -57
  20. data/ext/msgpack/buffer.h +19 -10
  21. data/ext/msgpack/buffer_class.c +90 -52
  22. data/ext/msgpack/compat.h +0 -99
  23. data/ext/msgpack/extconf.rb +9 -22
  24. data/ext/msgpack/factory_class.c +133 -43
  25. data/ext/msgpack/packer.c +60 -36
  26. data/ext/msgpack/packer.h +27 -18
  27. data/ext/msgpack/packer_class.c +84 -77
  28. data/ext/msgpack/packer_class.h +11 -0
  29. data/ext/msgpack/packer_ext_registry.c +24 -32
  30. data/ext/msgpack/packer_ext_registry.h +40 -33
  31. data/ext/msgpack/sysdep.h +5 -2
  32. data/ext/msgpack/unpacker.c +128 -97
  33. data/ext/msgpack/unpacker.h +17 -10
  34. data/ext/msgpack/unpacker_class.c +75 -80
  35. data/ext/msgpack/unpacker_class.h +11 -0
  36. data/ext/msgpack/unpacker_ext_registry.c +42 -18
  37. data/ext/msgpack/unpacker_ext_registry.h +23 -16
  38. data/lib/msgpack/bigint.rb +69 -0
  39. data/lib/msgpack/factory.rb +103 -0
  40. data/lib/msgpack/symbol.rb +21 -4
  41. data/lib/msgpack/time.rb +1 -1
  42. data/lib/msgpack/version.rb +1 -1
  43. data/lib/msgpack.rb +5 -7
  44. data/msgpack.gemspec +2 -2
  45. data/spec/bigint_spec.rb +26 -0
  46. data/spec/cruby/buffer_spec.rb +17 -0
  47. data/spec/factory_spec.rb +351 -12
  48. data/spec/msgpack_spec.rb +1 -1
  49. data/spec/packer_spec.rb +18 -0
  50. data/spec/spec_helper.rb +20 -3
  51. data/spec/timestamp_spec.rb +38 -0
  52. data/spec/unpacker_spec.rb +54 -4
  53. metadata +25 -41
  54. data/.travis.yml +0 -39
  55. data/bench/pack.rb +0 -23
  56. data/bench/pack_log.rb +0 -33
  57. data/bench/pack_log_long.rb +0 -65
  58. data/bench/pack_symbols.rb +0 -28
  59. data/bench/run.sh +0 -14
  60. data/bench/run_long.sh +0 -35
  61. data/bench/run_symbols.sh +0 -26
  62. data/bench/unpack.rb +0 -21
  63. data/bench/unpack_log.rb +0 -34
  64. data/bench/unpack_log_long.rb +0 -67
@@ -20,7 +20,7 @@
20
20
  #include "rmem.h"
21
21
  #include "extension_value_class.h"
22
22
 
23
- #if !defined(DISABLE_RMEM) && !defined(DISABLE_UNPACKER_STACK_RMEM) && \
23
+ #if !defined(DISABLE_UNPACKER_STACK_RMEM) && \
24
24
  MSGPACK_UNPACKER_STACK_CAPACITY * MSGPACK_UNPACKER_STACK_SIZE <= MSGPACK_RMEM_PAGE_SIZE
25
25
  #define UNPACKER_STACK_RMEM
26
26
  #endif
@@ -34,7 +34,14 @@ static ID s_call;
34
34
  static msgpack_rmem_t s_stack_rmem;
35
35
  #endif
36
36
 
37
- void msgpack_unpacker_static_init()
37
+ #if !defined(HAVE_RB_HASH_NEW_CAPA)
38
+ static inline VALUE rb_hash_new_capa(long capa)
39
+ {
40
+ return rb_hash_new();
41
+ }
42
+ #endif
43
+
44
+ void msgpack_unpacker_static_init(void)
38
45
  {
39
46
  #ifdef UNPACKER_STACK_RMEM
40
47
  msgpack_rmem_init(&s_stack_rmem);
@@ -43,7 +50,7 @@ void msgpack_unpacker_static_init()
43
50
  s_call = rb_intern("call");
44
51
  }
45
52
 
46
- void msgpack_unpacker_static_destroy()
53
+ void msgpack_unpacker_static_destroy(void)
47
54
  {
48
55
  #ifdef UNPACKER_STACK_RMEM
49
56
  msgpack_rmem_destroy(&s_stack_rmem);
@@ -52,10 +59,21 @@ void msgpack_unpacker_static_destroy()
52
59
 
53
60
  #define HEAD_BYTE_REQUIRED 0xc1
54
61
 
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;
73
+ }
74
+
55
75
  void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
56
76
  {
57
- memset(uk, 0, sizeof(msgpack_unpacker_t));
58
-
59
77
  msgpack_buffer_init(UNPACKER_BUFFER_(uk));
60
78
 
61
79
  uk->head_byte = HEAD_BYTE_REQUIRED;
@@ -63,39 +81,42 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
63
81
  uk->last_object = Qnil;
64
82
  uk->reading_raw = Qnil;
65
83
 
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;
84
+ uk->stack = _msgpack_unpacker_new_stack();
85
+ }
86
+
87
+ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
88
+ #ifdef UNPACKER_STACK_RMEM
89
+ msgpack_rmem_free(&s_stack_rmem, stack->data);
90
+ #else
91
+ xfree(stack->data);
92
+ #endif
93
+ xfree(stack);
74
94
  }
75
95
 
76
96
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
77
97
  {
78
- #ifdef UNPACKER_STACK_RMEM
79
- msgpack_rmem_free(&s_stack_rmem, uk->stack);
80
- #else
81
- xfree(uk->stack);
82
- #endif
83
-
98
+ _msgpack_unpacker_free_stack(uk->stack);
84
99
  msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
85
100
  }
86
101
 
102
+ void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
103
+ {
104
+ while (stack) {
105
+ msgpack_unpacker_stack_entry_t* s = stack->data;
106
+ msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
107
+ for(; s < send; s++) {
108
+ rb_gc_mark(s->object);
109
+ rb_gc_mark(s->key);
110
+ }
111
+ stack = stack->parent;
112
+ }
113
+ }
114
+
87
115
  void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
88
116
  {
89
117
  rb_gc_mark(uk->last_object);
90
118
  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
-
119
+ msgpack_unpacker_mark_stack(uk->stack);
99
120
  /* See MessagePack_Buffer_wrap */
100
121
  /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
101
122
  rb_gc_mark(uk->buffer_ref);
@@ -107,9 +128,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
107
128
 
108
129
  uk->head_byte = HEAD_BYTE_REQUIRED;
109
130
 
110
- /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack_depth);*/
111
- uk->stack_depth = 0;
112
-
131
+ /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
132
+ uk->stack->depth = 0;
113
133
  uk->last_object = Qnil;
114
134
  uk->reading_raw = Qnil;
115
135
  uk->reading_raw_remaining = 0;
@@ -151,16 +171,33 @@ static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
151
171
  return PRIMITIVE_OBJECT_COMPLETE;
152
172
  }
153
173
 
174
+ static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
175
+ {
176
+ uk->last_object = object;
177
+ reset_head_byte(uk);
178
+ return PRIMITIVE_OBJECT_COMPLETE;
179
+ }
180
+
154
181
  static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
155
182
  {
156
- VALUE proc = msgpack_unpacker_ext_registry_lookup(&uk->ext_registry, ext_type);
183
+ if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
184
+ if (RB_UNLIKELY(NIL_P(str))) { // empty extension is returned as Qnil
185
+ return object_complete_symbol(uk, ID2SYM(rb_intern3("", 0, rb_utf8_encoding())));
186
+ }
187
+ return object_complete_symbol(uk, rb_str_intern(str));
188
+ }
189
+
190
+ int ext_flags;
191
+ VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
192
+
157
193
  if(proc != Qnil) {
158
- VALUE obj = rb_funcall(proc, s_call, 1, str);
194
+ VALUE obj;
195
+ obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
159
196
  return object_complete(uk, obj);
160
197
  }
161
198
 
162
199
  if(uk->allow_unknown_ext) {
163
- VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
200
+ VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
164
201
  return object_complete(uk, obj);
165
202
  }
166
203
 
@@ -168,37 +205,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
168
205
  }
169
206
 
170
207
  /* stack funcs */
171
- static inline msgpack_unpacker_stack_t* _msgpack_unpacker_stack_top(msgpack_unpacker_t* uk)
208
+ static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
172
209
  {
173
- return &uk->stack[uk->stack_depth-1];
210
+ return &uk->stack->data[uk->stack->depth-1];
174
211
  }
175
212
 
176
213
  static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
177
214
  {
178
215
  reset_head_byte(uk);
179
216
 
180
- if(uk->stack_capacity - uk->stack_depth <= 0) {
217
+ if(uk->stack->capacity - uk->stack->depth <= 0) {
181
218
  return PRIMITIVE_STACK_TOO_DEEP;
182
219
  }
183
220
 
184
- msgpack_unpacker_stack_t* next = &uk->stack[uk->stack_depth];
221
+ msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
185
222
  next->count = count;
186
223
  next->type = type;
187
224
  next->object = object;
188
225
  next->key = Qnil;
189
226
 
190
- uk->stack_depth++;
227
+ uk->stack->depth++;
191
228
  return PRIMITIVE_CONTAINER_START;
192
229
  }
193
230
 
194
231
  static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
195
232
  {
196
- return --uk->stack_depth;
233
+ return --uk->stack->depth;
197
234
  }
198
235
 
199
236
  static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
200
237
  {
201
- return uk->stack_depth == 0;
238
+ return uk->stack->depth == 0;
202
239
  }
203
240
 
204
241
  #ifdef USE_CASE_RANGE
@@ -226,8 +263,8 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
226
263
 
227
264
  static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
228
265
  {
229
- if(uk->stack_depth > 0) {
230
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
266
+ if(uk->stack->depth > 0) {
267
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
231
268
  if(top->type == STACK_TYPE_MAP_KEY) {
232
269
  return true;
233
270
  }
@@ -270,25 +307,50 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
270
307
  {
271
308
  /* assuming uk->reading_raw == Qnil */
272
309
 
310
+ int ext_flags;
311
+ VALUE proc;
312
+
313
+ if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
314
+ proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
315
+ if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
316
+ VALUE obj;
317
+ uk->last_object = Qnil;
318
+ reset_head_byte(uk);
319
+ uk->reading_raw_remaining = 0;
320
+
321
+ msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
322
+ child_stack->parent = uk->stack;
323
+ uk->stack = child_stack;
324
+
325
+ obj = rb_funcall(proc, s_call, 1, uk->self);
326
+
327
+ uk->stack = child_stack->parent;
328
+ _msgpack_unpacker_free_stack(child_stack);
329
+
330
+ return object_complete(uk, obj);
331
+ }
332
+ }
333
+
273
334
  /* try optimized read */
274
335
  size_t length = uk->reading_raw_remaining;
275
336
  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
337
  int ret;
281
- if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
282
- ret = object_complete(uk, string);
338
+ if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
339
+ VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
340
+ ret = object_complete_symbol(uk, symbol);
283
341
  } 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);
342
+ bool will_freeze = uk->freeze;
343
+ if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
344
+ /* don't use zerocopy for hash keys but get a frozen string directly
345
+ * because rb_hash_aset freezes keys and it causes copying */
346
+ will_freeze = will_freeze || is_reading_map_key(uk);
347
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
348
+ ret = object_complete(uk, string);
349
+ } else {
350
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, false, false);
351
+ ret = object_complete_ext(uk, raw_type, string);
352
+ }
290
353
  }
291
- # endif
292
354
  uk->reading_raw_remaining = 0;
293
355
  return ret;
294
356
  }
@@ -317,9 +379,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
317
379
 
318
380
  SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
319
381
  int count = b & 0x1f;
320
- if(count == 0) {
321
- return object_complete(uk, rb_utf8_str_new_static("", 0));
322
- }
323
382
  /* read_raw_body_begin sets uk->reading_raw */
324
383
  uk->reading_raw_remaining = count;
325
384
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -336,7 +395,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
336
395
  if(count == 0) {
337
396
  return object_complete(uk, rb_hash_new());
338
397
  }
339
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
398
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
340
399
 
341
400
  SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
342
401
  switch(b) {
@@ -357,7 +416,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
357
416
  uint8_t length = cb->u8;
358
417
  int ext_type = (signed char) cb->buffer[1];
359
418
  if(length == 0) {
360
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
419
+ return object_complete_ext(uk, ext_type, Qnil);
361
420
  }
362
421
  uk->reading_raw_remaining = length;
363
422
  return read_raw_body_begin(uk, ext_type);
@@ -369,7 +428,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
369
428
  uint16_t length = _msgpack_be16(cb->u16);
370
429
  int ext_type = (signed char) cb->buffer[2];
371
430
  if(length == 0) {
372
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
431
+ return object_complete_ext(uk, ext_type, Qnil);
373
432
  }
374
433
  uk->reading_raw_remaining = length;
375
434
  return read_raw_body_begin(uk, ext_type);
@@ -381,7 +440,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
381
440
  uint32_t length = _msgpack_be32(cb->u32);
382
441
  int ext_type = (signed char) cb->buffer[4];
383
442
  if(length == 0) {
384
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
443
+ return object_complete_ext(uk, ext_type, Qnil);
385
444
  }
386
445
  uk->reading_raw_remaining = length;
387
446
  return read_raw_body_begin(uk, ext_type);
@@ -419,7 +478,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
419
478
  {
420
479
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
421
480
  uint32_t u32 = _msgpack_be32(cb->u32);
422
- return object_complete(uk, ULONG2NUM((unsigned long)u32));
481
+ return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
423
482
  }
424
483
 
425
484
  case 0xcf: // unsigned int 64
@@ -447,7 +506,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
447
506
  {
448
507
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
449
508
  int32_t i32 = _msgpack_be32(cb->i32);
450
- return object_complete(uk, LONG2NUM((long)i32));
509
+ return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
451
510
  }
452
511
 
453
512
  case 0xd3: // signed int 64
@@ -502,9 +561,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
502
561
  {
503
562
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
504
563
  uint8_t count = cb->u8;
505
- if(count == 0) {
506
- return object_complete(uk, rb_utf8_str_new_static("", 0));
507
- }
508
564
  /* read_raw_body_begin sets uk->reading_raw */
509
565
  uk->reading_raw_remaining = count;
510
566
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -514,9 +570,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
514
570
  {
515
571
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
516
572
  uint16_t count = _msgpack_be16(cb->u16);
517
- if(count == 0) {
518
- return object_complete(uk, rb_utf8_str_new_static("", 0));
519
- }
520
573
  /* read_raw_body_begin sets uk->reading_raw */
521
574
  uk->reading_raw_remaining = count;
522
575
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -526,9 +579,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
526
579
  {
527
580
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
528
581
  uint32_t count = _msgpack_be32(cb->u32);
529
- if(count == 0) {
530
- return object_complete(uk, rb_utf8_str_new_static("", 0));
531
- }
532
582
  /* read_raw_body_begin sets uk->reading_raw */
533
583
  uk->reading_raw_remaining = count;
534
584
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -538,9 +588,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
538
588
  {
539
589
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
540
590
  uint8_t count = cb->u8;
541
- if(count == 0) {
542
- return object_complete(uk, rb_str_new_static("", 0));
543
- }
544
591
  /* read_raw_body_begin sets uk->reading_raw */
545
592
  uk->reading_raw_remaining = count;
546
593
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -550,9 +597,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
550
597
  {
551
598
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
552
599
  uint16_t count = _msgpack_be16(cb->u16);
553
- if(count == 0) {
554
- return object_complete(uk, rb_str_new_static("", 0));
555
- }
556
600
  /* read_raw_body_begin sets uk->reading_raw */
557
601
  uk->reading_raw_remaining = count;
558
602
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -562,9 +606,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
562
606
  {
563
607
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
564
608
  uint32_t count = _msgpack_be32(cb->u32);
565
- if(count == 0) {
566
- return object_complete(uk, rb_str_new_static("", 0));
567
- }
568
609
  /* read_raw_body_begin sets uk->reading_raw */
569
610
  uk->reading_raw_remaining = count;
570
611
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -597,7 +638,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
597
638
  if(count == 0) {
598
639
  return object_complete(uk, rb_hash_new());
599
640
  }
600
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
641
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
601
642
  }
602
643
 
603
644
  case 0xdf: // map 32
@@ -607,7 +648,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
607
648
  if(count == 0) {
608
649
  return object_complete(uk, rb_hash_new());
609
650
  }
610
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
651
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
611
652
  }
612
653
 
613
654
  default:
@@ -694,7 +735,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
694
735
 
695
736
  container_completed:
696
737
  {
697
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
738
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
698
739
  switch(top->type) {
699
740
  case STACK_TYPE_ARRAY:
700
741
  rb_ary_push(top->object, uk->last_object);
@@ -705,18 +746,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
705
746
  break;
706
747
  case STACK_TYPE_MAP_VALUE:
707
748
  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 */
749
+ /* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
711
750
  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
751
  } else {
721
752
  rb_hash_aset(top->object, top->key, uk->last_object);
722
753
  }
@@ -754,7 +785,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
754
785
 
755
786
  container_completed:
756
787
  {
757
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
788
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
758
789
 
759
790
  /* this section optimized out */
760
791
  // TODO object_complete still creates objects which should be optimized out
@@ -27,6 +27,7 @@
27
27
 
28
28
  struct msgpack_unpacker_t;
29
29
  typedef struct msgpack_unpacker_t msgpack_unpacker_t;
30
+ typedef struct msgpack_unpacker_stack_t msgpack_unpacker_stack_t;
30
31
 
31
32
  enum stack_type_t {
32
33
  STACK_TYPE_ARRAY,
@@ -39,19 +40,23 @@ typedef struct {
39
40
  enum stack_type_t type;
40
41
  VALUE object;
41
42
  VALUE key;
42
- } msgpack_unpacker_stack_t;
43
+ } msgpack_unpacker_stack_entry_t;
44
+
45
+ struct msgpack_unpacker_stack_t {
46
+ size_t depth;
47
+ size_t capacity;
48
+ msgpack_unpacker_stack_entry_t *data;
49
+ msgpack_unpacker_stack_t *parent;
50
+ };
43
51
 
44
52
  #define MSGPACK_UNPACKER_STACK_SIZE (8+4+8+8) /* assumes size_t <= 64bit, enum <= 32bit, VALUE <= 64bit */
45
53
 
46
54
  struct msgpack_unpacker_t {
47
55
  msgpack_buffer_t buffer;
48
-
56
+ msgpack_unpacker_stack_t *stack;
49
57
  unsigned int head_byte;
50
58
 
51
- msgpack_unpacker_stack_t* stack;
52
- size_t stack_depth;
53
- size_t stack_capacity;
54
-
59
+ VALUE self;
55
60
  VALUE last_object;
56
61
 
57
62
  VALUE reading_raw;
@@ -60,12 +65,14 @@ struct msgpack_unpacker_t {
60
65
 
61
66
  VALUE buffer_ref;
62
67
 
63
- msgpack_unpacker_ext_registry_t ext_registry;
68
+ msgpack_unpacker_ext_registry_t *ext_registry;
64
69
 
65
70
  /* options */
66
71
  bool symbolize_keys;
67
72
  bool freeze;
68
73
  bool allow_unknown_ext;
74
+ bool optimized_symbol_ext_type;
75
+ int symbol_ext_type;
69
76
  };
70
77
 
71
78
  #define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
@@ -80,11 +87,11 @@ enum msgpack_unpacker_object_type {
80
87
  TYPE_MAP,
81
88
  };
82
89
 
83
- void msgpack_unpacker_static_init();
90
+ void msgpack_unpacker_static_init(void);
84
91
 
85
- void msgpack_unpacker_static_destroy();
92
+ void msgpack_unpacker_static_destroy(void);
86
93
 
87
- void _msgpack_unpacker_init(msgpack_unpacker_t* uk);
94
+ void _msgpack_unpacker_init(msgpack_unpacker_t*);
88
95
 
89
96
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk);
90
97