msgpack 1.7.1 → 1.7.3

Sign up to get free protection for your applications and to get access to all the features.
data/ext/msgpack/packer.c CHANGED
@@ -17,16 +17,11 @@
17
17
  */
18
18
 
19
19
  #include "packer.h"
20
+ #include "buffer_class.h"
20
21
 
21
- static ID s_call;
22
-
23
- void msgpack_packer_static_init(void)
24
- {
25
- s_call = rb_intern("call");
26
- }
27
-
28
- void msgpack_packer_static_destroy(void)
29
- { }
22
+ #if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
23
+ #define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
24
+ #endif
30
25
 
31
26
  void msgpack_packer_init(msgpack_packer_t* pk)
32
27
  {
@@ -100,14 +95,13 @@ struct msgpack_call_proc_args_t;
100
95
  typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
101
96
  struct msgpack_call_proc_args_t {
102
97
  VALUE proc;
103
- VALUE arg;
104
- VALUE packer;
98
+ VALUE args[2];
105
99
  };
106
100
 
107
101
  VALUE msgpack_packer_try_calling_proc(VALUE value)
108
102
  {
109
103
  msgpack_call_proc_args_t *args = (msgpack_call_proc_args_t *)value;
110
- return rb_funcall(args->proc, s_call, 2, args->arg, args->packer);
104
+ return rb_proc_call_with_block(args->proc, 2, args->args, Qnil);
111
105
  }
112
106
 
113
107
  bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
@@ -121,11 +115,13 @@ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v
121
115
  }
122
116
 
123
117
  if(ext_flags & MSGPACK_EXT_RECURSIVE) {
118
+ VALUE held_buffer = MessagePack_Buffer_hold(&pk->buffer);
119
+
124
120
  msgpack_buffer_t parent_buffer = pk->buffer;
125
121
  msgpack_buffer_init(PACKER_BUFFER_(pk));
126
122
 
127
123
  int exception_occured = 0;
128
- msgpack_call_proc_args_t args = { proc, v, pk->to_msgpack_arg };
124
+ msgpack_call_proc_args_t args = { proc, { v, pk->to_msgpack_arg } };
129
125
  rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
130
126
 
131
127
  if (exception_occured) {
@@ -139,8 +135,10 @@ bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v
139
135
  pk->buffer = parent_buffer;
140
136
  msgpack_packer_write_ext(pk, ext_type, payload);
141
137
  }
138
+
139
+ RB_GC_GUARD(held_buffer);
142
140
  } else {
143
- VALUE payload = rb_funcall(proc, s_call, 1, v);
141
+ VALUE payload = rb_proc_call_with_block(proc, 1, &v, Qnil);
144
142
  StringValue(payload);
145
143
  msgpack_packer_write_ext(pk, ext_type, payload);
146
144
  }
data/ext/msgpack/packer.h CHANGED
@@ -47,10 +47,6 @@ struct msgpack_packer_t {
47
47
 
48
48
  #define PACKER_BUFFER_(pk) (&(pk)->buffer)
49
49
 
50
- void msgpack_packer_static_init(void);
51
-
52
- void msgpack_packer_static_destroy(void);
53
-
54
50
  void msgpack_packer_init(msgpack_packer_t* pk);
55
51
 
56
52
  void msgpack_packer_destroy(msgpack_packer_t* pk);
@@ -106,8 +106,8 @@ VALUE MessagePack_Packer_initialize(int argc, VALUE* argv, VALUE self)
106
106
 
107
107
  msgpack_packer_t *pk = MessagePack_Packer_get(self);
108
108
 
109
- msgpack_packer_ext_registry_init(&pk->ext_registry);
110
- pk->buffer_ref = Qnil;
109
+ msgpack_packer_ext_registry_init(self, &pk->ext_registry);
110
+ pk->buffer_ref = MessagePack_Buffer_wrap(PACKER_BUFFER_(pk), self);
111
111
 
112
112
  MessagePack_Buffer_set_options(PACKER_BUFFER_(pk), io, options);
113
113
 
@@ -352,7 +352,7 @@ static VALUE Packer_registered_types_internal(VALUE self)
352
352
  return rb_hash_new();
353
353
  }
354
354
 
355
- static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
355
+ static VALUE Packer_register_type_internal(VALUE self, VALUE rb_ext_type, VALUE ext_module, VALUE proc)
356
356
  {
357
357
  if (OBJ_FROZEN(self)) {
358
358
  rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Packer");
@@ -360,38 +360,12 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
360
360
 
361
361
  msgpack_packer_t *pk = MessagePack_Packer_get(self);
362
362
 
363
- int ext_type;
364
- VALUE ext_module;
365
- VALUE proc;
366
- VALUE arg;
367
-
368
- switch (argc) {
369
- case 2:
370
- /* register_type(0x7f, Time) {|obj| block... } */
371
- rb_need_block();
372
- proc = rb_block_lambda();
373
- arg = proc;
374
- break;
375
- case 3:
376
- /* register_type(0x7f, Time, :to_msgpack_ext) */
377
- arg = argv[2];
378
- proc = rb_funcall(arg, rb_intern("to_proc"), 0);
379
- break;
380
- default:
381
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
382
- }
383
-
384
- ext_type = NUM2INT(argv[0]);
363
+ int ext_type = NUM2INT(rb_ext_type);
385
364
  if(ext_type < -128 || ext_type > 127) {
386
365
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
387
366
  }
388
367
 
389
- ext_module = argv[1];
390
- if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
391
- rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
392
- }
393
-
394
- msgpack_packer_ext_registry_put(&pk->ext_registry, ext_module, ext_type, 0, proc, arg);
368
+ msgpack_packer_ext_registry_put(self, &pk->ext_registry, ext_module, ext_type, 0, proc);
395
369
 
396
370
  if (ext_module == rb_cSymbol) {
397
371
  pk->has_symbol_ext_type = true;
@@ -424,10 +398,6 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
424
398
  s_write = rb_intern("write");
425
399
 
426
400
  sym_compatibility_mode = ID2SYM(rb_intern("compatibility_mode"));
427
-
428
- msgpack_packer_static_init();
429
- msgpack_packer_ext_registry_static_init();
430
-
431
401
  cMessagePack_Packer = rb_define_class_under(mMessagePack, "Packer", rb_cObject);
432
402
 
433
403
  rb_define_alloc_func(cMessagePack_Packer, MessagePack_Packer_alloc);
@@ -466,7 +436,7 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
466
436
  rb_define_method(cMessagePack_Packer, "to_a", Packer_to_a, 0);
467
437
 
468
438
  rb_define_private_method(cMessagePack_Packer, "registered_types_internal", Packer_registered_types_internal, 0);
469
- rb_define_method(cMessagePack_Packer, "register_type", Packer_register_type, -1);
439
+ rb_define_method(cMessagePack_Packer, "register_type_internal", Packer_register_type_internal, 3);
470
440
 
471
441
  rb_define_method(cMessagePack_Packer, "full_pack", Packer_full_pack, 0);
472
442
  }
@@ -18,20 +18,10 @@
18
18
 
19
19
  #include "packer_ext_registry.h"
20
20
 
21
- static ID s_call;
22
-
23
- void msgpack_packer_ext_registry_static_init(void)
24
- {
25
- s_call = rb_intern("call");
26
- }
27
-
28
- void msgpack_packer_ext_registry_static_destroy(void)
29
- { }
30
-
31
- void msgpack_packer_ext_registry_init(msgpack_packer_ext_registry_t* pkrg)
21
+ void msgpack_packer_ext_registry_init(VALUE owner, msgpack_packer_ext_registry_t* pkrg)
32
22
  {
33
- pkrg->hash = Qnil;
34
- pkrg->cache = Qnil;
23
+ RB_OBJ_WRITE(owner, &pkrg->hash, Qnil);
24
+ RB_OBJ_WRITE(owner, &pkrg->cache, Qnil);
35
25
  }
36
26
 
37
27
  void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
@@ -40,32 +30,45 @@ void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
40
30
  rb_gc_mark(pkrg->cache);
41
31
  }
42
32
 
43
- void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
33
+ void msgpack_packer_ext_registry_borrow(VALUE owner, msgpack_packer_ext_registry_t* src,
44
34
  msgpack_packer_ext_registry_t* dst)
45
35
  {
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;
36
+ if(RTEST(src->hash)) {
37
+ if(rb_obj_frozen_p(src->hash)) {
38
+ // If the type registry is frozen we can safely share it, and share the cache as well.
39
+ RB_OBJ_WRITE(owner, &dst->hash, src->hash);
40
+ RB_OBJ_WRITE(owner, &dst->cache, src->cache);
41
+ } else {
42
+ RB_OBJ_WRITE(owner, &dst->hash, rb_hash_dup(src->hash));
43
+ RB_OBJ_WRITE(owner, &dst->cache, NIL_P(src->cache) ? Qnil : rb_hash_dup(src->cache));
44
+ }
49
45
  } 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;
46
+ RB_OBJ_WRITE(owner, &dst->hash, Qnil);
47
+ RB_OBJ_WRITE(owner, &dst->cache, Qnil);
53
48
  }
54
49
  }
55
50
 
56
- VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
57
- VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
51
+ void msgpack_packer_ext_registry_dup(VALUE owner, msgpack_packer_ext_registry_t* src,
52
+ msgpack_packer_ext_registry_t* dst)
58
53
  {
59
- if (!RTEST(pkrg->hash)) {
60
- pkrg->hash = rb_hash_new();
54
+ RB_OBJ_WRITE(owner, &dst->hash, NIL_P(src->hash) ? Qnil : rb_hash_dup(src->hash));
55
+ RB_OBJ_WRITE(owner, &dst->cache, NIL_P(src->cache) ? Qnil : rb_hash_dup(src->cache));
56
+ }
57
+
58
+ void msgpack_packer_ext_registry_put(VALUE owner, msgpack_packer_ext_registry_t* pkrg,
59
+ VALUE ext_module, int ext_type, int flags, VALUE proc)
60
+ {
61
+ if(NIL_P(pkrg->hash)) {
62
+ RB_OBJ_WRITE(owner, &pkrg->hash, rb_hash_new());
61
63
  }
62
64
 
63
- if (RTEST(pkrg->cache)) {
65
+ if(NIL_P(pkrg->cache)) {
66
+ RB_OBJ_WRITE(owner, &pkrg->cache, rb_hash_new());
67
+ } else {
64
68
  /* clear lookup cache not to miss added type */
65
69
  rb_hash_clear(pkrg->cache);
66
70
  }
67
71
 
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);
72
+ VALUE entry = rb_ary_new3(3, INT2FIX(ext_type), proc, INT2FIX(flags));
73
+ rb_hash_aset(pkrg->hash, ext_module, entry);
71
74
  }
@@ -31,22 +31,21 @@ struct msgpack_packer_ext_registry_t {
31
31
  VALUE cache; // lookup cache for ext types inherited from a super class
32
32
  };
33
33
 
34
- void msgpack_packer_ext_registry_static_init(void);
35
-
36
- void msgpack_packer_ext_registry_static_destroy(void);
37
-
38
- void msgpack_packer_ext_registry_init(msgpack_packer_ext_registry_t* pkrg);
34
+ void msgpack_packer_ext_registry_init(VALUE owner, msgpack_packer_ext_registry_t* pkrg);
39
35
 
40
36
  static inline void msgpack_packer_ext_registry_destroy(msgpack_packer_ext_registry_t* pkrg)
41
37
  { }
42
38
 
43
39
  void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg);
44
40
 
45
- void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
41
+ void msgpack_packer_ext_registry_borrow(VALUE owner, msgpack_packer_ext_registry_t* src,
46
42
  msgpack_packer_ext_registry_t* dst);
47
43
 
48
- VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
49
- VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
44
+ void msgpack_packer_ext_registry_dup(VALUE owner, msgpack_packer_ext_registry_t* src,
45
+ msgpack_packer_ext_registry_t* dst);
46
+
47
+ void msgpack_packer_ext_registry_put(VALUE owner, msgpack_packer_ext_registry_t* pkrg,
48
+ VALUE ext_module, int ext_type, int flags, VALUE proc);
50
49
 
51
50
  static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
52
51
  {
@@ -68,7 +67,7 @@ static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registr
68
67
  VALUE type = rb_hash_lookup(pkrg->hash, lookup_class);
69
68
  if(type != Qnil) {
70
69
  *ext_type_result = FIX2INT(rb_ary_entry(type, 0));
71
- *ext_flags_result = FIX2INT(rb_ary_entry(type, 3));
70
+ *ext_flags_result = FIX2INT(rb_ary_entry(type, 2));
72
71
  return rb_ary_entry(type, 1);
73
72
  }
74
73
 
@@ -77,7 +76,7 @@ static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registr
77
76
  VALUE type_inht = rb_hash_lookup(pkrg->cache, lookup_class);
78
77
  if(type_inht != Qnil) {
79
78
  *ext_type_result = FIX2INT(rb_ary_entry(type_inht, 0));
80
- *ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 3));
79
+ *ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 2));
81
80
  return rb_ary_entry(type_inht, 1);
82
81
  }
83
82
  }
@@ -129,12 +128,9 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
129
128
  VALUE superclass = args[1];
130
129
  if(superclass != Qnil) {
131
130
  VALUE superclass_type = rb_hash_lookup(pkrg->hash, superclass);
132
- if (!RTEST(pkrg->cache)) {
133
- pkrg->cache = rb_hash_new();
134
- }
135
131
  rb_hash_aset(pkrg->cache, lookup_class, superclass_type);
136
132
  *ext_type_result = FIX2INT(rb_ary_entry(superclass_type, 0));
137
- *ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 3));
133
+ *ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 2));
138
134
  return rb_ary_entry(superclass_type, 1);
139
135
  }
140
136
 
@@ -20,11 +20,15 @@
20
20
  #include "rmem.h"
21
21
  #include "extension_value_class.h"
22
22
  #include <assert.h>
23
+ #include <limits.h>
24
+
25
+ #if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
26
+ #define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
27
+ #endif
23
28
 
24
29
  static int RAW_TYPE_STRING = 256;
25
30
  static int RAW_TYPE_BINARY = 257;
26
-
27
- static ID s_call;
31
+ static int16_t INITIAL_BUFFER_CAPACITY_MAX = SHRT_MAX;
28
32
 
29
33
  static msgpack_rmem_t s_stack_rmem;
30
34
 
@@ -35,13 +39,16 @@ static inline VALUE rb_hash_new_capa(long capa)
35
39
  }
36
40
  #endif
37
41
 
42
+ static inline int16_t initial_buffer_size(long size)
43
+ {
44
+ return (size > INITIAL_BUFFER_CAPACITY_MAX) ? INITIAL_BUFFER_CAPACITY_MAX : size;
45
+ }
46
+
38
47
  void msgpack_unpacker_static_init(void)
39
48
  {
40
49
  assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
41
50
 
42
51
  msgpack_rmem_init(&s_stack_rmem);
43
-
44
- s_call = rb_intern("call");
45
52
  }
46
53
 
47
54
  void msgpack_unpacker_static_destroy(void)
@@ -178,7 +185,8 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
178
185
 
179
186
  if(proc != Qnil) {
180
187
  VALUE obj;
181
- obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
188
+ VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
189
+ obj = rb_proc_call_with_block(proc, 1, &arg, Qnil);
182
190
  return object_complete(uk, obj);
183
191
  }
184
192
 
@@ -308,7 +316,7 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
308
316
  child_stack->parent = uk->stack;
309
317
  uk->stack = child_stack;
310
318
 
311
- obj = rb_funcall(proc, s_call, 1, uk->self);
319
+ obj = rb_proc_call_with_block(proc, 1, &uk->self, Qnil);
312
320
 
313
321
  uk->stack = child_stack->parent;
314
322
  _msgpack_unpacker_free_stack(child_stack);
@@ -374,14 +382,14 @@ static int read_primitive(msgpack_unpacker_t* uk)
374
382
  if(count == 0) {
375
383
  return object_complete(uk, rb_ary_new());
376
384
  }
377
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
385
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
378
386
 
379
387
  SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
380
388
  int count = b & 0x0f;
381
389
  if(count == 0) {
382
390
  return object_complete(uk, rb_hash_new());
383
391
  }
384
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
392
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
385
393
 
386
394
  SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
387
395
  switch(b) {
@@ -604,7 +612,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
604
612
  if(count == 0) {
605
613
  return object_complete(uk, rb_ary_new());
606
614
  }
607
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
615
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
608
616
  }
609
617
 
610
618
  case 0xdd: // array 32
@@ -614,7 +622,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
614
622
  if(count == 0) {
615
623
  return object_complete(uk, rb_ary_new());
616
624
  }
617
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
625
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
618
626
  }
619
627
 
620
628
  case 0xde: // map 16
@@ -624,7 +632,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
624
632
  if(count == 0) {
625
633
  return object_complete(uk, rb_hash_new());
626
634
  }
627
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
635
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
628
636
  }
629
637
 
630
638
  case 0xdf: // map 32
@@ -634,7 +642,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
634
642
  if(count == 0) {
635
643
  return object_complete(uk, rb_hash_new());
636
644
  }
637
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
645
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
638
646
  }
639
647
 
640
648
  default:
@@ -346,43 +346,19 @@ static VALUE Unpacker_registered_types_internal(VALUE self)
346
346
  return mapping;
347
347
  }
348
348
 
349
- static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
349
+ static VALUE Unpacker_register_type_internal(VALUE self, VALUE rb_ext_type, VALUE ext_module, VALUE proc)
350
350
  {
351
351
  if (OBJ_FROZEN(self)) {
352
352
  rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Unpacker");
353
353
  }
354
354
 
355
- msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
356
-
357
- int ext_type;
358
- VALUE proc;
359
- VALUE arg;
360
- VALUE ext_module;
361
-
362
- switch (argc) {
363
- case 1:
364
- /* register_type(0x7f) {|data| block... } */
365
- rb_need_block();
366
- proc = rb_block_lambda();
367
- arg = proc;
368
- ext_module = Qnil;
369
- break;
370
- case 3:
371
- /* register_type(0x7f, Time, :from_msgpack_ext) */
372
- ext_module = argv[1];
373
- arg = argv[2];
374
- proc = rb_obj_method(ext_module, arg);
375
- break;
376
- default:
377
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1 or 3)", argc);
378
- }
379
-
380
- ext_type = NUM2INT(argv[0]);
355
+ int ext_type = NUM2INT(rb_ext_type);
381
356
  if(ext_type < -128 || ext_type > 127) {
382
357
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
383
358
  }
384
359
 
385
- msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, 0, proc, arg);
360
+ msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
361
+ msgpack_unpacker_ext_registry_put(self, &uk->ext_registry, ext_module, ext_type, 0, proc);
386
362
 
387
363
  return Qnil;
388
364
  }
@@ -415,7 +391,6 @@ VALUE MessagePack_Unpacker_new(int argc, VALUE* argv)
415
391
  void MessagePack_Unpacker_module_init(VALUE mMessagePack)
416
392
  {
417
393
  msgpack_unpacker_static_init();
418
- msgpack_unpacker_ext_registry_static_init();
419
394
 
420
395
  mTypeError = rb_define_module_under(mMessagePack, "TypeError");
421
396
 
@@ -456,7 +431,7 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
456
431
  rb_define_method(cMessagePack_Unpacker, "reset", Unpacker_reset, 0);
457
432
 
458
433
  rb_define_private_method(cMessagePack_Unpacker, "registered_types_internal", Unpacker_registered_types_internal, 0);
459
- rb_define_method(cMessagePack_Unpacker, "register_type", Unpacker_register_type, -1);
434
+ rb_define_private_method(cMessagePack_Unpacker, "register_type_internal", Unpacker_register_type_internal, 3);
460
435
 
461
436
  rb_define_method(cMessagePack_Unpacker, "full_unpack", Unpacker_full_unpack, 0);
462
437
  }
@@ -18,19 +18,6 @@
18
18
 
19
19
  #include "unpacker_ext_registry.h"
20
20
 
21
- static ID s_call;
22
- static ID s_dup;
23
-
24
- void msgpack_unpacker_ext_registry_static_init(void)
25
- {
26
- s_call = rb_intern("call");
27
- s_dup = rb_intern("dup");
28
- }
29
-
30
-
31
- void msgpack_unpacker_ext_registry_static_destroy(void)
32
- { }
33
-
34
21
  void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg)
35
22
  {
36
23
  if (ukrg) {
@@ -76,11 +63,12 @@ void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg
76
63
  }
77
64
  }
78
65
 
79
- void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
80
- VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
66
+ void msgpack_unpacker_ext_registry_put(VALUE owner, msgpack_unpacker_ext_registry_t** ukrg,
67
+ VALUE ext_module, int ext_type, int flags, VALUE proc)
81
68
  {
82
69
  msgpack_unpacker_ext_registry_t* ext_registry = msgpack_unpacker_ext_registry_cow(*ukrg);
83
70
 
84
- ext_registry->array[ext_type + 128] = rb_ary_new3(4, ext_module, proc, arg, INT2FIX(flags));
71
+ VALUE entry = rb_ary_new3(3, ext_module, proc, INT2FIX(flags));
72
+ RB_OBJ_WRITE(owner, &ext_registry->array[ext_type + 128], entry);
85
73
  *ukrg = ext_registry;
86
74
  }
@@ -31,10 +31,6 @@ struct msgpack_unpacker_ext_registry_t {
31
31
  VALUE array[256];
32
32
  };
33
33
 
34
- void msgpack_unpacker_ext_registry_static_init(void);
35
-
36
- void msgpack_unpacker_ext_registry_static_destroy(void);
37
-
38
34
  void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg);
39
35
 
40
36
  static inline void msgpack_unpacker_ext_registry_borrow(msgpack_unpacker_ext_registry_t* src, msgpack_unpacker_ext_registry_t** dst)
@@ -47,8 +43,8 @@ static inline void msgpack_unpacker_ext_registry_borrow(msgpack_unpacker_ext_reg
47
43
 
48
44
  void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg);
49
45
 
50
- void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
51
- VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
46
+ void msgpack_unpacker_ext_registry_put(VALUE owner, msgpack_unpacker_ext_registry_t** ukrg,
47
+ VALUE ext_module, int ext_type, int flags, VALUE proc);
52
48
 
53
49
  static inline VALUE msgpack_unpacker_ext_registry_lookup(msgpack_unpacker_ext_registry_t* ukrg,
54
50
  int ext_type, int* ext_flags_result)
@@ -56,7 +52,7 @@ static inline VALUE msgpack_unpacker_ext_registry_lookup(msgpack_unpacker_ext_re
56
52
  if (ukrg) {
57
53
  VALUE entry = ukrg->array[ext_type + 128];
58
54
  if (entry != Qnil) {
59
- *ext_flags_result = FIX2INT(rb_ary_entry(entry, 3));
55
+ *ext_flags_result = FIX2INT(rb_ary_entry(entry, 2));
60
56
  return rb_ary_entry(entry, 1);
61
57
  }
62
58
  }
@@ -2,11 +2,46 @@ module MessagePack
2
2
  class Factory
3
3
  # see ext for other methods
4
4
 
5
+ def register_type(type, klass, options = { packer: :to_msgpack_ext, unpacker: :from_msgpack_ext })
6
+ raise FrozenError, "can't modify frozen MessagePack::Factory" if frozen?
7
+
8
+ if options
9
+ options = options.dup
10
+ case packer = options[:packer]
11
+ when nil, Proc
12
+ # all good
13
+ when String, Symbol
14
+ options[:packer] = packer.to_sym.to_proc
15
+ when Method
16
+ options[:packer] = packer.to_proc
17
+ when packer.respond_to?(:call)
18
+ options[:packer] = packer.method(:call).to_proc
19
+ else
20
+ raise ::TypeError, "expected :packer argument to be a callable object, got: #{packer.inspect}"
21
+ end
22
+
23
+ case unpacker = options[:unpacker]
24
+ when nil, Proc
25
+ # all good
26
+ when String, Symbol
27
+ options[:unpacker] = klass.method(unpacker).to_proc
28
+ when Method
29
+ options[:unpacker] = unpacker.to_proc
30
+ when packer.respond_to?(:call)
31
+ options[:unpacker] = unpacker.method(:call).to_proc
32
+ else
33
+ raise ::TypeError, "expected :unpacker argument to be a callable object, got: #{unpacker.inspect}"
34
+ end
35
+ end
36
+
37
+ register_type_internal(type, klass, options)
38
+ end
39
+
5
40
  # [ {type: id, class: Class(or nil), packer: arg, unpacker: arg}, ... ]
6
41
  def registered_types(selector=:both)
7
42
  packer, unpacker = registered_types_internal
8
- # packer: Class -> [tid, proc, arg]
9
- # unpacker: tid -> [klass, proc, arg]
43
+ # packer: Class -> [tid, proc, _flags]
44
+ # unpacker: tid -> [klass, proc, _flags]
10
45
 
11
46
  list = []
12
47
 
@@ -14,27 +49,31 @@ module MessagePack
14
49
  when :both
15
50
  packer.each_pair do |klass, ary|
16
51
  type = ary[0]
17
- packer_arg = ary[2]
18
- unpacker_arg = nil
19
- if unpacker.has_key?(type) && unpacker[type][0] == klass
20
- unpacker_arg = unpacker.delete(type)[2]
52
+ packer_proc = ary[1]
53
+ unpacker_proc = nil
54
+ if unpacker.has_key?(type)
55
+ unpacker_proc = unpacker.delete(type)[1]
21
56
  end
22
- list << {type: type, class: klass, packer: packer_arg, unpacker: unpacker_arg}
57
+ list << {type: type, class: klass, packer: packer_proc, unpacker: unpacker_proc}
23
58
  end
24
59
 
25
60
  # unpacker definition only
26
61
  unpacker.each_pair do |type, ary|
27
- list << {type: type, class: ary[0], packer: nil, unpacker: ary[2]}
62
+ list << {type: type, class: ary[0], packer: nil, unpacker: ary[1]}
28
63
  end
29
64
 
30
65
  when :packer
31
66
  packer.each_pair do |klass, ary|
32
- list << {type: ary[0], class: klass, packer: ary[2]}
67
+ if ary[1]
68
+ list << {type: ary[0], class: klass, packer: ary[1]}
69
+ end
33
70
  end
34
71
 
35
72
  when :unpacker
36
73
  unpacker.each_pair do |type, ary|
37
- list << {type: type, class: ary[0], unpacker: ary[2]}
74
+ if ary[1]
75
+ list << {type: type, class: ary[0], unpacker: ary[1]}
76
+ end
38
77
  end
39
78
 
40
79
  else
@@ -6,11 +6,16 @@ module MessagePack
6
6
  undef_method :dup
7
7
  undef_method :clone
8
8
 
9
+ def register_type(type, klass, method_name = nil, &block)
10
+ raise ArgumentError, "expected Module/Class got: #{klass.inspect}" unless klass.is_a?(Module)
11
+ register_type_internal(type, klass, block || method_name.to_proc)
12
+ end
13
+
9
14
  def registered_types
10
15
  list = []
11
16
 
12
17
  registered_types_internal.each_pair do |klass, ary|
13
- list << {type: ary[0], class: klass, packer: ary[2]}
18
+ list << {type: ary[0], class: klass, packer: ary[1]}
14
19
  end
15
20
 
16
21
  list.sort{|a, b| a[:type] <=> b[:type] }
@@ -6,11 +6,20 @@ module MessagePack
6
6
  undef_method :dup
7
7
  undef_method :clone
8
8
 
9
+ def register_type(type, klass = nil, method_name = nil, &block)
10
+ if klass && method_name
11
+ block = klass.method(method_name).to_proc
12
+ elsif !block_given?
13
+ raise ArgumentError, "register_type takes either 3 arguments or a block"
14
+ end
15
+ register_type_internal(type, klass, block)
16
+ end
17
+
9
18
  def registered_types
10
19
  list = []
11
20
 
12
21
  registered_types_internal.each_pair do |type, ary|
13
- list << {type: type, class: ary[0], unpacker: ary[2]}
22
+ list << {type: type, class: ary[0], unpacker: ary[1]}
14
23
  end
15
24
 
16
25
  list.sort{|a, b| a[:type] <=> b[:type] }