msgpack 1.2.10 → 1.5.1

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +57 -0
  3. data/.gitignore +3 -1
  4. data/.rubocop.yml +4 -1
  5. data/ChangeLog +60 -0
  6. data/Gemfile +3 -0
  7. data/README.md +264 -0
  8. data/Rakefile +1 -9
  9. data/doclib/msgpack/factory.rb +47 -3
  10. data/doclib/msgpack/packer.rb +5 -4
  11. data/doclib/msgpack/time.rb +22 -0
  12. data/doclib/msgpack/timestamp.rb +44 -0
  13. data/doclib/msgpack/unpacker.rb +2 -2
  14. data/ext/java/org/msgpack/jruby/Buffer.java +23 -16
  15. data/ext/java/org/msgpack/jruby/Decoder.java +46 -23
  16. data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
  17. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +37 -49
  18. data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
  19. data/ext/java/org/msgpack/jruby/Factory.java +47 -7
  20. data/ext/java/org/msgpack/jruby/Packer.java +29 -17
  21. data/ext/java/org/msgpack/jruby/Unpacker.java +72 -37
  22. data/ext/msgpack/buffer.c +4 -16
  23. data/ext/msgpack/buffer.h +46 -5
  24. data/ext/msgpack/buffer_class.c +23 -15
  25. data/ext/msgpack/compat.h +1 -12
  26. data/ext/msgpack/extconf.rb +39 -7
  27. data/ext/msgpack/factory_class.c +87 -20
  28. data/ext/msgpack/packer.c +58 -8
  29. data/ext/msgpack/packer.h +24 -16
  30. data/ext/msgpack/packer_class.c +29 -31
  31. data/ext/msgpack/packer_ext_registry.c +22 -30
  32. data/ext/msgpack/packer_ext_registry.h +38 -31
  33. data/ext/msgpack/unpacker.c +102 -70
  34. data/ext/msgpack/unpacker.h +10 -2
  35. data/ext/msgpack/unpacker_class.c +35 -52
  36. data/ext/msgpack/unpacker_ext_registry.c +40 -16
  37. data/ext/msgpack/unpacker_ext_registry.h +21 -14
  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 +29 -0
  42. data/lib/msgpack/timestamp.rb +76 -0
  43. data/lib/msgpack/version.rb +4 -7
  44. data/lib/msgpack.rb +8 -12
  45. data/msgpack.gemspec +3 -7
  46. data/spec/bigint_spec.rb +26 -0
  47. data/spec/factory_spec.rb +299 -12
  48. data/spec/msgpack_spec.rb +1 -1
  49. data/spec/packer_spec.rb +18 -0
  50. data/spec/spec_helper.rb +30 -3
  51. data/spec/timestamp_spec.rb +159 -0
  52. data/spec/unpacker_spec.rb +135 -4
  53. metadata +21 -51
  54. data/.travis.yml +0 -43
  55. data/README.rdoc +0 -209
@@ -30,8 +30,8 @@ void msgpack_packer_ext_registry_static_destroy()
30
30
 
31
31
  void msgpack_packer_ext_registry_init(msgpack_packer_ext_registry_t* pkrg)
32
32
  {
33
- pkrg->hash = rb_hash_new();
34
- pkrg->cache = rb_hash_new();
33
+ pkrg->hash = Qnil;
34
+ pkrg->cache = Qnil;
35
35
  }
36
36
 
37
37
  void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
@@ -43,37 +43,29 @@ void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
43
43
  void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
44
44
  msgpack_packer_ext_registry_t* dst)
45
45
  {
46
- #ifdef HAVE_RB_HASH_DUP
47
- dst->hash = rb_hash_dup(src->hash);
48
- dst->cache = rb_hash_dup(src->cache);
49
- #else
50
- dst->hash = rb_funcall(src->hash, rb_intern("dup"), 0);
51
- dst->cache = rb_funcall(src->cache, rb_intern("dup"), 0);
52
- #endif
53
- }
54
-
55
- #ifndef HAVE_RB_HASH_CLEAR
56
-
57
- static int
58
- __rb_hash_clear_clear_i(key, value, dummy)
59
- VALUE key, value, dummy;
60
- {
61
- return ST_DELETE;
46
+ if(RTEST(src->hash) && !rb_obj_frozen_p(src->hash)) {
47
+ dst->hash = rb_hash_dup(src->hash);
48
+ dst->cache = RTEST(src->cache) ? rb_hash_dup(src->cache) : Qnil;
49
+ } else {
50
+ // If the type registry is frozen we can safely share it, and share the cache as well.
51
+ dst->hash = src->hash;
52
+ dst->cache = src->cache;
53
+ }
62
54
  }
63
55
 
64
- #endif
65
-
66
56
  VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
67
- VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
57
+ VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
68
58
  {
69
- VALUE e = rb_ary_new3(3, INT2FIX(ext_type), proc, arg);
70
- /* clear lookup cache not to miss added type */
71
- #ifdef HAVE_RB_HASH_CLEAR
72
- rb_hash_clear(pkrg->cache);
73
- #else
74
- if(FIX2INT(rb_funcall(pkrg->cache, rb_intern("size"), 0)) > 0) {
75
- rb_hash_foreach(pkrg->cache, __rb_hash_clear_clear_i, 0);
59
+ if (!RTEST(pkrg->hash)) {
60
+ pkrg->hash = rb_hash_new();
61
+ }
62
+
63
+ if (RTEST(pkrg->cache)) {
64
+ /* clear lookup cache not to miss added type */
65
+ rb_hash_clear(pkrg->cache);
76
66
  }
77
- #endif
78
- return rb_hash_aset(pkrg->hash, ext_module, e);
67
+
68
+ // TODO: Ruby embeded array limit is 3, merging `proc` and `arg` would be good.
69
+ VALUE entry = rb_ary_new3(4, INT2FIX(ext_type), proc, arg, INT2FIX(flags));
70
+ return rb_hash_aset(pkrg->hash, ext_module, entry);
79
71
  }
@@ -21,6 +21,8 @@
21
21
  #include "compat.h"
22
22
  #include "ruby.h"
23
23
 
24
+ #define MSGPACK_EXT_RECURSIVE 0b0001
25
+
24
26
  struct msgpack_packer_ext_registry_t;
25
27
  typedef struct msgpack_packer_ext_registry_t msgpack_packer_ext_registry_t;
26
28
 
@@ -44,7 +46,7 @@ void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
44
46
  msgpack_packer_ext_registry_t* dst);
45
47
 
46
48
  VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
47
- VALUE ext_module, int ext_type, VALUE proc, VALUE arg);
49
+ VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
48
50
 
49
51
  static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
50
52
  {
@@ -60,59 +62,60 @@ static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
60
62
  }
61
63
 
62
64
  static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registry_t* pkrg,
63
- VALUE lookup_class, int* ext_type_result)
65
+ VALUE lookup_class, int* ext_type_result, int* ext_flags_result)
64
66
  {
65
67
  // fetch lookup_class from hash, which is a hash to register classes
66
68
  VALUE type = rb_hash_lookup(pkrg->hash, lookup_class);
67
69
  if(type != Qnil) {
68
70
  *ext_type_result = FIX2INT(rb_ary_entry(type, 0));
71
+ *ext_flags_result = FIX2INT(rb_ary_entry(type, 3));
69
72
  return rb_ary_entry(type, 1);
70
73
  }
71
74
 
72
75
  // fetch lookup_class from cache, which stores results of searching ancestors from pkrg->hash
73
- VALUE type_inht = rb_hash_lookup(pkrg->cache, lookup_class);
74
- if(type_inht != Qnil) {
75
- *ext_type_result = FIX2INT(rb_ary_entry(type_inht, 0));
76
- return rb_ary_entry(type_inht, 1);
76
+ if (RTEST(pkrg->cache)) {
77
+ VALUE type_inht = rb_hash_lookup(pkrg->cache, lookup_class);
78
+ if(type_inht != Qnil) {
79
+ *ext_type_result = FIX2INT(rb_ary_entry(type_inht, 0));
80
+ *ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 3));
81
+ return rb_ary_entry(type_inht, 1);
82
+ }
77
83
  }
78
84
 
79
85
  return Qnil;
80
86
  }
81
87
 
82
88
  static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_registry_t* pkrg,
83
- VALUE instance, int* ext_type_result)
89
+ VALUE instance, int* ext_type_result, int* ext_flags_result)
84
90
  {
85
- VALUE lookup_class;
86
91
  VALUE type;
87
92
 
88
- /*
89
- * 1. check whether singleton_class of this instance is registered (or resolved in past) or not.
90
- *
91
- * Objects of type Integer (Fixnum, Bignum), Float, Symbol and frozen
92
- * String have no singleton class and raise a TypeError when trying to get
93
- * it. See implementation of #singleton_class in ruby's source code:
94
- * VALUE rb_singleton_class(VALUE obj);
95
- *
96
- * Since all but symbols are already filtered out when reaching this code
97
- * only symbols are checked here.
98
- */
99
- if (!SYMBOL_P(instance)) {
100
- lookup_class = rb_singleton_class(instance);
101
-
102
- type = msgpack_packer_ext_registry_fetch(pkrg, lookup_class, ext_type_result);
93
+ if (pkrg->hash == Qnil) { // No extensions registered
94
+ return Qnil;
95
+ }
103
96
 
104
- if(type != Qnil) {
105
- return type;
106
- }
97
+ /*
98
+ * 1. check whether singleton_class or class of this instance is registered (or resolved in past) or not.
99
+ *
100
+ * Objects of type Integer (Fixnum, Bignum), Float, Symbol and frozen
101
+ * `rb_class_of` returns the singleton_class if the object has one, or the "real class" otherwise.
102
+ */
103
+ VALUE lookup_class = rb_class_of(instance);
104
+ type = msgpack_packer_ext_registry_fetch(pkrg, lookup_class, ext_type_result, ext_flags_result);
105
+ if(type != Qnil) {
106
+ return type;
107
107
  }
108
108
 
109
109
  /*
110
- * 2. check the class of instance is registered (or resolved in past) or not.
110
+ * 2. If the object had a singleton_class check if the real class of instance is registered
111
+ * (or resolved in past) or not.
111
112
  */
112
- type = msgpack_packer_ext_registry_fetch(pkrg, rb_obj_class(instance), ext_type_result);
113
-
114
- if(type != Qnil) {
115
- return type;
113
+ VALUE real_class = rb_obj_class(instance);
114
+ if(lookup_class != real_class) {
115
+ type = msgpack_packer_ext_registry_fetch(pkrg, real_class, ext_type_result, ext_flags_result);
116
+ if(type != Qnil) {
117
+ return type;
118
+ }
116
119
  }
117
120
 
118
121
  /*
@@ -126,8 +129,12 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
126
129
  VALUE superclass = args[1];
127
130
  if(superclass != Qnil) {
128
131
  VALUE superclass_type = rb_hash_lookup(pkrg->hash, superclass);
132
+ if (!RTEST(pkrg->cache)) {
133
+ pkrg->cache = rb_hash_new();
134
+ }
129
135
  rb_hash_aset(pkrg->cache, lookup_class, superclass_type);
130
136
  *ext_type_result = FIX2INT(rb_ary_entry(superclass_type, 0));
137
+ *ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 3));
131
138
  return rb_ary_entry(superclass_type, 1);
132
139
  }
133
140
 
@@ -52,9 +52,19 @@ void msgpack_unpacker_static_destroy()
52
52
 
53
53
  #define HEAD_BYTE_REQUIRED 0xc1
54
54
 
55
- void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
55
+ static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
56
+ #ifdef UNPACKER_STACK_RMEM
57
+ return msgpack_rmem_alloc(&s_stack_rmem);
58
+ /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
59
+ #else
60
+ /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
61
+ return xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
62
+ #endif
63
+ }
64
+
65
+ msgpack_unpacker_t* _msgpack_unpacker_new(void)
56
66
  {
57
- memset(uk, 0, sizeof(msgpack_unpacker_t));
67
+ msgpack_unpacker_t* uk = ZALLOC_N(msgpack_unpacker_t, 1);
58
68
 
59
69
  msgpack_buffer_init(UNPACKER_BUFFER_(uk));
60
70
 
@@ -63,24 +73,23 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
63
73
  uk->last_object = Qnil;
64
74
  uk->reading_raw = Qnil;
65
75
 
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
76
+ uk->stack = _msgpack_unpacker_new_stack();
73
77
  uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
78
+
79
+ return uk;
80
+ }
81
+
82
+ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
83
+ #ifdef UNPACKER_STACK_RMEM
84
+ msgpack_rmem_free(&s_stack_rmem, stack);
85
+ #else
86
+ xfree(stack);
87
+ #endif
74
88
  }
75
89
 
76
90
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
77
91
  {
78
- #ifdef UNPACKER_STACK_RMEM
79
- msgpack_rmem_free(&s_stack_rmem, uk->stack);
80
- #else
81
- xfree(uk->stack);
82
- #endif
83
-
92
+ _msgpack_unpacker_free_stack(uk->stack);
84
93
  msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
85
94
  }
86
95
 
@@ -142,41 +151,39 @@ static inline void reset_head_byte(msgpack_unpacker_t* uk)
142
151
 
143
152
  static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
144
153
  {
154
+ if(uk->freeze) {
155
+ rb_obj_freeze(object);
156
+ }
157
+
145
158
  uk->last_object = object;
146
159
  reset_head_byte(uk);
147
160
  return PRIMITIVE_OBJECT_COMPLETE;
148
161
  }
149
162
 
150
- static inline int object_complete_string(msgpack_unpacker_t* uk, VALUE str)
163
+ static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
151
164
  {
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)
159
- {
160
- #ifdef COMPAT_HAVE_ENCODING
161
- ENCODING_SET(str, msgpack_rb_encindex_ascii8bit);
162
- #endif
163
- return object_complete(uk, str);
165
+ uk->last_object = object;
166
+ reset_head_byte(uk);
167
+ return PRIMITIVE_OBJECT_COMPLETE;
164
168
  }
165
169
 
166
170
  static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
167
171
  {
168
- #ifdef COMPAT_HAVE_ENCODING
169
- ENCODING_SET(str, msgpack_rb_encindex_ascii8bit);
170
- #endif
172
+ if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
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
+ obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
175
182
  return object_complete(uk, obj);
176
183
  }
177
184
 
178
185
  if(uk->allow_unknown_ext) {
179
- VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
186
+ VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
180
187
  return object_complete(uk, obj);
181
188
  }
182
189
 
@@ -271,9 +278,10 @@ static int read_raw_body_cont(msgpack_unpacker_t* uk)
271
278
 
272
279
  int ret;
273
280
  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);
281
+ ENCODING_SET(uk->reading_raw, msgpack_rb_encindex_utf8);
282
+ ret = object_complete(uk, uk->reading_raw);
283
+ } else if (uk->reading_raw_type == RAW_TYPE_BINARY) {
284
+ ret = object_complete(uk, uk->reading_raw);
277
285
  } else {
278
286
  ret = object_complete_ext(uk, uk->reading_raw_type, uk->reading_raw);
279
287
  }
@@ -285,23 +293,57 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
285
293
  {
286
294
  /* assuming uk->reading_raw == Qnil */
287
295
 
296
+ int ext_flags;
297
+ VALUE proc;
298
+
299
+ if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
300
+ proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
301
+ if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
302
+ VALUE obj;
303
+ uk->last_object = Qnil;
304
+ reset_head_byte(uk);
305
+ size_t ext_size = uk->reading_raw_remaining;
306
+ uk->reading_raw_remaining = 0;
307
+
308
+ msgpack_unpacker_stack_t* stack = uk->stack;
309
+ size_t stack_depth = uk->stack_depth;
310
+ size_t stack_capacity = uk->stack_capacity;
311
+
312
+ uk->stack = _msgpack_unpacker_new_stack();
313
+ uk->stack_depth = 0;
314
+ uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
315
+
316
+ obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
317
+
318
+ _msgpack_unpacker_free_stack(uk->stack);
319
+ uk->stack = stack;
320
+ uk->stack_depth = stack_depth;
321
+ uk->stack_capacity = stack_capacity;
322
+
323
+ msgpack_buffer_skip(UNPACKER_BUFFER_(uk), ext_size);
324
+ return object_complete(uk, obj);
325
+ }
326
+ }
327
+
288
328
  /* try optimized read */
289
329
  size_t length = uk->reading_raw_remaining;
290
330
  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
331
  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);
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);
300
335
  } else {
301
- ret = object_complete_ext(uk, raw_type, string);
302
- }
303
- if(will_freeze) {
304
- 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
+ }
305
347
  }
306
348
  uk->reading_raw_remaining = 0;
307
349
  return ret;
@@ -332,7 +374,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
332
374
  SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
333
375
  int count = b & 0x1f;
334
376
  if(count == 0) {
335
- return object_complete_string(uk, rb_str_buf_new(0));
377
+ return object_complete(uk, rb_utf8_str_new_static("", 0));
336
378
  }
337
379
  /* read_raw_body_begin sets uk->reading_raw */
338
380
  uk->reading_raw_remaining = count;
@@ -371,7 +413,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
371
413
  uint8_t length = cb->u8;
372
414
  int ext_type = (signed char) cb->buffer[1];
373
415
  if(length == 0) {
374
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
416
+ return object_complete_ext(uk, ext_type, Qnil);
375
417
  }
376
418
  uk->reading_raw_remaining = length;
377
419
  return read_raw_body_begin(uk, ext_type);
@@ -383,7 +425,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
383
425
  uint16_t length = _msgpack_be16(cb->u16);
384
426
  int ext_type = (signed char) cb->buffer[2];
385
427
  if(length == 0) {
386
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
428
+ return object_complete_ext(uk, ext_type, Qnil);
387
429
  }
388
430
  uk->reading_raw_remaining = length;
389
431
  return read_raw_body_begin(uk, ext_type);
@@ -395,7 +437,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
395
437
  uint32_t length = _msgpack_be32(cb->u32);
396
438
  int ext_type = (signed char) cb->buffer[4];
397
439
  if(length == 0) {
398
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
440
+ return object_complete_ext(uk, ext_type, Qnil);
399
441
  }
400
442
  uk->reading_raw_remaining = length;
401
443
  return read_raw_body_begin(uk, ext_type);
@@ -517,7 +559,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
517
559
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
518
560
  uint8_t count = cb->u8;
519
561
  if(count == 0) {
520
- return object_complete_string(uk, rb_str_buf_new(0));
562
+ return object_complete(uk, rb_utf8_str_new_static("", 0));
521
563
  }
522
564
  /* read_raw_body_begin sets uk->reading_raw */
523
565
  uk->reading_raw_remaining = count;
@@ -529,7 +571,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
529
571
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
530
572
  uint16_t count = _msgpack_be16(cb->u16);
531
573
  if(count == 0) {
532
- return object_complete_string(uk, rb_str_buf_new(0));
574
+ return object_complete(uk, rb_utf8_str_new_static("", 0));
533
575
  }
534
576
  /* read_raw_body_begin sets uk->reading_raw */
535
577
  uk->reading_raw_remaining = count;
@@ -541,7 +583,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
541
583
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
542
584
  uint32_t count = _msgpack_be32(cb->u32);
543
585
  if(count == 0) {
544
- return object_complete_string(uk, rb_str_buf_new(0));
586
+ return object_complete(uk, rb_utf8_str_new_static("", 0));
545
587
  }
546
588
  /* read_raw_body_begin sets uk->reading_raw */
547
589
  uk->reading_raw_remaining = count;
@@ -553,7 +595,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
553
595
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
554
596
  uint8_t count = cb->u8;
555
597
  if(count == 0) {
556
- return object_complete_binary(uk, rb_str_buf_new(0));
598
+ return object_complete(uk, rb_str_new_static("", 0));
557
599
  }
558
600
  /* read_raw_body_begin sets uk->reading_raw */
559
601
  uk->reading_raw_remaining = count;
@@ -565,7 +607,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
565
607
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
566
608
  uint16_t count = _msgpack_be16(cb->u16);
567
609
  if(count == 0) {
568
- return object_complete_binary(uk, rb_str_buf_new(0));
610
+ return object_complete(uk, rb_str_new_static("", 0));
569
611
  }
570
612
  /* read_raw_body_begin sets uk->reading_raw */
571
613
  uk->reading_raw_remaining = count;
@@ -577,7 +619,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
577
619
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
578
620
  uint32_t count = _msgpack_be32(cb->u32);
579
621
  if(count == 0) {
580
- return object_complete_binary(uk, rb_str_buf_new(0));
622
+ return object_complete(uk, rb_str_new_static("", 0));
581
623
  }
582
624
  /* read_raw_body_begin sets uk->reading_raw */
583
625
  uk->reading_raw_remaining = count;
@@ -719,18 +761,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
719
761
  break;
720
762
  case STACK_TYPE_MAP_VALUE:
721
763
  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 */
764
+ /* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
725
765
  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
766
  } else {
735
767
  rb_hash_aset(top->object, top->key, uk->last_object);
736
768
  }
@@ -60,11 +60,14 @@ struct msgpack_unpacker_t {
60
60
 
61
61
  VALUE buffer_ref;
62
62
 
63
- msgpack_unpacker_ext_registry_t ext_registry;
63
+ msgpack_unpacker_ext_registry_t *ext_registry;
64
64
 
65
65
  /* options */
66
66
  bool symbolize_keys;
67
+ bool freeze;
67
68
  bool allow_unknown_ext;
69
+ bool optimized_symbol_ext_type;
70
+ int symbol_ext_type;
68
71
  };
69
72
 
70
73
  #define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
@@ -83,7 +86,7 @@ void msgpack_unpacker_static_init();
83
86
 
84
87
  void msgpack_unpacker_static_destroy();
85
88
 
86
- void _msgpack_unpacker_init(msgpack_unpacker_t* uk);
89
+ msgpack_unpacker_t* _msgpack_unpacker_new(void);
87
90
 
88
91
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk);
89
92
 
@@ -96,6 +99,11 @@ static inline void msgpack_unpacker_set_symbolized_keys(msgpack_unpacker_t* uk,
96
99
  uk->symbolize_keys = enable;
97
100
  }
98
101
 
102
+ static inline void msgpack_unpacker_set_freeze(msgpack_unpacker_t* uk, bool enable)
103
+ {
104
+ uk->freeze = enable;
105
+ }
106
+
99
107
  static inline void msgpack_unpacker_set_allow_unknown_ext(msgpack_unpacker_t* uk, bool enable)
100
108
  {
101
109
  uk->allow_unknown_ext = enable;