msgpack 1.7.1 → 1.7.3

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.
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] }