msgpack 1.4.4 → 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.
@@ -28,6 +28,8 @@ VALUE cMessagePack_Packer;
28
28
  static ID s_to_msgpack;
29
29
  static ID s_write;
30
30
 
31
+ static VALUE sym_compatibility_mode;
32
+
31
33
  //static VALUE s_packer_value;
32
34
  //static msgpack_packer_t* s_packer;
33
35
 
@@ -68,29 +70,28 @@ VALUE MessagePack_Packer_alloc(VALUE klass)
68
70
 
69
71
  VALUE MessagePack_Packer_initialize(int argc, VALUE* argv, VALUE self)
70
72
  {
73
+ if(argc > 2) {
74
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
75
+ }
76
+
71
77
  VALUE io = Qnil;
72
78
  VALUE options = Qnil;
73
79
 
74
- if(argc == 0 || (argc == 1 && argv[0] == Qnil)) {
75
- /* Qnil */
76
-
77
- } else if(argc == 1) {
78
- VALUE v = argv[0];
79
- if(rb_type(v) == T_HASH) {
80
- options = v;
81
- } else {
82
- io = v;
83
- }
84
-
85
- } else if(argc == 2) {
80
+ if(argc >= 1) {
86
81
  io = argv[0];
82
+ }
83
+
84
+ if(argc == 2) {
87
85
  options = argv[1];
88
- if(rb_type(options) != T_HASH) {
89
- rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
90
- }
86
+ }
91
87
 
92
- } else {
93
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
88
+ if (options == Qnil && rb_type(io) == T_HASH) {
89
+ options = io;
90
+ io = Qnil;
91
+ }
92
+
93
+ if(options != Qnil) {
94
+ Check_Type(options, T_HASH);
94
95
  }
95
96
 
96
97
  PACKER(self, pk);
@@ -103,7 +104,7 @@ VALUE MessagePack_Packer_initialize(int argc, VALUE* argv, VALUE self)
103
104
  if(options != Qnil) {
104
105
  VALUE v;
105
106
 
106
- v = rb_hash_aref(options, ID2SYM(rb_intern("compatibility_mode")));
107
+ v = rb_hash_aref(options, sym_compatibility_mode);
107
108
  msgpack_packer_set_compat(pk, RTEST(v));
108
109
  }
109
110
 
@@ -281,7 +282,7 @@ static VALUE Packer_flush(VALUE self)
281
282
  return self;
282
283
  }
283
284
 
284
- static VALUE Packer_clear(VALUE self)
285
+ static VALUE Packer_reset(VALUE self)
285
286
  {
286
287
  PACKER(self, pk);
287
288
  msgpack_buffer_clear(PACKER_BUFFER_(pk));
@@ -339,7 +340,10 @@ static VALUE Packer_write_to(VALUE self, VALUE io)
339
340
  static VALUE Packer_registered_types_internal(VALUE self)
340
341
  {
341
342
  PACKER(self, pk);
342
- return rb_hash_dup(pk->ext_registry.hash);
343
+ if (RTEST(pk->ext_registry.hash)) {
344
+ return rb_hash_dup(pk->ext_registry.hash);
345
+ }
346
+ return rb_hash_new();
343
347
  }
344
348
 
345
349
  static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
@@ -377,7 +381,7 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
377
381
  rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
378
382
  }
379
383
 
380
- msgpack_packer_ext_registry_put(&pk->ext_registry, ext_module, ext_type, proc, arg);
384
+ msgpack_packer_ext_registry_put(&pk->ext_registry, ext_module, ext_type, 0, proc, arg);
381
385
 
382
386
  if (ext_module == rb_cSymbol) {
383
387
  pk->has_symbol_ext_type = true;
@@ -409,6 +413,8 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
409
413
  s_to_msgpack = rb_intern("to_msgpack");
410
414
  s_write = rb_intern("write");
411
415
 
416
+ sym_compatibility_mode = ID2SYM(rb_intern("compatibility_mode"));
417
+
412
418
  msgpack_packer_static_init();
413
419
  msgpack_packer_ext_registry_static_init();
414
420
 
@@ -440,7 +446,8 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
440
446
  rb_define_method(cMessagePack_Packer, "flush", Packer_flush, 0);
441
447
 
442
448
  /* delegation methods */
443
- rb_define_method(cMessagePack_Packer, "clear", Packer_clear, 0);
449
+ rb_define_method(cMessagePack_Packer, "reset", Packer_reset, 0);
450
+ rb_define_alias(cMessagePack_Packer, "clear", "reset");
444
451
  rb_define_method(cMessagePack_Packer, "size", Packer_size, 0);
445
452
  rb_define_method(cMessagePack_Packer, "empty?", Packer_empty_p, 0);
446
453
  rb_define_method(cMessagePack_Packer, "write_to", Packer_write_to, 1);
@@ -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,15 +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
- dst->hash = rb_hash_dup(src->hash);
47
- dst->cache = rb_hash_dup(src->cache);
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
+ }
48
54
  }
49
55
 
50
56
  VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
51
- VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
57
+ VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
52
58
  {
53
- VALUE e = rb_ary_new3(3, INT2FIX(ext_type), proc, arg);
54
- /* clear lookup cache not to miss added type */
55
- rb_hash_clear(pkrg->cache);
56
- return rb_hash_aset(pkrg->hash, ext_module, e);
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);
66
+ }
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);
57
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
 
@@ -164,14 +173,17 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
164
173
  return object_complete_symbol(uk, rb_str_intern(str));
165
174
  }
166
175
 
167
- VALUE proc = msgpack_unpacker_ext_registry_lookup(&uk->ext_registry, ext_type);
176
+ int ext_flags;
177
+ VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
178
+
168
179
  if(proc != Qnil) {
169
- 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);
170
182
  return object_complete(uk, obj);
171
183
  }
172
184
 
173
185
  if(uk->allow_unknown_ext) {
174
- VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
186
+ VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
175
187
  return object_complete(uk, obj);
176
188
  }
177
189
 
@@ -281,29 +293,57 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
281
293
  {
282
294
  /* assuming uk->reading_raw == Qnil */
283
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
+
284
328
  /* try optimized read */
285
329
  size_t length = uk->reading_raw_remaining;
286
330
  if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
287
331
  int ret;
288
332
  if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
289
- VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length);
333
+ VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
290
334
  ret = object_complete_symbol(uk, symbol);
291
335
  } else {
292
- /* don't use zerocopy for hash keys but get a frozen string directly
293
- * because rb_hash_aset freezes keys and it causes copying */
294
- bool will_freeze = uk->freeze || is_reading_map_key(uk);
295
- VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
336
+ bool will_freeze = uk->freeze;
296
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);
297
342
  ret = object_complete(uk, string);
298
343
  } else {
344
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, false, false);
299
345
  ret = object_complete_ext(uk, raw_type, string);
300
346
  }
301
-
302
- # if !HASH_ASET_DEDUPE
303
- if(will_freeze) {
304
- rb_obj_freeze(string);
305
- }
306
- # endif
307
347
  }
308
348
  uk->reading_raw_remaining = 0;
309
349
  return ret;
@@ -373,7 +413,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
373
413
  uint8_t length = cb->u8;
374
414
  int ext_type = (signed char) cb->buffer[1];
375
415
  if(length == 0) {
376
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
416
+ return object_complete_ext(uk, ext_type, Qnil);
377
417
  }
378
418
  uk->reading_raw_remaining = length;
379
419
  return read_raw_body_begin(uk, ext_type);
@@ -385,7 +425,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
385
425
  uint16_t length = _msgpack_be16(cb->u16);
386
426
  int ext_type = (signed char) cb->buffer[2];
387
427
  if(length == 0) {
388
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
428
+ return object_complete_ext(uk, ext_type, Qnil);
389
429
  }
390
430
  uk->reading_raw_remaining = length;
391
431
  return read_raw_body_begin(uk, ext_type);
@@ -397,7 +437,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
397
437
  uint32_t length = _msgpack_be32(cb->u32);
398
438
  int ext_type = (signed char) cb->buffer[4];
399
439
  if(length == 0) {
400
- return object_complete_ext(uk, ext_type, rb_str_buf_new(0));
440
+ return object_complete_ext(uk, ext_type, Qnil);
401
441
  }
402
442
  uk->reading_raw_remaining = length;
403
443
  return read_raw_body_begin(uk, ext_type);
@@ -60,7 +60,7 @@ 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;
@@ -86,7 +86,7 @@ void msgpack_unpacker_static_init();
86
86
 
87
87
  void msgpack_unpacker_static_destroy();
88
88
 
89
- void _msgpack_unpacker_init(msgpack_unpacker_t* uk);
89
+ msgpack_unpacker_t* _msgpack_unpacker_new(void);
90
90
 
91
91
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk);
92
92
 
@@ -33,6 +33,10 @@ static VALUE eUnexpectedTypeError;
33
33
  static VALUE eUnknownExtTypeError;
34
34
  static VALUE mTypeError; // obsoleted. only for backward compatibility. See #86.
35
35
 
36
+ static VALUE sym_symbolize_keys;
37
+ static VALUE sym_freeze;
38
+ static VALUE sym_allow_unknown_ext;
39
+
36
40
  #define UNPACKER(from, name) \
37
41
  msgpack_unpacker_t *name = NULL; \
38
42
  Data_Get_Struct(from, msgpack_unpacker_t, name); \
@@ -45,7 +49,7 @@ static void Unpacker_free(msgpack_unpacker_t* uk)
45
49
  if(uk == NULL) {
46
50
  return;
47
51
  }
48
- msgpack_unpacker_ext_registry_destroy(&uk->ext_registry);
52
+ msgpack_unpacker_ext_registry_release(uk->ext_registry);
49
53
  _msgpack_unpacker_destroy(uk);
50
54
  xfree(uk);
51
55
  }
@@ -53,13 +57,12 @@ static void Unpacker_free(msgpack_unpacker_t* uk)
53
57
  static void Unpacker_mark(msgpack_unpacker_t* uk)
54
58
  {
55
59
  msgpack_unpacker_mark(uk);
56
- msgpack_unpacker_ext_registry_mark(&uk->ext_registry);
60
+ msgpack_unpacker_ext_registry_mark(uk->ext_registry);
57
61
  }
58
62
 
59
63
  VALUE MessagePack_Unpacker_alloc(VALUE klass)
60
64
  {
61
- msgpack_unpacker_t* uk = ZALLOC_N(msgpack_unpacker_t, 1);
62
- _msgpack_unpacker_init(uk);
65
+ msgpack_unpacker_t* uk = _msgpack_unpacker_new();
63
66
 
64
67
  VALUE self = Data_Wrap_Struct(klass, Unpacker_mark, Unpacker_free, uk);
65
68
  return self;
@@ -84,7 +87,7 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
84
87
  } else if(argc == 2) {
85
88
  io = argv[0];
86
89
  options = argv[1];
87
- if(rb_type(options) != T_HASH) {
90
+ if(options != Qnil && rb_type(options) != T_HASH) {
88
91
  rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
89
92
  }
90
93
 
@@ -94,7 +97,6 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
94
97
 
95
98
  UNPACKER(self, uk);
96
99
 
97
- msgpack_unpacker_ext_registry_init(&uk->ext_registry);
98
100
  uk->buffer_ref = MessagePack_Buffer_wrap(UNPACKER_BUFFER_(uk), self);
99
101
 
100
102
  MessagePack_Buffer_set_options(UNPACKER_BUFFER_(uk), io, options);
@@ -102,13 +104,13 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
102
104
  if(options != Qnil) {
103
105
  VALUE v;
104
106
 
105
- v = rb_hash_aref(options, ID2SYM(rb_intern("symbolize_keys")));
107
+ v = rb_hash_aref(options, sym_symbolize_keys);
106
108
  msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
107
109
 
108
- v = rb_hash_aref(options, ID2SYM(rb_intern("freeze")));
110
+ v = rb_hash_aref(options, sym_freeze);
109
111
  msgpack_unpacker_set_freeze(uk, RTEST(v));
110
112
 
111
- v = rb_hash_aref(options, ID2SYM(rb_intern("allow_unknown_ext")));
113
+ v = rb_hash_aref(options, sym_allow_unknown_ext);
112
114
  msgpack_unpacker_set_allow_unknown_ext(uk, RTEST(v));
113
115
  }
114
116
 
@@ -133,7 +135,7 @@ static VALUE Unpacker_allow_unknown_ext_p(VALUE self)
133
135
  return uk->allow_unknown_ext ? Qtrue : Qfalse;
134
136
  }
135
137
 
136
- static void raise_unpacker_error(int r)
138
+ NORETURN(static void raise_unpacker_error(int r))
137
139
  {
138
140
  switch(r) {
139
141
  case PRIMITIVE_EOF:
@@ -145,6 +147,7 @@ static void raise_unpacker_error(int r)
145
147
  case PRIMITIVE_UNEXPECTED_TYPE:
146
148
  rb_raise(eUnexpectedTypeError, "unexpected type");
147
149
  case PRIMITIVE_UNEXPECTED_EXT_TYPE:
150
+ // rb_bug("unexpected extension type");
148
151
  rb_raise(eUnknownExtTypeError, "unexpected extension type");
149
152
  default:
150
153
  rb_raise(eUnpackError, "logically unknown error %d", r);
@@ -222,34 +225,6 @@ static VALUE Unpacker_read_map_header(VALUE self)
222
225
  return ULONG2NUM(size);
223
226
  }
224
227
 
225
- static VALUE Unpacker_peek_next_type(VALUE self)
226
- {
227
- UNPACKER(self, uk);
228
-
229
- int r = msgpack_unpacker_peek_next_object_type(uk);
230
- if(r < 0) {
231
- raise_unpacker_error(r);
232
- }
233
-
234
- switch((enum msgpack_unpacker_object_type) r) {
235
- case TYPE_NIL:
236
- return rb_intern("nil");
237
- case TYPE_BOOLEAN:
238
- return rb_intern("boolean");
239
- case TYPE_INTEGER:
240
- return rb_intern("integer");
241
- case TYPE_FLOAT:
242
- return rb_intern("float");
243
- case TYPE_RAW:
244
- return rb_intern("raw");
245
- case TYPE_ARRAY:
246
- return rb_intern("array");
247
- case TYPE_MAP:
248
- return rb_intern("map");
249
- default:
250
- rb_raise(eUnpackError, "logically unknown type %d", r);
251
- }
252
- }
253
228
 
254
229
  static VALUE Unpacker_feed(VALUE self, VALUE data)
255
230
  {
@@ -296,9 +271,10 @@ static VALUE Unpacker_each_impl(VALUE self)
296
271
  }
297
272
  }
298
273
 
299
- static VALUE Unpacker_rescue_EOFError(VALUE self)
274
+ static VALUE Unpacker_rescue_EOFError(VALUE args, VALUE error)
300
275
  {
301
- UNUSED(self);
276
+ UNUSED(args);
277
+ UNUSED(error);
302
278
  return Qnil;
303
279
  }
304
280
 
@@ -347,9 +323,11 @@ static VALUE Unpacker_registered_types_internal(VALUE self)
347
323
  UNPACKER(self, uk);
348
324
 
349
325
  VALUE mapping = rb_hash_new();
350
- for(int i=0; i < 256; i++) {
351
- if(uk->ext_registry.array[i] != Qnil) {
352
- rb_hash_aset(mapping, INT2FIX(i - 128), uk->ext_registry.array[i]);
326
+ if (uk->ext_registry) {
327
+ for(int i=0; i < 256; i++) {
328
+ if(uk->ext_registry->array[i] != Qnil) {
329
+ rb_hash_aset(mapping, INT2FIX(i - 128), uk->ext_registry->array[i]);
330
+ }
353
331
  }
354
332
  }
355
333
 
@@ -388,7 +366,7 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
388
366
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
389
367
  }
390
368
 
391
- msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, proc, arg);
369
+ msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, 0, proc, arg);
392
370
 
393
371
  return Qnil;
394
372
  }
@@ -438,6 +416,10 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
438
416
 
439
417
  eUnknownExtTypeError = rb_define_class_under(mMessagePack, "UnknownExtTypeError", eUnpackError);
440
418
 
419
+ sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
420
+ sym_freeze = ID2SYM(rb_intern("freeze"));
421
+ sym_allow_unknown_ext = ID2SYM(rb_intern("allow_unknown_ext"));
422
+
441
423
  rb_define_alloc_func(cMessagePack_Unpacker, MessagePack_Unpacker_alloc);
442
424
 
443
425
  rb_define_method(cMessagePack_Unpacker, "initialize", MessagePack_Unpacker_initialize, -1);
@@ -451,7 +433,6 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
451
433
  rb_define_method(cMessagePack_Unpacker, "skip_nil", Unpacker_skip_nil, 0);
452
434
  rb_define_method(cMessagePack_Unpacker, "read_array_header", Unpacker_read_array_header, 0);
453
435
  rb_define_method(cMessagePack_Unpacker, "read_map_header", Unpacker_read_map_header, 0);
454
- //rb_define_method(cMessagePack_Unpacker, "peek_next_type", Unpacker_peek_next_type, 0); // TODO
455
436
  rb_define_method(cMessagePack_Unpacker, "feed", Unpacker_feed, 1);
456
437
  rb_define_method(cMessagePack_Unpacker, "feed_reference", Unpacker_feed_reference, 1);
457
438
  rb_define_method(cMessagePack_Unpacker, "each", Unpacker_each, 0);