msgpack 1.7.1 → 1.8.0

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.
@@ -1,20 +1,21 @@
1
1
  require 'mkmf'
2
2
 
3
- have_header("ruby/st.h")
4
- have_header("st.h")
5
3
  have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
6
4
  have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
5
+ have_func("rb_proc_call_with_block", "ruby.h") # CRuby (TruffleRuby doesn't have it)
6
+ have_func("rb_gc_mark_locations", "ruby.h") # Missing on TruffleRuby
7
7
 
8
8
  append_cflags([
9
9
  "-fvisibility=hidden",
10
10
  "-I..",
11
11
  "-Wall",
12
- "-O3",
13
12
  "-std=gnu99"
14
13
  ])
15
- append_cflags(RbConfig::CONFIG["debugflags"]) if RbConfig::CONFIG["debugflags"]
16
14
 
17
- append_cflags("-DRUBY_DEBUG=1") if ENV["MSGPACK_DEBUG"]
15
+ if ENV["MSGPACK_DEBUG"]
16
+ append_cflags(RbConfig::CONFIG["debugflags"]) if RbConfig::CONFIG["debugflags"]
17
+ append_cflags("-DRUBY_DEBUG=1")
18
+ end
18
19
 
19
20
  if RUBY_VERSION.start_with?('3.0.') && RUBY_VERSION <= '3.0.5'
20
21
  # https://bugs.ruby-lang.org/issues/18772
@@ -75,7 +75,7 @@ static const rb_data_type_t factory_data_type = {
75
75
  .dfree = Factory_free,
76
76
  .dsize = Factory_memsize,
77
77
  },
78
- .flags = RUBY_TYPED_FREE_IMMEDIATELY
78
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
79
79
  };
80
80
 
81
81
  static inline msgpack_factory_t *Factory_get(VALUE object)
@@ -98,7 +98,7 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
98
98
  {
99
99
  msgpack_factory_t *fc = Factory_get(self);
100
100
 
101
- msgpack_packer_ext_registry_init(&fc->pkrg);
101
+ msgpack_packer_ext_registry_init(self, &fc->pkrg);
102
102
  // fc->ukrg is lazily initialized
103
103
 
104
104
  fc->has_symbol_ext_type = false;
@@ -124,7 +124,7 @@ static VALUE Factory_dup(VALUE self)
124
124
  cloned_fc->has_symbol_ext_type = fc->has_symbol_ext_type;
125
125
  cloned_fc->pkrg = fc->pkrg;
126
126
  msgpack_unpacker_ext_registry_borrow(fc->ukrg, &cloned_fc->ukrg);
127
- msgpack_packer_ext_registry_dup(&fc->pkrg, &cloned_fc->pkrg);
127
+ msgpack_packer_ext_registry_dup(clone, &fc->pkrg, &cloned_fc->pkrg);
128
128
 
129
129
  return clone;
130
130
  }
@@ -139,7 +139,7 @@ static VALUE Factory_freeze(VALUE self) {
139
139
  // If the factory is frozen, we can safely share the packer cache between
140
140
  // all packers. So we eagerly create it now so it's available when #packer
141
141
  // is called.
142
- fc->pkrg.cache = rb_hash_new();
142
+ RB_OBJ_WRITE(self, &fc->pkrg.cache, rb_hash_new());
143
143
  }
144
144
  }
145
145
 
@@ -158,7 +158,7 @@ VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
158
158
 
159
159
  msgpack_packer_t* pk = MessagePack_Packer_get(packer);
160
160
  msgpack_packer_ext_registry_destroy(&pk->ext_registry);
161
- msgpack_packer_ext_registry_dup(&fc->pkrg, &pk->ext_registry);
161
+ msgpack_packer_ext_registry_borrow(packer, &fc->pkrg, &pk->ext_registry);
162
162
  pk->has_bigint_ext_type = fc->has_bigint_ext_type;
163
163
  pk->has_symbol_ext_type = fc->has_symbol_ext_type;
164
164
 
@@ -187,7 +187,7 @@ static VALUE Factory_registered_types_internal(VALUE self)
187
187
  VALUE uk_mapping = rb_hash_new();
188
188
  if (fc->ukrg) {
189
189
  for(int i=0; i < 256; i++) {
190
- if(fc->ukrg->array[i] != Qnil) {
190
+ if(!NIL_P(fc->ukrg->array[i])) {
191
191
  rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg->array[i]);
192
192
  }
193
193
  }
@@ -200,72 +200,35 @@ static VALUE Factory_registered_types_internal(VALUE self)
200
200
  );
201
201
  }
202
202
 
203
- static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
203
+ static VALUE Factory_register_type_internal(VALUE self, VALUE rb_ext_type, VALUE ext_module, VALUE options)
204
204
  {
205
205
  msgpack_factory_t *fc = Factory_get(self);
206
206
 
207
- int ext_type;
208
- int flags = 0;
209
- VALUE ext_module;
210
- VALUE options = Qnil;
211
- VALUE packer_arg, unpacker_arg;
212
- VALUE packer_proc, unpacker_proc;
207
+ Check_Type(rb_ext_type, T_FIXNUM);
213
208
 
214
- if (OBJ_FROZEN(self)) {
215
- rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
209
+ if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
210
+ rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
216
211
  }
217
212
 
218
- switch (argc) {
219
- case 2:
220
- /* register_type(0x7f, Time) */
221
- packer_arg = ID2SYM(rb_intern("to_msgpack_ext"));
222
- unpacker_arg = ID2SYM(rb_intern("from_msgpack_ext"));
223
- break;
224
- case 3:
225
- /* register_type(0x7f, Time, packer: proc-like, unpacker: proc-like) */
226
- options = argv[2];
227
- if(rb_type(options) != T_HASH) {
228
- rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
229
- }
213
+ int flags = 0;
230
214
 
231
- packer_arg = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
232
- unpacker_arg = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
233
- break;
234
- default:
235
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
215
+ VALUE packer_proc = Qnil;
216
+ VALUE unpacker_proc = Qnil;
217
+ if(!NIL_P(options)) {
218
+ Check_Type(options, T_HASH);
219
+ packer_proc = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
220
+ unpacker_proc = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
236
221
  }
237
222
 
238
- if (options != Qnil) {
239
- Check_Type(options, T_HASH);
223
+ if (OBJ_FROZEN(self)) {
224
+ rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
240
225
  }
241
226
 
242
- ext_type = NUM2INT(argv[0]);
227
+ int ext_type = NUM2INT(rb_ext_type);
243
228
  if(ext_type < -128 || ext_type > 127) {
244
229
  rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
245
230
  }
246
231
 
247
- ext_module = argv[1];
248
- if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
249
- rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
250
- }
251
-
252
- packer_proc = Qnil;
253
- unpacker_proc = Qnil;
254
-
255
- if(packer_arg != Qnil) {
256
- packer_proc = rb_funcall(packer_arg, rb_intern("to_proc"), 0);
257
- }
258
-
259
- if(unpacker_arg != Qnil) {
260
- if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
261
- unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
262
- } else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
263
- unpacker_proc = unpacker_arg;
264
- } else {
265
- unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
266
- }
267
- }
268
-
269
232
  if(ext_module == rb_cSymbol) {
270
233
  if(NIL_P(options) || RTEST(rb_hash_aref(options, ID2SYM(rb_intern("packer"))))) {
271
234
  fc->has_symbol_ext_type = true;
@@ -289,8 +252,8 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
289
252
  }
290
253
  }
291
254
 
292
- msgpack_packer_ext_registry_put(&fc->pkrg, ext_module, ext_type, flags, packer_proc, packer_arg);
293
- msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, flags, unpacker_proc, unpacker_arg);
255
+ msgpack_packer_ext_registry_put(self, &fc->pkrg, ext_module, ext_type, flags, packer_proc);
256
+ msgpack_unpacker_ext_registry_put(self, &fc->ukrg, ext_module, ext_type, flags, unpacker_proc);
294
257
 
295
258
  return Qnil;
296
259
  }
@@ -309,5 +272,5 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
309
272
  rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
310
273
 
311
274
  rb_define_private_method(cMessagePack_Factory, "registered_types_internal", Factory_registered_types_internal, 0);
312
- rb_define_method(cMessagePack_Factory, "register_type", Factory_register_type, -1);
275
+ rb_define_private_method(cMessagePack_Factory, "register_type_internal", Factory_register_type_internal, 3);
313
276
  }
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
@@ -25,21 +25,26 @@
25
25
  #define MSGPACK_PACKER_IO_FLUSH_THRESHOLD_TO_WRITE_STRING_BODY (1024)
26
26
  #endif
27
27
 
28
+ #ifndef UNREACHABLE_RETURN
29
+ // Ruby 2.5
30
+ #define UNREACHABLE_RETURN() return
31
+ #endif
32
+
28
33
  struct msgpack_packer_t;
29
34
  typedef struct msgpack_packer_t msgpack_packer_t;
30
35
 
31
36
  struct msgpack_packer_t {
32
37
  msgpack_buffer_t buffer;
33
38
 
34
- bool compatibility_mode;
35
- bool has_bigint_ext_type;
36
- bool has_symbol_ext_type;
37
-
38
39
  ID to_msgpack_method;
39
40
  VALUE to_msgpack_arg;
40
41
 
41
42
  VALUE buffer_ref;
42
43
 
44
+ bool compatibility_mode;
45
+ bool has_bigint_ext_type;
46
+ bool has_symbol_ext_type;
47
+
43
48
  /* options */
44
49
  bool comaptibility_mode;
45
50
  msgpack_packer_ext_registry_t ext_registry;
@@ -47,10 +52,6 @@ struct msgpack_packer_t {
47
52
 
48
53
  #define PACKER_BUFFER_(pk) (&(pk)->buffer)
49
54
 
50
- void msgpack_packer_static_init(void);
51
-
52
- void msgpack_packer_static_destroy(void);
53
-
54
55
  void msgpack_packer_init(msgpack_packer_t* pk);
55
56
 
56
57
  void msgpack_packer_destroy(msgpack_packer_t* pk);
@@ -408,27 +409,33 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
408
409
  {
409
410
  return encindex == msgpack_rb_encindex_utf8
410
411
  || encindex == msgpack_rb_encindex_usascii
411
- || (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v));
412
+ || ENC_CODERANGE_ASCIIONLY(v);
412
413
  }
413
414
 
414
415
  static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
415
416
  {
416
- /* actual return type of RSTRING_LEN is long */
417
- unsigned long len = RSTRING_LEN(v);
418
- if(len > 0xffffffffUL) {
419
- // TODO rb_eArgError?
420
- rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %lu", len, 0xffffffffUL);
417
+ long len = RSTRING_LEN(v);
418
+
419
+ if(RB_UNLIKELY(len > 0xffffffffL)) {
420
+ rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %ld", len, 0xffffffffL);
421
+ UNREACHABLE_RETURN();
421
422
  }
422
423
 
423
- int encindex = ENCODING_GET(v);
424
- if(msgpack_packer_is_binary(v, encindex) && !pk->compatibility_mode) {
424
+ if (RB_UNLIKELY(pk->compatibility_mode)) {
425
+ msgpack_packer_write_raw_header(pk, (unsigned int)len);
426
+ msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
427
+ return;
428
+ }
429
+
430
+ int encindex = ENCODING_GET_INLINED(v);
431
+ if(msgpack_packer_is_binary(v, encindex)) {
425
432
  /* write ASCII-8BIT string using Binary type */
426
433
  msgpack_packer_write_bin_header(pk, (unsigned int)len);
427
434
  msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
428
435
  } else {
429
436
  /* write UTF-8, US-ASCII, or 7bit-safe ascii-compatible string using String type directly */
430
437
  /* in compatibility mode, packer packs String values as is */
431
- if(!pk->compatibility_mode && !msgpack_packer_is_utf8_compat_string(v, encindex)) {
438
+ if(RB_UNLIKELY(!msgpack_packer_is_utf8_compat_string(v, encindex))) {
432
439
  /* transcode other strings to UTF-8 and write using String type */
433
440
  VALUE enc = rb_enc_from_encoding(rb_utf8_encoding()); /* rb_enc_from_encoding_index is not extern */
434
441
  v = rb_str_encode(v, enc, 0, Qnil);
@@ -457,11 +464,7 @@ static inline void msgpack_packer_write_symbol_value(msgpack_packer_t* pk, VALUE
457
464
 
458
465
  static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE v)
459
466
  {
460
- #ifdef JRUBY
461
- msgpack_packer_write_long(pk, FIXNUM_P(v) ? FIX2LONG(v) : rb_num2ll(v));
462
- #else
463
467
  msgpack_packer_write_long(pk, FIX2LONG(v));
464
- #endif
465
468
  }
466
469
 
467
470
  static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
@@ -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