msgpack 1.3.3 → 1.7.2

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +99 -0
  3. data/README.md +293 -0
  4. data/ext/java/org/msgpack/jruby/Buffer.java +26 -19
  5. data/ext/java/org/msgpack/jruby/Decoder.java +46 -23
  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 +86 -68
  12. data/ext/msgpack/buffer.c +58 -85
  13. data/ext/msgpack/buffer.h +59 -20
  14. data/ext/msgpack/buffer_class.c +161 -52
  15. data/ext/msgpack/buffer_class.h +1 -0
  16. data/ext/msgpack/compat.h +1 -111
  17. data/ext/msgpack/extconf.rb +41 -23
  18. data/ext/msgpack/factory_class.c +143 -87
  19. data/ext/msgpack/packer.c +66 -43
  20. data/ext/msgpack/packer.h +25 -27
  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 +130 -126
  29. data/ext/msgpack/unpacker.h +22 -13
  30. data/ext/msgpack/unpacker_class.c +94 -124
  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 +4 -8
  42. data/lib/msgpack.rb +7 -12
  43. data/msgpack.gemspec +9 -8
  44. metadata +37 -96
  45. data/.gitignore +0 -23
  46. data/.rubocop.yml +0 -36
  47. data/.travis.yml +0 -43
  48. data/Gemfile +0 -9
  49. data/README.rdoc +0 -225
  50. data/Rakefile +0 -78
  51. data/appveyor.yml +0 -18
  52. data/bench/pack.rb +0 -23
  53. data/bench/pack_log.rb +0 -33
  54. data/bench/pack_log_long.rb +0 -65
  55. data/bench/pack_symbols.rb +0 -28
  56. data/bench/run.sh +0 -14
  57. data/bench/run_long.sh +0 -35
  58. data/bench/run_symbols.sh +0 -26
  59. data/bench/unpack.rb +0 -21
  60. data/bench/unpack_log.rb +0 -34
  61. data/bench/unpack_log_long.rb +0 -67
  62. data/doclib/msgpack/buffer.rb +0 -193
  63. data/doclib/msgpack/core_ext.rb +0 -101
  64. data/doclib/msgpack/error.rb +0 -19
  65. data/doclib/msgpack/extension_value.rb +0 -9
  66. data/doclib/msgpack/factory.rb +0 -101
  67. data/doclib/msgpack/packer.rb +0 -208
  68. data/doclib/msgpack/time.rb +0 -22
  69. data/doclib/msgpack/timestamp.rb +0 -44
  70. data/doclib/msgpack/unpacker.rb +0 -183
  71. data/doclib/msgpack.rb +0 -87
  72. data/msgpack.org.md +0 -46
  73. data/spec/cases.json +0 -1
  74. data/spec/cases.msg +0 -0
  75. data/spec/cases_compact.msg +0 -0
  76. data/spec/cases_spec.rb +0 -39
  77. data/spec/cruby/buffer_io_spec.rb +0 -255
  78. data/spec/cruby/buffer_packer.rb +0 -29
  79. data/spec/cruby/buffer_spec.rb +0 -575
  80. data/spec/cruby/buffer_unpacker.rb +0 -19
  81. data/spec/cruby/unpacker_spec.rb +0 -70
  82. data/spec/ext_value_spec.rb +0 -99
  83. data/spec/exttypes.rb +0 -51
  84. data/spec/factory_spec.rb +0 -367
  85. data/spec/format_spec.rb +0 -301
  86. data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
  87. data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
  88. data/spec/jruby/unpacker_spec.rb +0 -186
  89. data/spec/msgpack_spec.rb +0 -214
  90. data/spec/pack_spec.rb +0 -61
  91. data/spec/packer_spec.rb +0 -557
  92. data/spec/random_compat.rb +0 -24
  93. data/spec/spec_helper.rb +0 -38
  94. data/spec/timestamp_spec.rb +0 -121
  95. data/spec/unpack_spec.rb +0 -57
  96. data/spec/unpacker_spec.rb +0 -716
@@ -19,43 +19,48 @@
19
19
  #include "unpacker.h"
20
20
  #include "rmem.h"
21
21
  #include "extension_value_class.h"
22
+ #include <assert.h>
22
23
 
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
24
+ #if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
25
+ #define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
26
26
  #endif
27
27
 
28
28
  static int RAW_TYPE_STRING = 256;
29
29
  static int RAW_TYPE_BINARY = 257;
30
30
 
31
- static ID s_call;
32
-
33
- #ifdef UNPACKER_STACK_RMEM
34
31
  static msgpack_rmem_t s_stack_rmem;
35
- #endif
36
32
 
37
- void msgpack_unpacker_static_init()
33
+ #if !defined(HAVE_RB_HASH_NEW_CAPA)
34
+ static inline VALUE rb_hash_new_capa(long capa)
38
35
  {
39
- #ifdef UNPACKER_STACK_RMEM
40
- msgpack_rmem_init(&s_stack_rmem);
36
+ return rb_hash_new();
37
+ }
41
38
  #endif
42
39
 
43
- s_call = rb_intern("call");
40
+ void msgpack_unpacker_static_init(void)
41
+ {
42
+ assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
43
+
44
+ msgpack_rmem_init(&s_stack_rmem);
44
45
  }
45
46
 
46
- void msgpack_unpacker_static_destroy()
47
+ void msgpack_unpacker_static_destroy(void)
47
48
  {
48
- #ifdef UNPACKER_STACK_RMEM
49
49
  msgpack_rmem_destroy(&s_stack_rmem);
50
- #endif
51
50
  }
52
51
 
53
52
  #define HEAD_BYTE_REQUIRED 0xc1
54
53
 
54
+ static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
55
+ msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
56
+ stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
57
+ stack->data = msgpack_rmem_alloc(&s_stack_rmem);
58
+ /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
59
+ return stack;
60
+ }
61
+
55
62
  void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
56
63
  {
57
- memset(uk, 0, sizeof(msgpack_unpacker_t));
58
-
59
64
  msgpack_buffer_init(UNPACKER_BUFFER_(uk));
60
65
 
61
66
  uk->head_byte = HEAD_BYTE_REQUIRED;
@@ -63,42 +68,44 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
63
68
  uk->last_object = Qnil;
64
69
  uk->reading_raw = Qnil;
65
70
 
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;
71
+ uk->stack = _msgpack_unpacker_new_stack();
72
+ }
73
+
74
+ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
75
+ if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
76
+ rb_bug("Failed to free an rmem pointer, memory leak?");
77
+ }
78
+ xfree(stack);
74
79
  }
75
80
 
76
81
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
77
82
  {
78
- #ifdef UNPACKER_STACK_RMEM
79
- msgpack_rmem_free(&s_stack_rmem, uk->stack);
80
- #else
81
- xfree(uk->stack);
82
- #endif
83
-
83
+ _msgpack_unpacker_free_stack(uk->stack);
84
84
  msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
85
85
  }
86
86
 
87
+ void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
88
+ {
89
+ while (stack) {
90
+ msgpack_unpacker_stack_entry_t* s = stack->data;
91
+ msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
92
+ for(; s < send; s++) {
93
+ rb_gc_mark(s->object);
94
+ rb_gc_mark(s->key);
95
+ }
96
+ stack = stack->parent;
97
+ }
98
+ }
99
+
87
100
  void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
88
101
  {
89
102
  rb_gc_mark(uk->last_object);
90
103
  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
-
104
+ msgpack_unpacker_mark_stack(uk->stack);
99
105
  /* See MessagePack_Buffer_wrap */
100
106
  /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
101
107
  rb_gc_mark(uk->buffer_ref);
108
+ rb_gc_mark(uk->self);
102
109
  }
103
110
 
104
111
  void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
@@ -107,9 +114,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
107
114
 
108
115
  uk->head_byte = HEAD_BYTE_REQUIRED;
109
116
 
110
- /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack_depth);*/
111
- uk->stack_depth = 0;
112
-
117
+ /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
118
+ uk->stack->depth = 0;
113
119
  uk->last_object = Qnil;
114
120
  uk->reading_raw = Qnil;
115
121
  uk->reading_raw_remaining = 0;
@@ -142,41 +148,43 @@ static inline void reset_head_byte(msgpack_unpacker_t* uk)
142
148
 
143
149
  static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
144
150
  {
151
+ if(uk->freeze) {
152
+ rb_obj_freeze(object);
153
+ }
154
+
145
155
  uk->last_object = object;
146
156
  reset_head_byte(uk);
147
157
  return PRIMITIVE_OBJECT_COMPLETE;
148
158
  }
149
159
 
150
- static inline int object_complete_string(msgpack_unpacker_t* uk, VALUE str)
151
- {
152
- #ifdef COMPAT_HAVE_ENCODING
153
- ENCODING_SET(str, msgpack_rb_encindex_utf8);
154
- #endif
155
- return object_complete(uk, str);
156
- }
157
-
158
- static inline int object_complete_binary(msgpack_unpacker_t* uk, VALUE str)
160
+ static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
159
161
  {
160
- #ifdef COMPAT_HAVE_ENCODING
161
- ENCODING_SET(str, msgpack_rb_encindex_ascii8bit);
162
- #endif
163
- return object_complete(uk, str);
162
+ uk->last_object = object;
163
+ reset_head_byte(uk);
164
+ return PRIMITIVE_OBJECT_COMPLETE;
164
165
  }
165
166
 
166
167
  static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
167
168
  {
168
- #ifdef COMPAT_HAVE_ENCODING
169
- ENCODING_SET(str, msgpack_rb_encindex_ascii8bit);
170
- #endif
169
+ if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
170
+ if (RB_UNLIKELY(NIL_P(str))) { // empty extension is returned as Qnil
171
+ return object_complete_symbol(uk, ID2SYM(rb_intern3("", 0, rb_utf8_encoding())));
172
+ }
173
+ return object_complete_symbol(uk, rb_str_intern(str));
174
+ }
175
+
176
+ int ext_flags;
177
+ VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
171
178
 
172
- VALUE proc = msgpack_unpacker_ext_registry_lookup(&uk->ext_registry, ext_type);
173
179
  if(proc != Qnil) {
174
- VALUE obj = rb_funcall(proc, s_call, 1, str);
180
+ VALUE obj;
181
+ VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
182
+ obj = rb_proc_call_with_block(proc, 1, &arg, Qnil);
175
183
  return object_complete(uk, obj);
176
184
  }
177
185
 
178
186
  if(uk->allow_unknown_ext) {
179
- VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
187
+ VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
180
188
  return object_complete(uk, obj);
181
189
  }
182
190
 
@@ -184,37 +192,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
184
192
  }
185
193
 
186
194
  /* stack funcs */
187
- static inline msgpack_unpacker_stack_t* _msgpack_unpacker_stack_top(msgpack_unpacker_t* uk)
195
+ static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
188
196
  {
189
- return &uk->stack[uk->stack_depth-1];
197
+ return &uk->stack->data[uk->stack->depth-1];
190
198
  }
191
199
 
192
200
  static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
193
201
  {
194
202
  reset_head_byte(uk);
195
203
 
196
- if(uk->stack_capacity - uk->stack_depth <= 0) {
204
+ if(uk->stack->capacity - uk->stack->depth <= 0) {
197
205
  return PRIMITIVE_STACK_TOO_DEEP;
198
206
  }
199
207
 
200
- msgpack_unpacker_stack_t* next = &uk->stack[uk->stack_depth];
208
+ msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
201
209
  next->count = count;
202
210
  next->type = type;
203
211
  next->object = object;
204
212
  next->key = Qnil;
205
213
 
206
- uk->stack_depth++;
214
+ uk->stack->depth++;
207
215
  return PRIMITIVE_CONTAINER_START;
208
216
  }
209
217
 
210
218
  static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
211
219
  {
212
- return --uk->stack_depth;
220
+ return --uk->stack->depth;
213
221
  }
214
222
 
215
223
  static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
216
224
  {
217
- return uk->stack_depth == 0;
225
+ return uk->stack->depth == 0;
218
226
  }
219
227
 
220
228
  #ifdef USE_CASE_RANGE
@@ -242,8 +250,8 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
242
250
 
243
251
  static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
244
252
  {
245
- if(uk->stack_depth > 0) {
246
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
253
+ if(uk->stack->depth > 0) {
254
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
247
255
  if(top->type == STACK_TYPE_MAP_KEY) {
248
256
  return true;
249
257
  }
@@ -271,9 +279,10 @@ static int read_raw_body_cont(msgpack_unpacker_t* uk)
271
279
 
272
280
  int ret;
273
281
  if(uk->reading_raw_type == RAW_TYPE_STRING) {
274
- ret = object_complete_string(uk, uk->reading_raw);
275
- } else if(uk->reading_raw_type == RAW_TYPE_BINARY) {
276
- ret = object_complete_binary(uk, uk->reading_raw);
282
+ ENCODING_SET(uk->reading_raw, msgpack_rb_encindex_utf8);
283
+ ret = object_complete(uk, uk->reading_raw);
284
+ } else if (uk->reading_raw_type == RAW_TYPE_BINARY) {
285
+ ret = object_complete(uk, uk->reading_raw);
277
286
  } else {
278
287
  ret = object_complete_ext(uk, uk->reading_raw_type, uk->reading_raw);
279
288
  }
@@ -285,23 +294,49 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
285
294
  {
286
295
  /* assuming uk->reading_raw == Qnil */
287
296
 
297
+ int ext_flags;
298
+ VALUE proc;
299
+
300
+ if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
301
+ proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
302
+ if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
303
+ VALUE obj;
304
+ uk->last_object = Qnil;
305
+ reset_head_byte(uk);
306
+ uk->reading_raw_remaining = 0;
307
+
308
+ msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
309
+ child_stack->parent = uk->stack;
310
+ uk->stack = child_stack;
311
+
312
+ obj = rb_proc_call_with_block(proc, 1, &uk->self, Qnil);
313
+
314
+ uk->stack = child_stack->parent;
315
+ _msgpack_unpacker_free_stack(child_stack);
316
+
317
+ return object_complete(uk, obj);
318
+ }
319
+ }
320
+
288
321
  /* try optimized read */
289
322
  size_t length = uk->reading_raw_remaining;
290
323
  if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
291
- /* don't use zerocopy for hash keys but get a frozen string directly
292
- * because rb_hash_aset freezes keys and it causes copying */
293
- bool will_freeze = is_reading_map_key(uk);
294
- VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze);
295
324
  int ret;
296
- if(raw_type == RAW_TYPE_STRING) {
297
- ret = object_complete_string(uk, string);
298
- } else if(raw_type == RAW_TYPE_BINARY) {
299
- ret = object_complete_binary(uk, string);
325
+ if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
326
+ VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
327
+ ret = object_complete_symbol(uk, symbol);
300
328
  } else {
301
- ret = object_complete_ext(uk, raw_type, string);
302
- }
303
- if(will_freeze) {
304
- rb_obj_freeze(string);
329
+ bool will_freeze = uk->freeze;
330
+ if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
331
+ /* don't use zerocopy for hash keys but get a frozen string directly
332
+ * because rb_hash_aset freezes keys and it causes copying */
333
+ will_freeze = will_freeze || is_reading_map_key(uk);
334
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
335
+ ret = object_complete(uk, string);
336
+ } else {
337
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, false, false);
338
+ ret = object_complete_ext(uk, raw_type, string);
339
+ }
305
340
  }
306
341
  uk->reading_raw_remaining = 0;
307
342
  return ret;
@@ -331,9 +366,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
331
366
 
332
367
  SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
333
368
  int count = b & 0x1f;
334
- if(count == 0) {
335
- return object_complete_string(uk, rb_str_buf_new(0));
336
- }
337
369
  /* read_raw_body_begin sets uk->reading_raw */
338
370
  uk->reading_raw_remaining = count;
339
371
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -350,7 +382,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
350
382
  if(count == 0) {
351
383
  return object_complete(uk, rb_hash_new());
352
384
  }
353
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
385
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
354
386
 
355
387
  SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
356
388
  switch(b) {
@@ -371,7 +403,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
371
403
  uint8_t length = cb->u8;
372
404
  int ext_type = (signed char) cb->buffer[1];
373
405
  if(length == 0) {
374
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
406
+ return object_complete_ext(uk, ext_type, Qnil);
375
407
  }
376
408
  uk->reading_raw_remaining = length;
377
409
  return read_raw_body_begin(uk, ext_type);
@@ -383,7 +415,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
383
415
  uint16_t length = _msgpack_be16(cb->u16);
384
416
  int ext_type = (signed char) cb->buffer[2];
385
417
  if(length == 0) {
386
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
418
+ return object_complete_ext(uk, ext_type, Qnil);
387
419
  }
388
420
  uk->reading_raw_remaining = length;
389
421
  return read_raw_body_begin(uk, ext_type);
@@ -395,7 +427,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
395
427
  uint32_t length = _msgpack_be32(cb->u32);
396
428
  int ext_type = (signed char) cb->buffer[4];
397
429
  if(length == 0) {
398
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
430
+ return object_complete_ext(uk, ext_type, Qnil);
399
431
  }
400
432
  uk->reading_raw_remaining = length;
401
433
  return read_raw_body_begin(uk, ext_type);
@@ -433,7 +465,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
433
465
  {
434
466
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
435
467
  uint32_t u32 = _msgpack_be32(cb->u32);
436
- return object_complete(uk, ULONG2NUM((unsigned long)u32));
468
+ return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
437
469
  }
438
470
 
439
471
  case 0xcf: // unsigned int 64
@@ -461,7 +493,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
461
493
  {
462
494
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
463
495
  int32_t i32 = _msgpack_be32(cb->i32);
464
- return object_complete(uk, LONG2NUM((long)i32));
496
+ return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
465
497
  }
466
498
 
467
499
  case 0xd3: // signed int 64
@@ -516,9 +548,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
516
548
  {
517
549
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
518
550
  uint8_t count = cb->u8;
519
- if(count == 0) {
520
- return object_complete_string(uk, rb_str_buf_new(0));
521
- }
522
551
  /* read_raw_body_begin sets uk->reading_raw */
523
552
  uk->reading_raw_remaining = count;
524
553
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -528,9 +557,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
528
557
  {
529
558
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
530
559
  uint16_t count = _msgpack_be16(cb->u16);
531
- if(count == 0) {
532
- return object_complete_string(uk, rb_str_buf_new(0));
533
- }
534
560
  /* read_raw_body_begin sets uk->reading_raw */
535
561
  uk->reading_raw_remaining = count;
536
562
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -540,9 +566,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
540
566
  {
541
567
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
542
568
  uint32_t count = _msgpack_be32(cb->u32);
543
- if(count == 0) {
544
- return object_complete_string(uk, rb_str_buf_new(0));
545
- }
546
569
  /* read_raw_body_begin sets uk->reading_raw */
547
570
  uk->reading_raw_remaining = count;
548
571
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -552,9 +575,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
552
575
  {
553
576
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
554
577
  uint8_t count = cb->u8;
555
- if(count == 0) {
556
- return object_complete_binary(uk, rb_str_buf_new(0));
557
- }
558
578
  /* read_raw_body_begin sets uk->reading_raw */
559
579
  uk->reading_raw_remaining = count;
560
580
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -564,9 +584,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
564
584
  {
565
585
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
566
586
  uint16_t count = _msgpack_be16(cb->u16);
567
- if(count == 0) {
568
- return object_complete_binary(uk, rb_str_buf_new(0));
569
- }
570
587
  /* read_raw_body_begin sets uk->reading_raw */
571
588
  uk->reading_raw_remaining = count;
572
589
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -576,9 +593,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
576
593
  {
577
594
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
578
595
  uint32_t count = _msgpack_be32(cb->u32);
579
- if(count == 0) {
580
- return object_complete_binary(uk, rb_str_buf_new(0));
581
- }
582
596
  /* read_raw_body_begin sets uk->reading_raw */
583
597
  uk->reading_raw_remaining = count;
584
598
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -611,7 +625,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
611
625
  if(count == 0) {
612
626
  return object_complete(uk, rb_hash_new());
613
627
  }
614
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
628
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
615
629
  }
616
630
 
617
631
  case 0xdf: // map 32
@@ -621,7 +635,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
621
635
  if(count == 0) {
622
636
  return object_complete(uk, rb_hash_new());
623
637
  }
624
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new());
638
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
625
639
  }
626
640
 
627
641
  default:
@@ -708,7 +722,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
708
722
 
709
723
  container_completed:
710
724
  {
711
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
725
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
712
726
  switch(top->type) {
713
727
  case STACK_TYPE_ARRAY:
714
728
  rb_ary_push(top->object, uk->last_object);
@@ -719,18 +733,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
719
733
  break;
720
734
  case STACK_TYPE_MAP_VALUE:
721
735
  if(uk->symbolize_keys && rb_type(top->key) == T_STRING) {
722
- /* here uses rb_intern_str instead of rb_intern so that Ruby VM can GC unused symbols */
723
- #ifdef HAVE_RB_STR_INTERN
724
- /* rb_str_intern is added since MRI 2.2.0 */
736
+ /* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
725
737
  rb_hash_aset(top->object, rb_str_intern(top->key), uk->last_object);
726
- #else
727
- #ifndef HAVE_RB_INTERN_STR
728
- /* MRI 1.8 doesn't have rb_intern_str or rb_intern2 */
729
- rb_hash_aset(top->object, ID2SYM(rb_intern(RSTRING_PTR(top->key))), uk->last_object);
730
- #else
731
- rb_hash_aset(top->object, ID2SYM(rb_intern_str(top->key)), uk->last_object);
732
- #endif
733
- #endif
734
738
  } else {
735
739
  rb_hash_aset(top->object, top->key, uk->last_object);
736
740
  }
@@ -768,7 +772,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
768
772
 
769
773
  container_completed:
770
774
  {
771
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
775
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
772
776
 
773
777
  /* this section optimized out */
774
778
  // 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,11 +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;
68
+ bool freeze;
67
69
  bool allow_unknown_ext;
70
+ bool optimized_symbol_ext_type;
71
+ int symbol_ext_type;
68
72
  };
69
73
 
70
74
  #define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
@@ -79,11 +83,11 @@ enum msgpack_unpacker_object_type {
79
83
  TYPE_MAP,
80
84
  };
81
85
 
82
- void msgpack_unpacker_static_init();
86
+ void msgpack_unpacker_static_init(void);
83
87
 
84
- void msgpack_unpacker_static_destroy();
88
+ void msgpack_unpacker_static_destroy(void);
85
89
 
86
- void _msgpack_unpacker_init(msgpack_unpacker_t* uk);
90
+ void _msgpack_unpacker_init(msgpack_unpacker_t*);
87
91
 
88
92
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk);
89
93
 
@@ -96,6 +100,11 @@ static inline void msgpack_unpacker_set_symbolized_keys(msgpack_unpacker_t* uk,
96
100
  uk->symbolize_keys = enable;
97
101
  }
98
102
 
103
+ static inline void msgpack_unpacker_set_freeze(msgpack_unpacker_t* uk, bool enable)
104
+ {
105
+ uk->freeze = enable;
106
+ }
107
+
99
108
  static inline void msgpack_unpacker_set_allow_unknown_ext(msgpack_unpacker_t* uk, bool enable)
100
109
  {
101
110
  uk->allow_unknown_ext = enable;