msgpack 1.4.4 → 1.5.1

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