msgpack 1.4.5 → 1.5.6
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +5 -5
- data/ChangeLog +32 -0
- data/README.md +25 -1
- data/bench/bench.rb +78 -0
- data/doclib/msgpack/factory.rb +45 -2
- data/ext/java/org/msgpack/jruby/Buffer.java +6 -0
- data/ext/java/org/msgpack/jruby/Decoder.java +23 -19
- data/ext/java/org/msgpack/jruby/Encoder.java +46 -18
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +24 -31
- data/ext/java/org/msgpack/jruby/Factory.java +40 -5
- data/ext/java/org/msgpack/jruby/Packer.java +21 -11
- data/ext/java/org/msgpack/jruby/Unpacker.java +44 -22
- data/ext/msgpack/buffer.c +9 -36
- data/ext/msgpack/buffer.h +9 -1
- data/ext/msgpack/buffer_class.c +18 -9
- data/ext/msgpack/compat.h +0 -99
- data/ext/msgpack/extconf.rb +9 -11
- data/ext/msgpack/factory_class.c +62 -5
- data/ext/msgpack/packer.c +42 -29
- data/ext/msgpack/packer.h +25 -7
- data/ext/msgpack/packer_class.c +23 -20
- data/ext/msgpack/packer_ext_registry.c +13 -4
- data/ext/msgpack/packer_ext_registry.h +10 -5
- data/ext/msgpack/unpacker.c +99 -68
- data/ext/msgpack/unpacker.h +10 -6
- data/ext/msgpack/unpacker_class.c +16 -8
- data/ext/msgpack/unpacker_ext_registry.c +3 -2
- data/ext/msgpack/unpacker_ext_registry.h +5 -2
- data/lib/msgpack/bigint.rb +69 -0
- data/lib/msgpack/factory.rb +103 -0
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +4 -5
- data/msgpack.gemspec +1 -0
- data/spec/bigint_spec.rb +26 -0
- data/spec/factory_spec.rb +248 -0
- data/spec/spec_helper.rb +9 -1
- data/spec/timestamp_spec.rb +2 -2
- data/spec/unpacker_spec.rb +12 -0
- metadata +20 -13
- data/bench/pack.rb +0 -23
- data/bench/pack_log.rb +0 -33
- data/bench/pack_log_long.rb +0 -65
- data/bench/pack_symbols.rb +0 -28
- data/bench/run.sh +0 -14
- data/bench/run_long.sh +0 -35
- data/bench/run_symbols.sh +0 -26
- data/bench/unpack.rb +0 -21
- data/bench/unpack_log.rb +0 -34
- data/bench/unpack_log_long.rb +0 -67
data/ext/msgpack/factory_class.c
CHANGED
@@ -31,6 +31,7 @@ typedef struct msgpack_factory_t msgpack_factory_t;
|
|
31
31
|
struct msgpack_factory_t {
|
32
32
|
msgpack_packer_ext_registry_t pkrg;
|
33
33
|
msgpack_unpacker_ext_registry_t *ukrg;
|
34
|
+
bool has_bigint_ext_type;
|
34
35
|
bool has_symbol_ext_type;
|
35
36
|
bool optimized_symbol_ext_type;
|
36
37
|
int symbol_ext_type;
|
@@ -87,6 +88,41 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
|
|
87
88
|
return Qnil;
|
88
89
|
}
|
89
90
|
|
91
|
+
static VALUE Factory_dup(VALUE self)
|
92
|
+
{
|
93
|
+
VALUE clone = Factory_alloc(rb_obj_class(self));
|
94
|
+
|
95
|
+
FACTORY(self, fc);
|
96
|
+
FACTORY(clone, cloned_fc);
|
97
|
+
|
98
|
+
cloned_fc->has_symbol_ext_type = fc->has_symbol_ext_type;
|
99
|
+
cloned_fc->pkrg = fc->pkrg;
|
100
|
+
msgpack_unpacker_ext_registry_borrow(fc->ukrg, &cloned_fc->ukrg);
|
101
|
+
msgpack_packer_ext_registry_dup(&fc->pkrg, &cloned_fc->pkrg);
|
102
|
+
|
103
|
+
return clone;
|
104
|
+
}
|
105
|
+
|
106
|
+
static VALUE Factory_freeze(VALUE self) {
|
107
|
+
if(!rb_obj_frozen_p(self)) {
|
108
|
+
FACTORY(self, fc);
|
109
|
+
|
110
|
+
if (RTEST(fc->pkrg.hash)) {
|
111
|
+
rb_hash_freeze(fc->pkrg.hash);
|
112
|
+
if (!RTEST(fc->pkrg.cache)) {
|
113
|
+
// If the factory is frozen, we can safely share the packer cache between
|
114
|
+
// all packers. So we eagerly create it now so it's available when #packer
|
115
|
+
// is called.
|
116
|
+
fc->pkrg.cache = rb_hash_new();
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
rb_obj_freeze(self);
|
121
|
+
}
|
122
|
+
|
123
|
+
return self;
|
124
|
+
}
|
125
|
+
|
90
126
|
VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
|
91
127
|
{
|
92
128
|
FACTORY(self, fc);
|
@@ -99,6 +135,7 @@ VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
|
|
99
135
|
|
100
136
|
msgpack_packer_ext_registry_destroy(&pk->ext_registry);
|
101
137
|
msgpack_packer_ext_registry_dup(&fc->pkrg, &pk->ext_registry);
|
138
|
+
pk->has_bigint_ext_type = fc->has_bigint_ext_type;
|
102
139
|
pk->has_symbol_ext_type = fc->has_symbol_ext_type;
|
103
140
|
|
104
141
|
return packer;
|
@@ -145,6 +182,7 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
145
182
|
FACTORY(self, fc);
|
146
183
|
|
147
184
|
int ext_type;
|
185
|
+
int flags = 0;
|
148
186
|
VALUE ext_module;
|
149
187
|
VALUE options = Qnil;
|
150
188
|
VALUE packer_arg, unpacker_arg;
|
@@ -173,6 +211,10 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
173
211
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
|
174
212
|
}
|
175
213
|
|
214
|
+
if (options != Qnil) {
|
215
|
+
Check_Type(options, T_HASH);
|
216
|
+
}
|
217
|
+
|
176
218
|
ext_type = NUM2INT(argv[0]);
|
177
219
|
if(ext_type < -128 || ext_type > 127) {
|
178
220
|
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
|
@@ -200,16 +242,29 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
200
242
|
}
|
201
243
|
}
|
202
244
|
|
203
|
-
|
204
|
-
|
205
|
-
if (ext_module == rb_cSymbol) {
|
245
|
+
if(ext_module == rb_cSymbol) {
|
206
246
|
fc->has_symbol_ext_type = true;
|
207
|
-
if(
|
247
|
+
if(RTEST(options) && RTEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
|
208
248
|
fc->optimized_symbol_ext_type = true;
|
209
249
|
}
|
210
250
|
}
|
211
251
|
|
212
|
-
|
252
|
+
if(RTEST(options)) {
|
253
|
+
if(RTEST(rb_hash_aref(options, ID2SYM(rb_intern("oversized_integer_extension"))))) {
|
254
|
+
if(ext_module == rb_cInteger) {
|
255
|
+
fc->has_bigint_ext_type = true;
|
256
|
+
} else {
|
257
|
+
rb_raise(rb_eArgError, "oversized_integer_extension: true is only for Integer class");
|
258
|
+
}
|
259
|
+
}
|
260
|
+
|
261
|
+
if(RTEST(rb_hash_aref(options, ID2SYM(rb_intern("recursive"))))) {
|
262
|
+
flags |= MSGPACK_EXT_RECURSIVE;
|
263
|
+
}
|
264
|
+
}
|
265
|
+
|
266
|
+
msgpack_packer_ext_registry_put(&fc->pkrg, ext_module, ext_type, flags, packer_proc, packer_arg);
|
267
|
+
msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, flags, unpacker_proc, unpacker_arg);
|
213
268
|
|
214
269
|
return Qnil;
|
215
270
|
}
|
@@ -221,6 +276,8 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
|
|
221
276
|
rb_define_alloc_func(cMessagePack_Factory, Factory_alloc);
|
222
277
|
|
223
278
|
rb_define_method(cMessagePack_Factory, "initialize", Factory_initialize, -1);
|
279
|
+
rb_define_method(cMessagePack_Factory, "dup", Factory_dup, 0);
|
280
|
+
rb_define_method(cMessagePack_Factory, "freeze", Factory_freeze, 0);
|
224
281
|
|
225
282
|
rb_define_method(cMessagePack_Factory, "packer", MessagePack_Factory_packer, -1);
|
226
283
|
rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
|
data/ext/msgpack/packer.c
CHANGED
@@ -18,24 +18,10 @@
|
|
18
18
|
|
19
19
|
#include "packer.h"
|
20
20
|
|
21
|
-
#ifdef RUBINIUS
|
22
|
-
static ID s_to_iter;
|
23
|
-
static ID s_next;
|
24
|
-
static ID s_key;
|
25
|
-
static ID s_value;
|
26
|
-
#endif
|
27
|
-
|
28
21
|
static ID s_call;
|
29
22
|
|
30
23
|
void msgpack_packer_static_init()
|
31
24
|
{
|
32
|
-
#ifdef RUBINIUS
|
33
|
-
s_to_iter = rb_intern("to_iter");
|
34
|
-
s_next = rb_intern("next");
|
35
|
-
s_key = rb_intern("key");
|
36
|
-
s_value = rb_intern("value");
|
37
|
-
#endif
|
38
|
-
|
39
25
|
s_call = rb_intern("call");
|
40
26
|
}
|
41
27
|
|
@@ -108,32 +94,59 @@ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
|
|
108
94
|
unsigned int len32 = (unsigned int)len;
|
109
95
|
msgpack_packer_write_map_header(pk, len32);
|
110
96
|
|
111
|
-
#ifdef RUBINIUS
|
112
|
-
VALUE iter = rb_funcall(v, s_to_iter, 0);
|
113
|
-
VALUE entry = Qnil;
|
114
|
-
while(RTEST(entry = rb_funcall(iter, s_next, 1, entry))) {
|
115
|
-
VALUE key = rb_funcall(entry, s_key, 0);
|
116
|
-
VALUE val = rb_funcall(entry, s_value, 0);
|
117
|
-
write_hash_foreach(key, val, (VALUE) pk);
|
118
|
-
}
|
119
|
-
#else
|
120
97
|
rb_hash_foreach(v, write_hash_foreach, (VALUE) pk);
|
121
|
-
|
98
|
+
}
|
99
|
+
|
100
|
+
struct msgpack_call_proc_args_t;
|
101
|
+
typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
|
102
|
+
struct msgpack_call_proc_args_t {
|
103
|
+
VALUE proc;
|
104
|
+
VALUE arg;
|
105
|
+
VALUE packer;
|
106
|
+
};
|
107
|
+
|
108
|
+
VALUE msgpack_packer_try_calling_proc(VALUE value)
|
109
|
+
{
|
110
|
+
msgpack_call_proc_args_t *args = (msgpack_call_proc_args_t *)value;
|
111
|
+
return rb_funcall(args->proc, s_call, 2, args->arg, args->packer);
|
122
112
|
}
|
123
113
|
|
124
114
|
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
|
125
115
|
{
|
126
|
-
int ext_type;
|
116
|
+
int ext_type, ext_flags;
|
117
|
+
|
118
|
+
VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type, &ext_flags);
|
127
119
|
|
128
|
-
|
120
|
+
if(proc == Qnil) {
|
121
|
+
return false;
|
122
|
+
}
|
129
123
|
|
130
|
-
if(
|
124
|
+
if(ext_flags & MSGPACK_EXT_RECURSIVE) {
|
125
|
+
msgpack_buffer_t parent_buffer = pk->buffer;
|
126
|
+
msgpack_buffer_init(PACKER_BUFFER_(pk));
|
127
|
+
|
128
|
+
int exception_occured = 0;
|
129
|
+
msgpack_call_proc_args_t args = { proc, v, pk->to_msgpack_arg };
|
130
|
+
rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
|
131
|
+
|
132
|
+
if (exception_occured) {
|
133
|
+
msgpack_buffer_destroy(PACKER_BUFFER_(pk));
|
134
|
+
pk->buffer = parent_buffer;
|
135
|
+
rb_jump_tag(exception_occured); // re-raise the exception
|
136
|
+
} else {
|
137
|
+
VALUE payload = msgpack_buffer_all_as_string(PACKER_BUFFER_(pk));
|
138
|
+
StringValue(payload);
|
139
|
+
msgpack_buffer_destroy(PACKER_BUFFER_(pk));
|
140
|
+
pk->buffer = parent_buffer;
|
141
|
+
msgpack_packer_write_ext(pk, ext_type, payload);
|
142
|
+
}
|
143
|
+
} else {
|
131
144
|
VALUE payload = rb_funcall(proc, s_call, 1, v);
|
132
145
|
StringValue(payload);
|
133
146
|
msgpack_packer_write_ext(pk, ext_type, payload);
|
134
|
-
return true;
|
135
147
|
}
|
136
|
-
|
148
|
+
|
149
|
+
return true;
|
137
150
|
}
|
138
151
|
|
139
152
|
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
|
data/ext/msgpack/packer.h
CHANGED
@@ -32,6 +32,7 @@ struct msgpack_packer_t {
|
|
32
32
|
msgpack_buffer_t buffer;
|
33
33
|
|
34
34
|
bool compatibility_mode;
|
35
|
+
bool has_bigint_ext_type;
|
35
36
|
bool has_symbol_ext_type;
|
36
37
|
|
37
38
|
ID to_msgpack_method;
|
@@ -56,6 +57,8 @@ void msgpack_packer_destroy(msgpack_packer_t* pk);
|
|
56
57
|
|
57
58
|
void msgpack_packer_mark(msgpack_packer_t* pk);
|
58
59
|
|
60
|
+
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v);
|
61
|
+
|
59
62
|
static inline void msgpack_packer_set_to_msgpack_method(msgpack_packer_t* pk,
|
60
63
|
ID to_msgpack_method, VALUE to_msgpack_arg)
|
61
64
|
{
|
@@ -405,13 +408,7 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
|
|
405
408
|
{
|
406
409
|
return encindex == msgpack_rb_encindex_utf8
|
407
410
|
|| encindex == msgpack_rb_encindex_usascii
|
408
|
-
|
409
|
-
/* Because ENC_CODERANGE_ASCIIONLY does not scan string, it may return ENC_CODERANGE_UNKNOWN unlike */
|
410
|
-
/* rb_enc_str_asciionly_p. It is always faster than rb_str_encode if it is available. */
|
411
|
-
/* Very old Rubinius (< v1.3.1) doesn't have ENC_CODERANGE_ASCIIONLY. */
|
412
|
-
|| (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v))
|
413
|
-
#endif
|
414
|
-
;
|
411
|
+
|| (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v));
|
415
412
|
}
|
416
413
|
|
417
414
|
static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
|
@@ -469,9 +466,30 @@ static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE
|
|
469
466
|
|
470
467
|
static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
|
471
468
|
{
|
469
|
+
int leading_zero_bits;
|
470
|
+
size_t required_size = rb_absint_size(v, &leading_zero_bits);
|
471
|
+
|
472
472
|
if(RBIGNUM_POSITIVE_P(v)) {
|
473
|
+
if(required_size > 8 && pk->has_bigint_ext_type) {
|
474
|
+
if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
475
|
+
return;
|
476
|
+
}
|
477
|
+
// if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
|
478
|
+
}
|
479
|
+
|
473
480
|
msgpack_packer_write_u64(pk, rb_big2ull(v));
|
474
481
|
} else {
|
482
|
+
if(leading_zero_bits == 0) {
|
483
|
+
required_size += 1;
|
484
|
+
}
|
485
|
+
|
486
|
+
if(required_size > 8 && pk->has_bigint_ext_type) {
|
487
|
+
if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
488
|
+
return;
|
489
|
+
}
|
490
|
+
// if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
|
491
|
+
}
|
492
|
+
|
475
493
|
msgpack_packer_write_long_long(pk, rb_big2ll(v));
|
476
494
|
}
|
477
495
|
}
|
data/ext/msgpack/packer_class.c
CHANGED
@@ -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
|
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
|
-
|
89
|
-
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
90
|
-
}
|
86
|
+
}
|
91
87
|
|
92
|
-
|
93
|
-
|
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,
|
107
|
+
v = rb_hash_aref(options, sym_compatibility_mode);
|
107
108
|
msgpack_packer_set_compat(pk, RTEST(v));
|
108
109
|
}
|
109
110
|
|
@@ -321,7 +322,7 @@ static VALUE Packer_write_to(VALUE self, VALUE io)
|
|
321
322
|
{
|
322
323
|
PACKER(self, pk);
|
323
324
|
size_t sz = msgpack_buffer_flush_to_io(PACKER_BUFFER_(pk), io, s_write, true);
|
324
|
-
return
|
325
|
+
return SIZET2NUM(sz);
|
325
326
|
}
|
326
327
|
|
327
328
|
//static VALUE Packer_append(VALUE self, VALUE string_or_buffer)
|
@@ -380,7 +381,7 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
|
380
381
|
rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
|
381
382
|
}
|
382
383
|
|
383
|
-
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);
|
384
385
|
|
385
386
|
if (ext_module == rb_cSymbol) {
|
386
387
|
pk->has_symbol_ext_type = true;
|
@@ -412,6 +413,8 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
|
|
412
413
|
s_to_msgpack = rb_intern("to_msgpack");
|
413
414
|
s_write = rb_intern("write");
|
414
415
|
|
416
|
+
sym_compatibility_mode = ID2SYM(rb_intern("compatibility_mode"));
|
417
|
+
|
415
418
|
msgpack_packer_static_init();
|
416
419
|
msgpack_packer_ext_registry_static_init();
|
417
420
|
|
@@ -43,12 +43,18 @@ 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
|
-
|
47
|
-
|
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
59
|
if (!RTEST(pkrg->hash)) {
|
54
60
|
pkrg->hash = rb_hash_new();
|
@@ -58,5 +64,8 @@ VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
|
|
58
64
|
/* clear lookup cache not to miss added type */
|
59
65
|
rb_hash_clear(pkrg->cache);
|
60
66
|
}
|
61
|
-
|
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);
|
62
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,12 +62,13 @@ 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
|
|
@@ -74,6 +77,7 @@ static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registr
|
|
74
77
|
VALUE type_inht = rb_hash_lookup(pkrg->cache, lookup_class);
|
75
78
|
if(type_inht != Qnil) {
|
76
79
|
*ext_type_result = FIX2INT(rb_ary_entry(type_inht, 0));
|
80
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 3));
|
77
81
|
return rb_ary_entry(type_inht, 1);
|
78
82
|
}
|
79
83
|
}
|
@@ -82,7 +86,7 @@ static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registr
|
|
82
86
|
}
|
83
87
|
|
84
88
|
static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_registry_t* pkrg,
|
85
|
-
VALUE instance, int* ext_type_result)
|
89
|
+
VALUE instance, int* ext_type_result, int* ext_flags_result)
|
86
90
|
{
|
87
91
|
VALUE type;
|
88
92
|
|
@@ -97,7 +101,7 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
|
|
97
101
|
* `rb_class_of` returns the singleton_class if the object has one, or the "real class" otherwise.
|
98
102
|
*/
|
99
103
|
VALUE lookup_class = rb_class_of(instance);
|
100
|
-
type = msgpack_packer_ext_registry_fetch(pkrg, lookup_class, ext_type_result);
|
104
|
+
type = msgpack_packer_ext_registry_fetch(pkrg, lookup_class, ext_type_result, ext_flags_result);
|
101
105
|
if(type != Qnil) {
|
102
106
|
return type;
|
103
107
|
}
|
@@ -108,7 +112,7 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
|
|
108
112
|
*/
|
109
113
|
VALUE real_class = rb_obj_class(instance);
|
110
114
|
if(lookup_class != real_class) {
|
111
|
-
type = msgpack_packer_ext_registry_fetch(pkrg, real_class, ext_type_result);
|
115
|
+
type = msgpack_packer_ext_registry_fetch(pkrg, real_class, ext_type_result, ext_flags_result);
|
112
116
|
if(type != Qnil) {
|
113
117
|
return type;
|
114
118
|
}
|
@@ -130,6 +134,7 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
|
|
130
134
|
}
|
131
135
|
rb_hash_aset(pkrg->cache, lookup_class, superclass_type);
|
132
136
|
*ext_type_result = FIX2INT(rb_ary_entry(superclass_type, 0));
|
137
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 3));
|
133
138
|
return rb_ary_entry(superclass_type, 1);
|
134
139
|
}
|
135
140
|
|