msgpack 1.4.3 → 1.5.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +7 -6
- data/ChangeLog +18 -0
- data/README.md +22 -0
- data/Rakefile +1 -2
- data/doclib/msgpack/factory.rb +46 -3
- data/doclib/msgpack/packer.rb +5 -4
- data/doclib/msgpack/unpacker.rb +2 -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 +45 -18
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +28 -40
- 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.h +2 -2
- data/ext/msgpack/buffer_class.c +23 -15
- data/ext/msgpack/factory_class.c +78 -16
- data/ext/msgpack/packer.c +42 -5
- data/ext/msgpack/packer.h +24 -0
- data/ext/msgpack/packer_class.c +29 -22
- data/ext/msgpack/packer_ext_registry.c +23 -9
- data/ext/msgpack/packer_ext_registry.h +38 -31
- data/ext/msgpack/unpacker.c +37 -19
- data/ext/msgpack/unpacker.h +2 -2
- data/ext/msgpack/unpacker_class.c +26 -45
- data/ext/msgpack/unpacker_ext_registry.c +40 -16
- data/ext/msgpack/unpacker_ext_registry.h +21 -14
- data/lib/msgpack/bigint.rb +69 -0
- data/lib/msgpack/factory.rb +103 -0
- data/lib/msgpack/symbol.rb +8 -1
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +4 -5
- data/msgpack.gemspec +1 -2
- data/spec/bigint_spec.rb +26 -0
- data/spec/factory_spec.rb +263 -14
- data/spec/spec_helper.rb +3 -4
- data/spec/timestamp_spec.rb +0 -2
- data/spec/unpacker_spec.rb +22 -3
- metadata +7 -29
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
|
|
@@ -281,7 +282,7 @@ static VALUE Packer_flush(VALUE self)
|
|
281
282
|
return self;
|
282
283
|
}
|
283
284
|
|
284
|
-
static VALUE
|
285
|
+
static VALUE Packer_reset(VALUE self)
|
285
286
|
{
|
286
287
|
PACKER(self, pk);
|
287
288
|
msgpack_buffer_clear(PACKER_BUFFER_(pk));
|
@@ -339,7 +340,10 @@ static VALUE Packer_write_to(VALUE self, VALUE io)
|
|
339
340
|
static VALUE Packer_registered_types_internal(VALUE self)
|
340
341
|
{
|
341
342
|
PACKER(self, pk);
|
342
|
-
|
343
|
+
if (RTEST(pk->ext_registry.hash)) {
|
344
|
+
return rb_hash_dup(pk->ext_registry.hash);
|
345
|
+
}
|
346
|
+
return rb_hash_new();
|
343
347
|
}
|
344
348
|
|
345
349
|
static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
@@ -377,7 +381,7 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
|
377
381
|
rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
|
378
382
|
}
|
379
383
|
|
380
|
-
msgpack_packer_ext_registry_put(&pk->ext_registry, ext_module, ext_type, proc, arg);
|
384
|
+
msgpack_packer_ext_registry_put(&pk->ext_registry, ext_module, ext_type, 0, proc, arg);
|
381
385
|
|
382
386
|
if (ext_module == rb_cSymbol) {
|
383
387
|
pk->has_symbol_ext_type = true;
|
@@ -409,6 +413,8 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
|
|
409
413
|
s_to_msgpack = rb_intern("to_msgpack");
|
410
414
|
s_write = rb_intern("write");
|
411
415
|
|
416
|
+
sym_compatibility_mode = ID2SYM(rb_intern("compatibility_mode"));
|
417
|
+
|
412
418
|
msgpack_packer_static_init();
|
413
419
|
msgpack_packer_ext_registry_static_init();
|
414
420
|
|
@@ -440,7 +446,8 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
|
|
440
446
|
rb_define_method(cMessagePack_Packer, "flush", Packer_flush, 0);
|
441
447
|
|
442
448
|
/* delegation methods */
|
443
|
-
rb_define_method(cMessagePack_Packer, "
|
449
|
+
rb_define_method(cMessagePack_Packer, "reset", Packer_reset, 0);
|
450
|
+
rb_define_alias(cMessagePack_Packer, "clear", "reset");
|
444
451
|
rb_define_method(cMessagePack_Packer, "size", Packer_size, 0);
|
445
452
|
rb_define_method(cMessagePack_Packer, "empty?", Packer_empty_p, 0);
|
446
453
|
rb_define_method(cMessagePack_Packer, "write_to", Packer_write_to, 1);
|
@@ -30,8 +30,8 @@ void msgpack_packer_ext_registry_static_destroy()
|
|
30
30
|
|
31
31
|
void msgpack_packer_ext_registry_init(msgpack_packer_ext_registry_t* pkrg)
|
32
32
|
{
|
33
|
-
pkrg->hash =
|
34
|
-
pkrg->cache =
|
33
|
+
pkrg->hash = Qnil;
|
34
|
+
pkrg->cache = Qnil;
|
35
35
|
}
|
36
36
|
|
37
37
|
void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
|
@@ -43,15 +43,29 @@ void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
|
|
43
43
|
void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
|
44
44
|
msgpack_packer_ext_registry_t* dst)
|
45
45
|
{
|
46
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
59
|
+
if (!RTEST(pkrg->hash)) {
|
60
|
+
pkrg->hash = rb_hash_new();
|
61
|
+
}
|
62
|
+
|
63
|
+
if (RTEST(pkrg->cache)) {
|
64
|
+
/* clear lookup cache not to miss added type */
|
65
|
+
rb_hash_clear(pkrg->cache);
|
66
|
+
}
|
67
|
+
|
68
|
+
// TODO: Ruby embeded array limit is 3, merging `proc` and `arg` would be good.
|
69
|
+
VALUE entry = rb_ary_new3(4, INT2FIX(ext_type), proc, arg, INT2FIX(flags));
|
70
|
+
return rb_hash_aset(pkrg->hash, ext_module, entry);
|
57
71
|
}
|
@@ -21,6 +21,8 @@
|
|
21
21
|
#include "compat.h"
|
22
22
|
#include "ruby.h"
|
23
23
|
|
24
|
+
#define MSGPACK_EXT_RECURSIVE 0b0001
|
25
|
+
|
24
26
|
struct msgpack_packer_ext_registry_t;
|
25
27
|
typedef struct msgpack_packer_ext_registry_t msgpack_packer_ext_registry_t;
|
26
28
|
|
@@ -44,7 +46,7 @@ void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
|
|
44
46
|
msgpack_packer_ext_registry_t* dst);
|
45
47
|
|
46
48
|
VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
|
47
|
-
VALUE ext_module, int ext_type, VALUE proc, VALUE arg);
|
49
|
+
VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
|
48
50
|
|
49
51
|
static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
|
50
52
|
{
|
@@ -60,59 +62,60 @@ static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
|
|
60
62
|
}
|
61
63
|
|
62
64
|
static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registry_t* pkrg,
|
63
|
-
VALUE lookup_class, int* ext_type_result)
|
65
|
+
VALUE lookup_class, int* ext_type_result, int* ext_flags_result)
|
64
66
|
{
|
65
67
|
// fetch lookup_class from hash, which is a hash to register classes
|
66
68
|
VALUE type = rb_hash_lookup(pkrg->hash, lookup_class);
|
67
69
|
if(type != Qnil) {
|
68
70
|
*ext_type_result = FIX2INT(rb_ary_entry(type, 0));
|
71
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(type, 3));
|
69
72
|
return rb_ary_entry(type, 1);
|
70
73
|
}
|
71
74
|
|
72
75
|
// fetch lookup_class from cache, which stores results of searching ancestors from pkrg->hash
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
76
|
+
if (RTEST(pkrg->cache)) {
|
77
|
+
VALUE type_inht = rb_hash_lookup(pkrg->cache, lookup_class);
|
78
|
+
if(type_inht != Qnil) {
|
79
|
+
*ext_type_result = FIX2INT(rb_ary_entry(type_inht, 0));
|
80
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 3));
|
81
|
+
return rb_ary_entry(type_inht, 1);
|
82
|
+
}
|
77
83
|
}
|
78
84
|
|
79
85
|
return Qnil;
|
80
86
|
}
|
81
87
|
|
82
88
|
static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_registry_t* pkrg,
|
83
|
-
VALUE instance, int* ext_type_result)
|
89
|
+
VALUE instance, int* ext_type_result, int* ext_flags_result)
|
84
90
|
{
|
85
|
-
VALUE lookup_class;
|
86
91
|
VALUE type;
|
87
92
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
* Objects of type Integer (Fixnum, Bignum), Float, Symbol and frozen
|
92
|
-
* String have no singleton class and raise a TypeError when trying to get
|
93
|
-
* it. See implementation of #singleton_class in ruby's source code:
|
94
|
-
* VALUE rb_singleton_class(VALUE obj);
|
95
|
-
*
|
96
|
-
* Since all but symbols are already filtered out when reaching this code
|
97
|
-
* only symbols are checked here.
|
98
|
-
*/
|
99
|
-
if (!SYMBOL_P(instance)) {
|
100
|
-
lookup_class = rb_singleton_class(instance);
|
101
|
-
|
102
|
-
type = msgpack_packer_ext_registry_fetch(pkrg, lookup_class, ext_type_result);
|
93
|
+
if (pkrg->hash == Qnil) { // No extensions registered
|
94
|
+
return Qnil;
|
95
|
+
}
|
103
96
|
|
104
|
-
|
105
|
-
|
106
|
-
|
97
|
+
/*
|
98
|
+
* 1. check whether singleton_class or class of this instance is registered (or resolved in past) or not.
|
99
|
+
*
|
100
|
+
* Objects of type Integer (Fixnum, Bignum), Float, Symbol and frozen
|
101
|
+
* `rb_class_of` returns the singleton_class if the object has one, or the "real class" otherwise.
|
102
|
+
*/
|
103
|
+
VALUE lookup_class = rb_class_of(instance);
|
104
|
+
type = msgpack_packer_ext_registry_fetch(pkrg, lookup_class, ext_type_result, ext_flags_result);
|
105
|
+
if(type != Qnil) {
|
106
|
+
return type;
|
107
107
|
}
|
108
108
|
|
109
109
|
/*
|
110
|
-
* 2. check the class of instance is registered
|
110
|
+
* 2. If the object had a singleton_class check if the real class of instance is registered
|
111
|
+
* (or resolved in past) or not.
|
111
112
|
*/
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
113
|
+
VALUE real_class = rb_obj_class(instance);
|
114
|
+
if(lookup_class != real_class) {
|
115
|
+
type = msgpack_packer_ext_registry_fetch(pkrg, real_class, ext_type_result, ext_flags_result);
|
116
|
+
if(type != Qnil) {
|
117
|
+
return type;
|
118
|
+
}
|
116
119
|
}
|
117
120
|
|
118
121
|
/*
|
@@ -126,8 +129,12 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
|
|
126
129
|
VALUE superclass = args[1];
|
127
130
|
if(superclass != Qnil) {
|
128
131
|
VALUE superclass_type = rb_hash_lookup(pkrg->hash, superclass);
|
132
|
+
if (!RTEST(pkrg->cache)) {
|
133
|
+
pkrg->cache = rb_hash_new();
|
134
|
+
}
|
129
135
|
rb_hash_aset(pkrg->cache, lookup_class, superclass_type);
|
130
136
|
*ext_type_result = FIX2INT(rb_ary_entry(superclass_type, 0));
|
137
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 3));
|
131
138
|
return rb_ary_entry(superclass_type, 1);
|
132
139
|
}
|
133
140
|
|
data/ext/msgpack/unpacker.c
CHANGED
@@ -52,9 +52,9 @@ void msgpack_unpacker_static_destroy()
|
|
52
52
|
|
53
53
|
#define HEAD_BYTE_REQUIRED 0xc1
|
54
54
|
|
55
|
-
|
55
|
+
msgpack_unpacker_t* _msgpack_unpacker_new(void)
|
56
56
|
{
|
57
|
-
|
57
|
+
msgpack_unpacker_t* uk = ZALLOC_N(msgpack_unpacker_t, 1);
|
58
58
|
|
59
59
|
msgpack_buffer_init(UNPACKER_BUFFER_(uk));
|
60
60
|
|
@@ -71,6 +71,8 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
|
71
71
|
uk->stack = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
|
72
72
|
#endif
|
73
73
|
uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
74
|
+
|
75
|
+
return uk;
|
74
76
|
}
|
75
77
|
|
76
78
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
|
@@ -164,14 +166,17 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
|
|
164
166
|
return object_complete_symbol(uk, rb_str_intern(str));
|
165
167
|
}
|
166
168
|
|
167
|
-
|
169
|
+
int ext_flags;
|
170
|
+
VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
|
171
|
+
|
168
172
|
if(proc != Qnil) {
|
169
|
-
VALUE obj
|
173
|
+
VALUE obj;
|
174
|
+
obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
|
170
175
|
return object_complete(uk, obj);
|
171
176
|
}
|
172
177
|
|
173
178
|
if(uk->allow_unknown_ext) {
|
174
|
-
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
|
179
|
+
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
|
175
180
|
return object_complete(uk, obj);
|
176
181
|
}
|
177
182
|
|
@@ -281,29 +286,42 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
281
286
|
{
|
282
287
|
/* assuming uk->reading_raw == Qnil */
|
283
288
|
|
289
|
+
int ext_flags;
|
290
|
+
VALUE proc;
|
291
|
+
|
292
|
+
if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
|
293
|
+
proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
|
294
|
+
if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
|
295
|
+
VALUE obj;
|
296
|
+
uk->last_object = Qnil;
|
297
|
+
reset_head_byte(uk);
|
298
|
+
size_t ext_size = uk->reading_raw_remaining;
|
299
|
+
uk->reading_raw_remaining = 0;
|
300
|
+
obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
|
301
|
+
msgpack_buffer_skip(UNPACKER_BUFFER_(uk), ext_size);
|
302
|
+
return object_complete(uk, obj);
|
303
|
+
}
|
304
|
+
}
|
305
|
+
|
284
306
|
/* try optimized read */
|
285
307
|
size_t length = uk->reading_raw_remaining;
|
286
308
|
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
|
287
309
|
int ret;
|
288
310
|
if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
|
289
|
-
VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length);
|
311
|
+
VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
|
290
312
|
ret = object_complete_symbol(uk, symbol);
|
291
313
|
} else {
|
292
|
-
|
293
|
-
* because rb_hash_aset freezes keys and it causes copying */
|
294
|
-
bool will_freeze = uk->freeze || is_reading_map_key(uk);
|
295
|
-
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
314
|
+
bool will_freeze = uk->freeze;
|
296
315
|
if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
|
316
|
+
/* don't use zerocopy for hash keys but get a frozen string directly
|
317
|
+
* because rb_hash_aset freezes keys and it causes copying */
|
318
|
+
will_freeze = will_freeze || is_reading_map_key(uk);
|
319
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
297
320
|
ret = object_complete(uk, string);
|
298
321
|
} else {
|
322
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, false, false);
|
299
323
|
ret = object_complete_ext(uk, raw_type, string);
|
300
324
|
}
|
301
|
-
|
302
|
-
# if !HASH_ASET_DEDUPE
|
303
|
-
if(will_freeze) {
|
304
|
-
rb_obj_freeze(string);
|
305
|
-
}
|
306
|
-
# endif
|
307
325
|
}
|
308
326
|
uk->reading_raw_remaining = 0;
|
309
327
|
return ret;
|
@@ -373,7 +391,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
373
391
|
uint8_t length = cb->u8;
|
374
392
|
int ext_type = (signed char) cb->buffer[1];
|
375
393
|
if(length == 0) {
|
376
|
-
return object_complete_ext(uk, ext_type,
|
394
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
377
395
|
}
|
378
396
|
uk->reading_raw_remaining = length;
|
379
397
|
return read_raw_body_begin(uk, ext_type);
|
@@ -385,7 +403,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
385
403
|
uint16_t length = _msgpack_be16(cb->u16);
|
386
404
|
int ext_type = (signed char) cb->buffer[2];
|
387
405
|
if(length == 0) {
|
388
|
-
return object_complete_ext(uk, ext_type,
|
406
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
389
407
|
}
|
390
408
|
uk->reading_raw_remaining = length;
|
391
409
|
return read_raw_body_begin(uk, ext_type);
|
@@ -397,7 +415,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
397
415
|
uint32_t length = _msgpack_be32(cb->u32);
|
398
416
|
int ext_type = (signed char) cb->buffer[4];
|
399
417
|
if(length == 0) {
|
400
|
-
return object_complete_ext(uk, ext_type,
|
418
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
401
419
|
}
|
402
420
|
uk->reading_raw_remaining = length;
|
403
421
|
return read_raw_body_begin(uk, ext_type);
|
data/ext/msgpack/unpacker.h
CHANGED
@@ -60,7 +60,7 @@ struct msgpack_unpacker_t {
|
|
60
60
|
|
61
61
|
VALUE buffer_ref;
|
62
62
|
|
63
|
-
msgpack_unpacker_ext_registry_t ext_registry;
|
63
|
+
msgpack_unpacker_ext_registry_t *ext_registry;
|
64
64
|
|
65
65
|
/* options */
|
66
66
|
bool symbolize_keys;
|
@@ -86,7 +86,7 @@ void msgpack_unpacker_static_init();
|
|
86
86
|
|
87
87
|
void msgpack_unpacker_static_destroy();
|
88
88
|
|
89
|
-
|
89
|
+
msgpack_unpacker_t* _msgpack_unpacker_new(void);
|
90
90
|
|
91
91
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk);
|
92
92
|
|
@@ -33,6 +33,10 @@ static VALUE eUnexpectedTypeError;
|
|
33
33
|
static VALUE eUnknownExtTypeError;
|
34
34
|
static VALUE mTypeError; // obsoleted. only for backward compatibility. See #86.
|
35
35
|
|
36
|
+
static VALUE sym_symbolize_keys;
|
37
|
+
static VALUE sym_freeze;
|
38
|
+
static VALUE sym_allow_unknown_ext;
|
39
|
+
|
36
40
|
#define UNPACKER(from, name) \
|
37
41
|
msgpack_unpacker_t *name = NULL; \
|
38
42
|
Data_Get_Struct(from, msgpack_unpacker_t, name); \
|
@@ -45,7 +49,7 @@ static void Unpacker_free(msgpack_unpacker_t* uk)
|
|
45
49
|
if(uk == NULL) {
|
46
50
|
return;
|
47
51
|
}
|
48
|
-
|
52
|
+
msgpack_unpacker_ext_registry_release(uk->ext_registry);
|
49
53
|
_msgpack_unpacker_destroy(uk);
|
50
54
|
xfree(uk);
|
51
55
|
}
|
@@ -53,13 +57,12 @@ static void Unpacker_free(msgpack_unpacker_t* uk)
|
|
53
57
|
static void Unpacker_mark(msgpack_unpacker_t* uk)
|
54
58
|
{
|
55
59
|
msgpack_unpacker_mark(uk);
|
56
|
-
msgpack_unpacker_ext_registry_mark(
|
60
|
+
msgpack_unpacker_ext_registry_mark(uk->ext_registry);
|
57
61
|
}
|
58
62
|
|
59
63
|
VALUE MessagePack_Unpacker_alloc(VALUE klass)
|
60
64
|
{
|
61
|
-
msgpack_unpacker_t* uk =
|
62
|
-
_msgpack_unpacker_init(uk);
|
65
|
+
msgpack_unpacker_t* uk = _msgpack_unpacker_new();
|
63
66
|
|
64
67
|
VALUE self = Data_Wrap_Struct(klass, Unpacker_mark, Unpacker_free, uk);
|
65
68
|
return self;
|
@@ -84,7 +87,7 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
84
87
|
} else if(argc == 2) {
|
85
88
|
io = argv[0];
|
86
89
|
options = argv[1];
|
87
|
-
if(rb_type(options) != T_HASH) {
|
90
|
+
if(options != Qnil && rb_type(options) != T_HASH) {
|
88
91
|
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
89
92
|
}
|
90
93
|
|
@@ -94,7 +97,6 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
94
97
|
|
95
98
|
UNPACKER(self, uk);
|
96
99
|
|
97
|
-
msgpack_unpacker_ext_registry_init(&uk->ext_registry);
|
98
100
|
uk->buffer_ref = MessagePack_Buffer_wrap(UNPACKER_BUFFER_(uk), self);
|
99
101
|
|
100
102
|
MessagePack_Buffer_set_options(UNPACKER_BUFFER_(uk), io, options);
|
@@ -102,13 +104,13 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
102
104
|
if(options != Qnil) {
|
103
105
|
VALUE v;
|
104
106
|
|
105
|
-
v = rb_hash_aref(options,
|
107
|
+
v = rb_hash_aref(options, sym_symbolize_keys);
|
106
108
|
msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
|
107
109
|
|
108
|
-
v = rb_hash_aref(options,
|
110
|
+
v = rb_hash_aref(options, sym_freeze);
|
109
111
|
msgpack_unpacker_set_freeze(uk, RTEST(v));
|
110
112
|
|
111
|
-
v = rb_hash_aref(options,
|
113
|
+
v = rb_hash_aref(options, sym_allow_unknown_ext);
|
112
114
|
msgpack_unpacker_set_allow_unknown_ext(uk, RTEST(v));
|
113
115
|
}
|
114
116
|
|
@@ -133,7 +135,7 @@ static VALUE Unpacker_allow_unknown_ext_p(VALUE self)
|
|
133
135
|
return uk->allow_unknown_ext ? Qtrue : Qfalse;
|
134
136
|
}
|
135
137
|
|
136
|
-
static void raise_unpacker_error(int r)
|
138
|
+
NORETURN(static void raise_unpacker_error(int r))
|
137
139
|
{
|
138
140
|
switch(r) {
|
139
141
|
case PRIMITIVE_EOF:
|
@@ -145,6 +147,7 @@ static void raise_unpacker_error(int r)
|
|
145
147
|
case PRIMITIVE_UNEXPECTED_TYPE:
|
146
148
|
rb_raise(eUnexpectedTypeError, "unexpected type");
|
147
149
|
case PRIMITIVE_UNEXPECTED_EXT_TYPE:
|
150
|
+
// rb_bug("unexpected extension type");
|
148
151
|
rb_raise(eUnknownExtTypeError, "unexpected extension type");
|
149
152
|
default:
|
150
153
|
rb_raise(eUnpackError, "logically unknown error %d", r);
|
@@ -222,34 +225,6 @@ static VALUE Unpacker_read_map_header(VALUE self)
|
|
222
225
|
return ULONG2NUM(size);
|
223
226
|
}
|
224
227
|
|
225
|
-
static VALUE Unpacker_peek_next_type(VALUE self)
|
226
|
-
{
|
227
|
-
UNPACKER(self, uk);
|
228
|
-
|
229
|
-
int r = msgpack_unpacker_peek_next_object_type(uk);
|
230
|
-
if(r < 0) {
|
231
|
-
raise_unpacker_error(r);
|
232
|
-
}
|
233
|
-
|
234
|
-
switch((enum msgpack_unpacker_object_type) r) {
|
235
|
-
case TYPE_NIL:
|
236
|
-
return rb_intern("nil");
|
237
|
-
case TYPE_BOOLEAN:
|
238
|
-
return rb_intern("boolean");
|
239
|
-
case TYPE_INTEGER:
|
240
|
-
return rb_intern("integer");
|
241
|
-
case TYPE_FLOAT:
|
242
|
-
return rb_intern("float");
|
243
|
-
case TYPE_RAW:
|
244
|
-
return rb_intern("raw");
|
245
|
-
case TYPE_ARRAY:
|
246
|
-
return rb_intern("array");
|
247
|
-
case TYPE_MAP:
|
248
|
-
return rb_intern("map");
|
249
|
-
default:
|
250
|
-
rb_raise(eUnpackError, "logically unknown type %d", r);
|
251
|
-
}
|
252
|
-
}
|
253
228
|
|
254
229
|
static VALUE Unpacker_feed(VALUE self, VALUE data)
|
255
230
|
{
|
@@ -296,9 +271,10 @@ static VALUE Unpacker_each_impl(VALUE self)
|
|
296
271
|
}
|
297
272
|
}
|
298
273
|
|
299
|
-
static VALUE Unpacker_rescue_EOFError(VALUE
|
274
|
+
static VALUE Unpacker_rescue_EOFError(VALUE args, VALUE error)
|
300
275
|
{
|
301
|
-
UNUSED(
|
276
|
+
UNUSED(args);
|
277
|
+
UNUSED(error);
|
302
278
|
return Qnil;
|
303
279
|
}
|
304
280
|
|
@@ -347,9 +323,11 @@ static VALUE Unpacker_registered_types_internal(VALUE self)
|
|
347
323
|
UNPACKER(self, uk);
|
348
324
|
|
349
325
|
VALUE mapping = rb_hash_new();
|
350
|
-
|
351
|
-
|
352
|
-
|
326
|
+
if (uk->ext_registry) {
|
327
|
+
for(int i=0; i < 256; i++) {
|
328
|
+
if(uk->ext_registry->array[i] != Qnil) {
|
329
|
+
rb_hash_aset(mapping, INT2FIX(i - 128), uk->ext_registry->array[i]);
|
330
|
+
}
|
353
331
|
}
|
354
332
|
}
|
355
333
|
|
@@ -388,7 +366,7 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
|
|
388
366
|
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
|
389
367
|
}
|
390
368
|
|
391
|
-
msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, proc, arg);
|
369
|
+
msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, 0, proc, arg);
|
392
370
|
|
393
371
|
return Qnil;
|
394
372
|
}
|
@@ -438,6 +416,10 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
438
416
|
|
439
417
|
eUnknownExtTypeError = rb_define_class_under(mMessagePack, "UnknownExtTypeError", eUnpackError);
|
440
418
|
|
419
|
+
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
420
|
+
sym_freeze = ID2SYM(rb_intern("freeze"));
|
421
|
+
sym_allow_unknown_ext = ID2SYM(rb_intern("allow_unknown_ext"));
|
422
|
+
|
441
423
|
rb_define_alloc_func(cMessagePack_Unpacker, MessagePack_Unpacker_alloc);
|
442
424
|
|
443
425
|
rb_define_method(cMessagePack_Unpacker, "initialize", MessagePack_Unpacker_initialize, -1);
|
@@ -451,7 +433,6 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
451
433
|
rb_define_method(cMessagePack_Unpacker, "skip_nil", Unpacker_skip_nil, 0);
|
452
434
|
rb_define_method(cMessagePack_Unpacker, "read_array_header", Unpacker_read_array_header, 0);
|
453
435
|
rb_define_method(cMessagePack_Unpacker, "read_map_header", Unpacker_read_map_header, 0);
|
454
|
-
//rb_define_method(cMessagePack_Unpacker, "peek_next_type", Unpacker_peek_next_type, 0); // TODO
|
455
436
|
rb_define_method(cMessagePack_Unpacker, "feed", Unpacker_feed, 1);
|
456
437
|
rb_define_method(cMessagePack_Unpacker, "feed_reference", Unpacker_feed_reference, 1);
|
457
438
|
rb_define_method(cMessagePack_Unpacker, "each", Unpacker_each, 0);
|
@@ -27,36 +27,60 @@ void msgpack_unpacker_ext_registry_static_init()
|
|
27
27
|
s_dup = rb_intern("dup");
|
28
28
|
}
|
29
29
|
|
30
|
+
|
30
31
|
void msgpack_unpacker_ext_registry_static_destroy()
|
31
32
|
{ }
|
32
33
|
|
33
|
-
void
|
34
|
+
void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg)
|
34
35
|
{
|
35
|
-
|
36
|
-
|
36
|
+
if (ukrg) {
|
37
|
+
for(int i=0; i < 256; i++) {
|
38
|
+
if (ukrg->array[i] != Qnil) {
|
39
|
+
rb_gc_mark(ukrg->array[i]);
|
40
|
+
}
|
41
|
+
}
|
37
42
|
}
|
38
43
|
}
|
39
44
|
|
40
|
-
|
45
|
+
msgpack_unpacker_ext_registry_t* msgpack_unpacker_ext_registry_cow(msgpack_unpacker_ext_registry_t* src)
|
41
46
|
{
|
42
|
-
|
43
|
-
|
47
|
+
msgpack_unpacker_ext_registry_t* dst;
|
48
|
+
if (src) {
|
49
|
+
if (src->borrow_count) {
|
50
|
+
dst = ALLOC(msgpack_unpacker_ext_registry_t);
|
51
|
+
dst->borrow_count = 0;
|
52
|
+
MEMCPY(dst->array, src->array, VALUE, 256);
|
53
|
+
msgpack_unpacker_ext_registry_release(src);
|
54
|
+
return dst;
|
55
|
+
} else {
|
56
|
+
return src;
|
57
|
+
}
|
58
|
+
} else {
|
59
|
+
dst = ALLOC(msgpack_unpacker_ext_registry_t);
|
60
|
+
dst->borrow_count = 0;
|
61
|
+
for(int i=0; i < 256; i++) {
|
62
|
+
dst->array[i] = Qnil;
|
63
|
+
}
|
64
|
+
return dst;
|
44
65
|
}
|
45
66
|
}
|
46
67
|
|
47
|
-
void
|
48
|
-
msgpack_unpacker_ext_registry_t* dst)
|
68
|
+
void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg)
|
49
69
|
{
|
50
|
-
|
51
|
-
|
70
|
+
if (ukrg) {
|
71
|
+
if (ukrg->borrow_count) {
|
72
|
+
ukrg->borrow_count--;
|
73
|
+
} else {
|
74
|
+
xfree(ukrg);
|
75
|
+
}
|
52
76
|
}
|
53
77
|
}
|
54
78
|
|
55
|
-
|
56
|
-
VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
|
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)
|
57
81
|
{
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
82
|
+
msgpack_unpacker_ext_registry_t* ext_registry = msgpack_unpacker_ext_registry_cow(*ukrg);
|
83
|
+
|
84
|
+
ext_registry->array[ext_type + 128] = rb_ary_new3(4, ext_module, proc, arg, INT2FIX(flags));
|
85
|
+
*ukrg = ext_registry;
|
62
86
|
}
|