msgpack 1.4.4 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +4 -3
- data/ChangeLog +18 -0
- data/README.md +22 -0
- 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 +46 -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 +72 -32
- 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/spec/bigint_spec.rb +26 -0
- data/spec/factory_spec.rb +284 -14
- data/spec/spec_helper.rb +4 -4
- data/spec/timestamp_spec.rb +0 -2
- data/spec/unpacker_spec.rb +22 -3
- metadata +4 -2
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,19 @@ void msgpack_unpacker_static_destroy()
|
|
52
52
|
|
53
53
|
#define HEAD_BYTE_REQUIRED 0xc1
|
54
54
|
|
55
|
-
|
55
|
+
static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
|
56
|
+
#ifdef UNPACKER_STACK_RMEM
|
57
|
+
return msgpack_rmem_alloc(&s_stack_rmem);
|
58
|
+
/*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
|
59
|
+
#else
|
60
|
+
/*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
|
61
|
+
return xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
|
62
|
+
#endif
|
63
|
+
}
|
64
|
+
|
65
|
+
msgpack_unpacker_t* _msgpack_unpacker_new(void)
|
56
66
|
{
|
57
|
-
|
67
|
+
msgpack_unpacker_t* uk = ZALLOC_N(msgpack_unpacker_t, 1);
|
58
68
|
|
59
69
|
msgpack_buffer_init(UNPACKER_BUFFER_(uk));
|
60
70
|
|
@@ -63,24 +73,23 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
|
63
73
|
uk->last_object = Qnil;
|
64
74
|
uk->reading_raw = Qnil;
|
65
75
|
|
66
|
-
|
67
|
-
uk->stack = msgpack_rmem_alloc(&s_stack_rmem);
|
68
|
-
/*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
|
69
|
-
#else
|
70
|
-
/*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
|
71
|
-
uk->stack = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
|
72
|
-
#endif
|
76
|
+
uk->stack = _msgpack_unpacker_new_stack();
|
73
77
|
uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
78
|
+
|
79
|
+
return uk;
|
80
|
+
}
|
81
|
+
|
82
|
+
static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
|
83
|
+
#ifdef UNPACKER_STACK_RMEM
|
84
|
+
msgpack_rmem_free(&s_stack_rmem, stack);
|
85
|
+
#else
|
86
|
+
xfree(stack);
|
87
|
+
#endif
|
74
88
|
}
|
75
89
|
|
76
90
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
|
77
91
|
{
|
78
|
-
|
79
|
-
msgpack_rmem_free(&s_stack_rmem, uk->stack);
|
80
|
-
#else
|
81
|
-
xfree(uk->stack);
|
82
|
-
#endif
|
83
|
-
|
92
|
+
_msgpack_unpacker_free_stack(uk->stack);
|
84
93
|
msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
|
85
94
|
}
|
86
95
|
|
@@ -164,14 +173,17 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
|
|
164
173
|
return object_complete_symbol(uk, rb_str_intern(str));
|
165
174
|
}
|
166
175
|
|
167
|
-
|
176
|
+
int ext_flags;
|
177
|
+
VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
|
178
|
+
|
168
179
|
if(proc != Qnil) {
|
169
|
-
VALUE obj
|
180
|
+
VALUE obj;
|
181
|
+
obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
|
170
182
|
return object_complete(uk, obj);
|
171
183
|
}
|
172
184
|
|
173
185
|
if(uk->allow_unknown_ext) {
|
174
|
-
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
|
186
|
+
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
|
175
187
|
return object_complete(uk, obj);
|
176
188
|
}
|
177
189
|
|
@@ -281,29 +293,57 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
281
293
|
{
|
282
294
|
/* assuming uk->reading_raw == Qnil */
|
283
295
|
|
296
|
+
int ext_flags;
|
297
|
+
VALUE proc;
|
298
|
+
|
299
|
+
if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
|
300
|
+
proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
|
301
|
+
if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
|
302
|
+
VALUE obj;
|
303
|
+
uk->last_object = Qnil;
|
304
|
+
reset_head_byte(uk);
|
305
|
+
size_t ext_size = uk->reading_raw_remaining;
|
306
|
+
uk->reading_raw_remaining = 0;
|
307
|
+
|
308
|
+
msgpack_unpacker_stack_t* stack = uk->stack;
|
309
|
+
size_t stack_depth = uk->stack_depth;
|
310
|
+
size_t stack_capacity = uk->stack_capacity;
|
311
|
+
|
312
|
+
uk->stack = _msgpack_unpacker_new_stack();
|
313
|
+
uk->stack_depth = 0;
|
314
|
+
uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
315
|
+
|
316
|
+
obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
|
317
|
+
|
318
|
+
_msgpack_unpacker_free_stack(uk->stack);
|
319
|
+
uk->stack = stack;
|
320
|
+
uk->stack_depth = stack_depth;
|
321
|
+
uk->stack_capacity = stack_capacity;
|
322
|
+
|
323
|
+
msgpack_buffer_skip(UNPACKER_BUFFER_(uk), ext_size);
|
324
|
+
return object_complete(uk, obj);
|
325
|
+
}
|
326
|
+
}
|
327
|
+
|
284
328
|
/* try optimized read */
|
285
329
|
size_t length = uk->reading_raw_remaining;
|
286
330
|
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
|
287
331
|
int ret;
|
288
332
|
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);
|
333
|
+
VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
|
290
334
|
ret = object_complete_symbol(uk, symbol);
|
291
335
|
} 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);
|
336
|
+
bool will_freeze = uk->freeze;
|
296
337
|
if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
|
338
|
+
/* don't use zerocopy for hash keys but get a frozen string directly
|
339
|
+
* because rb_hash_aset freezes keys and it causes copying */
|
340
|
+
will_freeze = will_freeze || is_reading_map_key(uk);
|
341
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
297
342
|
ret = object_complete(uk, string);
|
298
343
|
} else {
|
344
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, false, false);
|
299
345
|
ret = object_complete_ext(uk, raw_type, string);
|
300
346
|
}
|
301
|
-
|
302
|
-
# if !HASH_ASET_DEDUPE
|
303
|
-
if(will_freeze) {
|
304
|
-
rb_obj_freeze(string);
|
305
|
-
}
|
306
|
-
# endif
|
307
347
|
}
|
308
348
|
uk->reading_raw_remaining = 0;
|
309
349
|
return ret;
|
@@ -373,7 +413,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
373
413
|
uint8_t length = cb->u8;
|
374
414
|
int ext_type = (signed char) cb->buffer[1];
|
375
415
|
if(length == 0) {
|
376
|
-
return object_complete_ext(uk, ext_type,
|
416
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
377
417
|
}
|
378
418
|
uk->reading_raw_remaining = length;
|
379
419
|
return read_raw_body_begin(uk, ext_type);
|
@@ -385,7 +425,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
385
425
|
uint16_t length = _msgpack_be16(cb->u16);
|
386
426
|
int ext_type = (signed char) cb->buffer[2];
|
387
427
|
if(length == 0) {
|
388
|
-
return object_complete_ext(uk, ext_type,
|
428
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
389
429
|
}
|
390
430
|
uk->reading_raw_remaining = length;
|
391
431
|
return read_raw_body_begin(uk, ext_type);
|
@@ -397,7 +437,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
397
437
|
uint32_t length = _msgpack_be32(cb->u32);
|
398
438
|
int ext_type = (signed char) cb->buffer[4];
|
399
439
|
if(length == 0) {
|
400
|
-
return object_complete_ext(uk, ext_type,
|
440
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
401
441
|
}
|
402
442
|
uk->reading_raw_remaining = length;
|
403
443
|
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);
|