msgpack 1.3.3 → 1.7.2

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