msgpack 1.4.2 → 1.7.3

Sign up to get free protection for your applications and to get access to all the features.
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