msgpack 1.2.10 → 1.5.1
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 +57 -0
- data/.gitignore +3 -1
- data/.rubocop.yml +4 -1
- data/ChangeLog +60 -0
- data/Gemfile +3 -0
- data/README.md +264 -0
- data/Rakefile +1 -9
- data/doclib/msgpack/factory.rb +47 -3
- data/doclib/msgpack/packer.rb +5 -4
- data/doclib/msgpack/time.rb +22 -0
- data/doclib/msgpack/timestamp.rb +44 -0
- data/doclib/msgpack/unpacker.rb +2 -2
- data/ext/java/org/msgpack/jruby/Buffer.java +23 -16
- data/ext/java/org/msgpack/jruby/Decoder.java +46 -23
- data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +37 -49
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
- data/ext/java/org/msgpack/jruby/Factory.java +47 -7
- data/ext/java/org/msgpack/jruby/Packer.java +29 -17
- data/ext/java/org/msgpack/jruby/Unpacker.java +72 -37
- data/ext/msgpack/buffer.c +4 -16
- data/ext/msgpack/buffer.h +46 -5
- data/ext/msgpack/buffer_class.c +23 -15
- data/ext/msgpack/compat.h +1 -12
- data/ext/msgpack/extconf.rb +39 -7
- data/ext/msgpack/factory_class.c +87 -20
- data/ext/msgpack/packer.c +58 -8
- data/ext/msgpack/packer.h +24 -16
- data/ext/msgpack/packer_class.c +29 -31
- data/ext/msgpack/packer_ext_registry.c +22 -30
- data/ext/msgpack/packer_ext_registry.h +38 -31
- data/ext/msgpack/unpacker.c +102 -70
- data/ext/msgpack/unpacker.h +10 -2
- data/ext/msgpack/unpacker_class.c +35 -52
- 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 +21 -4
- data/lib/msgpack/time.rb +29 -0
- data/lib/msgpack/timestamp.rb +76 -0
- data/lib/msgpack/version.rb +4 -7
- data/lib/msgpack.rb +8 -12
- data/msgpack.gemspec +3 -7
- data/spec/bigint_spec.rb +26 -0
- data/spec/factory_spec.rb +299 -12
- data/spec/msgpack_spec.rb +1 -1
- data/spec/packer_spec.rb +18 -0
- data/spec/spec_helper.rb +30 -3
- data/spec/timestamp_spec.rb +159 -0
- data/spec/unpacker_spec.rb +135 -4
- metadata +21 -51
- data/.travis.yml +0 -43
- data/README.rdoc +0 -209
data/ext/msgpack/buffer_class.c
CHANGED
@@ -29,6 +29,11 @@ static ID s_write;
|
|
29
29
|
static ID s_append;
|
30
30
|
static ID s_close;
|
31
31
|
|
32
|
+
static VALUE sym_read_reference_threshold;
|
33
|
+
static VALUE sym_write_reference_threshold;
|
34
|
+
static VALUE sym_io_buffer_size;
|
35
|
+
|
36
|
+
|
32
37
|
#define BUFFER(from, name) \
|
33
38
|
msgpack_buffer_t *name = NULL; \
|
34
39
|
Data_Get_Struct(from, msgpack_buffer_t, name); \
|
@@ -62,24 +67,22 @@ static VALUE Buffer_alloc(VALUE klass)
|
|
62
67
|
|
63
68
|
static ID get_partial_read_method(VALUE io)
|
64
69
|
{
|
65
|
-
if(rb_respond_to(io, s_readpartial)) {
|
70
|
+
if(io != Qnil && rb_respond_to(io, s_readpartial)) {
|
66
71
|
return s_readpartial;
|
67
|
-
} else if(rb_respond_to(io, s_read)) {
|
68
|
-
return s_read;
|
69
|
-
} else {
|
70
|
-
return s_read;
|
71
72
|
}
|
73
|
+
return s_read;
|
72
74
|
}
|
73
75
|
|
74
76
|
static ID get_write_all_method(VALUE io)
|
75
77
|
{
|
76
|
-
if(
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
if(io != Qnil) {
|
79
|
+
if(rb_respond_to(io, s_write)) {
|
80
|
+
return s_write;
|
81
|
+
} else if(rb_respond_to(io, s_append)) {
|
82
|
+
return s_append;
|
83
|
+
}
|
82
84
|
}
|
85
|
+
return s_write;
|
83
86
|
}
|
84
87
|
|
85
88
|
void MessagePack_Buffer_set_options(msgpack_buffer_t* b, VALUE io, VALUE options)
|
@@ -91,17 +94,17 @@ void MessagePack_Buffer_set_options(msgpack_buffer_t* b, VALUE io, VALUE options
|
|
91
94
|
if(options != Qnil) {
|
92
95
|
VALUE v;
|
93
96
|
|
94
|
-
v = rb_hash_aref(options,
|
97
|
+
v = rb_hash_aref(options, sym_read_reference_threshold);
|
95
98
|
if(v != Qnil) {
|
96
99
|
msgpack_buffer_set_read_reference_threshold(b, NUM2ULONG(v));
|
97
100
|
}
|
98
101
|
|
99
|
-
v = rb_hash_aref(options,
|
102
|
+
v = rb_hash_aref(options, sym_write_reference_threshold);
|
100
103
|
if(v != Qnil) {
|
101
104
|
msgpack_buffer_set_write_reference_threshold(b, NUM2ULONG(v));
|
102
105
|
}
|
103
106
|
|
104
|
-
v = rb_hash_aref(options,
|
107
|
+
v = rb_hash_aref(options, sym_io_buffer_size);
|
105
108
|
if(v != Qnil) {
|
106
109
|
msgpack_buffer_set_io_buffer_size(b, NUM2ULONG(v));
|
107
110
|
}
|
@@ -245,10 +248,11 @@ static VALUE read_until_eof_rescue(VALUE args)
|
|
245
248
|
return Qnil;
|
246
249
|
}
|
247
250
|
|
248
|
-
static VALUE read_until_eof_error(VALUE args)
|
251
|
+
static VALUE read_until_eof_error(VALUE args, VALUE error)
|
249
252
|
{
|
250
253
|
/* ignore EOFError */
|
251
254
|
UNUSED(args);
|
255
|
+
UNUSED(error);
|
252
256
|
return Qnil;
|
253
257
|
}
|
254
258
|
|
@@ -480,6 +484,10 @@ void MessagePack_Buffer_module_init(VALUE mMessagePack)
|
|
480
484
|
s_append = rb_intern("<<");
|
481
485
|
s_close = rb_intern("close");
|
482
486
|
|
487
|
+
sym_read_reference_threshold = ID2SYM(rb_intern("read_reference_threshold"));
|
488
|
+
sym_write_reference_threshold = ID2SYM(rb_intern("write_reference_threshold"));
|
489
|
+
sym_io_buffer_size = ID2SYM(rb_intern("io_buffer_size"));
|
490
|
+
|
483
491
|
msgpack_buffer_static_init();
|
484
492
|
|
485
493
|
cMessagePack_Buffer = rb_define_class_under(mMessagePack, "Buffer", rb_cObject);
|
data/ext/msgpack/compat.h
CHANGED
@@ -20,6 +20,7 @@
|
|
20
20
|
|
21
21
|
#include <stdbool.h>
|
22
22
|
#include "ruby.h"
|
23
|
+
#include "ruby/encoding.h"
|
23
24
|
|
24
25
|
#if defined(HAVE_RUBY_ST_H)
|
25
26
|
# include "ruby/st.h" /* ruby hash on Ruby 1.9 */
|
@@ -38,18 +39,6 @@
|
|
38
39
|
# define ZALLOC_N(type,n) RB_ZALLOC_N(type,n)
|
39
40
|
#endif
|
40
41
|
|
41
|
-
/*
|
42
|
-
* COMPAT_HAVE_ENCODING
|
43
|
-
*/
|
44
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
45
|
-
# include "ruby/encoding.h"
|
46
|
-
# define COMPAT_HAVE_ENCODING
|
47
|
-
#endif
|
48
|
-
|
49
|
-
#if defined(__MACRUBY__) /* MacRuby */
|
50
|
-
# undef COMPAT_HAVE_ENCODING
|
51
|
-
#endif
|
52
|
-
|
53
42
|
|
54
43
|
/*
|
55
44
|
* define STR_DUP_LIKELY_DOES_COPY
|
data/ext/msgpack/extconf.rb
CHANGED
@@ -2,13 +2,7 @@ require 'mkmf'
|
|
2
2
|
|
3
3
|
have_header("ruby/st.h")
|
4
4
|
have_header("st.h")
|
5
|
-
have_func("
|
6
|
-
have_func("rb_intern_str", ["ruby.h"])
|
7
|
-
have_func("rb_sym2str", ["ruby.h"])
|
8
|
-
have_func("rb_str_intern", ["ruby.h"])
|
9
|
-
have_func("rb_block_lambda", ["ruby.h"])
|
10
|
-
have_func("rb_hash_dup", ["ruby.h"])
|
11
|
-
have_func("rb_hash_clear", ["ruby.h"])
|
5
|
+
have_func("rb_enc_interned_str", "ruby.h")
|
12
6
|
|
13
7
|
unless RUBY_PLATFORM.include? 'mswin'
|
14
8
|
$CFLAGS << %[ -I.. -Wall -O3 -g -std=gnu99]
|
@@ -25,6 +19,44 @@ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
|
25
19
|
$CFLAGS << %[ -DDISABLE_RMEM]
|
26
20
|
end
|
27
21
|
|
22
|
+
# checking if Hash#[]= (rb_hash_aset) dedupes string keys
|
23
|
+
h = {}
|
24
|
+
x = {}
|
25
|
+
r = rand.to_s
|
26
|
+
h[%W(#{r}).join('')] = :foo
|
27
|
+
x[%W(#{r}).join('')] = :foo
|
28
|
+
if x.keys[0].equal?(h.keys[0])
|
29
|
+
$CFLAGS << ' -DHASH_ASET_DEDUPE=1 '
|
30
|
+
else
|
31
|
+
$CFLAGS << ' -DHASH_ASET_DEDUPE=0 '
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
# checking if String#-@ (str_uminus) dedupes... '
|
36
|
+
begin
|
37
|
+
a = -(%w(t e s t).join)
|
38
|
+
b = -(%w(t e s t).join)
|
39
|
+
if a.equal?(b)
|
40
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE=1 '
|
41
|
+
else
|
42
|
+
$CFLAGS += ' -DSTR_UMINUS_DEDUPE=0 '
|
43
|
+
end
|
44
|
+
rescue NoMethodError
|
45
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
|
46
|
+
end
|
47
|
+
|
48
|
+
# checking if String#-@ (str_uminus) directly interns frozen strings... '
|
49
|
+
begin
|
50
|
+
s = rand.to_s.freeze
|
51
|
+
if (-s).equal?(s) && (-s.dup).equal?(s)
|
52
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=1 '
|
53
|
+
else
|
54
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
|
55
|
+
end
|
56
|
+
rescue NoMethodError
|
57
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
|
58
|
+
end
|
59
|
+
|
28
60
|
if warnflags = CONFIG['warnflags']
|
29
61
|
warnflags.slice!(/ -Wdeclaration-after-statement/)
|
30
62
|
end
|
data/ext/msgpack/factory_class.c
CHANGED
@@ -30,8 +30,11 @@ typedef struct msgpack_factory_t msgpack_factory_t;
|
|
30
30
|
|
31
31
|
struct msgpack_factory_t {
|
32
32
|
msgpack_packer_ext_registry_t pkrg;
|
33
|
-
msgpack_unpacker_ext_registry_t ukrg;
|
33
|
+
msgpack_unpacker_ext_registry_t *ukrg;
|
34
|
+
bool has_bigint_ext_type;
|
34
35
|
bool has_symbol_ext_type;
|
36
|
+
bool optimized_symbol_ext_type;
|
37
|
+
int symbol_ext_type;
|
35
38
|
};
|
36
39
|
|
37
40
|
#define FACTORY(from, name) \
|
@@ -47,14 +50,14 @@ static void Factory_free(msgpack_factory_t* fc)
|
|
47
50
|
return;
|
48
51
|
}
|
49
52
|
msgpack_packer_ext_registry_destroy(&fc->pkrg);
|
50
|
-
|
53
|
+
msgpack_unpacker_ext_registry_release(fc->ukrg);
|
51
54
|
xfree(fc);
|
52
55
|
}
|
53
56
|
|
54
57
|
void Factory_mark(msgpack_factory_t* fc)
|
55
58
|
{
|
56
59
|
msgpack_packer_ext_registry_mark(&fc->pkrg);
|
57
|
-
msgpack_unpacker_ext_registry_mark(
|
60
|
+
msgpack_unpacker_ext_registry_mark(fc->ukrg);
|
58
61
|
}
|
59
62
|
|
60
63
|
static VALUE Factory_alloc(VALUE klass)
|
@@ -70,7 +73,7 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
|
|
70
73
|
FACTORY(self, fc);
|
71
74
|
|
72
75
|
msgpack_packer_ext_registry_init(&fc->pkrg);
|
73
|
-
|
76
|
+
// fc->ukrg is lazily initialized
|
74
77
|
|
75
78
|
fc->has_symbol_ext_type = false;
|
76
79
|
|
@@ -85,6 +88,41 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
|
|
85
88
|
return Qnil;
|
86
89
|
}
|
87
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
|
+
|
88
126
|
VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
|
89
127
|
{
|
90
128
|
FACTORY(self, fc);
|
@@ -97,6 +135,7 @@ VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
|
|
97
135
|
|
98
136
|
msgpack_packer_ext_registry_destroy(&pk->ext_registry);
|
99
137
|
msgpack_packer_ext_registry_dup(&fc->pkrg, &pk->ext_registry);
|
138
|
+
pk->has_bigint_ext_type = fc->has_bigint_ext_type;
|
100
139
|
pk->has_symbol_ext_type = fc->has_symbol_ext_type;
|
101
140
|
|
102
141
|
return packer;
|
@@ -111,9 +150,9 @@ VALUE MessagePack_Factory_unpacker(int argc, VALUE* argv, VALUE self)
|
|
111
150
|
|
112
151
|
msgpack_unpacker_t* uk;
|
113
152
|
Data_Get_Struct(unpacker, msgpack_unpacker_t, uk);
|
114
|
-
|
115
|
-
|
116
|
-
|
153
|
+
msgpack_unpacker_ext_registry_borrow(fc->ukrg, &uk->ext_registry);
|
154
|
+
uk->optimized_symbol_ext_type = fc->optimized_symbol_ext_type;
|
155
|
+
uk->symbol_ext_type = fc->symbol_ext_type;
|
117
156
|
|
118
157
|
return unpacker;
|
119
158
|
}
|
@@ -123,16 +162,19 @@ static VALUE Factory_registered_types_internal(VALUE self)
|
|
123
162
|
FACTORY(self, fc);
|
124
163
|
|
125
164
|
VALUE uk_mapping = rb_hash_new();
|
126
|
-
|
127
|
-
|
128
|
-
|
165
|
+
if (fc->ukrg) {
|
166
|
+
for(int i=0; i < 256; i++) {
|
167
|
+
if(fc->ukrg->array[i] != Qnil) {
|
168
|
+
rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg->array[i]);
|
169
|
+
}
|
129
170
|
}
|
130
171
|
}
|
131
|
-
|
132
|
-
return rb_ary_new3(
|
133
|
-
|
134
|
-
|
135
|
-
|
172
|
+
|
173
|
+
return rb_ary_new3(
|
174
|
+
2,
|
175
|
+
RTEST(fc->pkrg.hash) ? rb_hash_dup(fc->pkrg.hash) : rb_hash_new(),
|
176
|
+
uk_mapping
|
177
|
+
);
|
136
178
|
}
|
137
179
|
|
138
180
|
static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
@@ -140,8 +182,9 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
140
182
|
FACTORY(self, fc);
|
141
183
|
|
142
184
|
int ext_type;
|
185
|
+
int flags = 0;
|
143
186
|
VALUE ext_module;
|
144
|
-
VALUE options;
|
187
|
+
VALUE options = Qnil;
|
145
188
|
VALUE packer_arg, unpacker_arg;
|
146
189
|
VALUE packer_proc, unpacker_proc;
|
147
190
|
|
@@ -168,6 +211,10 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
168
211
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
|
169
212
|
}
|
170
213
|
|
214
|
+
if (options != Qnil) {
|
215
|
+
Check_Type(options, T_HASH);
|
216
|
+
}
|
217
|
+
|
171
218
|
ext_type = NUM2INT(argv[0]);
|
172
219
|
if(ext_type < -128 || ext_type > 127) {
|
173
220
|
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
|
@@ -188,18 +235,36 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
188
235
|
if(unpacker_arg != Qnil) {
|
189
236
|
if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
|
190
237
|
unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
|
238
|
+
} else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
|
239
|
+
unpacker_proc = unpacker_arg;
|
191
240
|
} else {
|
192
241
|
unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
|
193
242
|
}
|
194
243
|
}
|
195
244
|
|
196
|
-
|
197
|
-
|
198
|
-
if (ext_module == rb_cSymbol) {
|
245
|
+
if(ext_module == rb_cSymbol) {
|
199
246
|
fc->has_symbol_ext_type = true;
|
247
|
+
if(RTEST(options) && RTEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
|
248
|
+
fc->optimized_symbol_ext_type = true;
|
249
|
+
}
|
250
|
+
}
|
251
|
+
|
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
|
+
}
|
200
264
|
}
|
201
265
|
|
202
|
-
|
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);
|
203
268
|
|
204
269
|
return Qnil;
|
205
270
|
}
|
@@ -211,6 +276,8 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
|
|
211
276
|
rb_define_alloc_func(cMessagePack_Factory, Factory_alloc);
|
212
277
|
|
213
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);
|
214
281
|
|
215
282
|
rb_define_method(cMessagePack_Factory, "packer", MessagePack_Factory_packer, -1);
|
216
283
|
rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
|
data/ext/msgpack/packer.c
CHANGED
@@ -121,17 +121,61 @@ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
|
|
121
121
|
#endif
|
122
122
|
}
|
123
123
|
|
124
|
-
|
124
|
+
struct msgpack_call_proc_args_t;
|
125
|
+
typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
|
126
|
+
struct msgpack_call_proc_args_t {
|
127
|
+
VALUE proc;
|
128
|
+
VALUE arg;
|
129
|
+
VALUE packer;
|
130
|
+
};
|
131
|
+
|
132
|
+
VALUE msgpack_packer_try_calling_proc(VALUE value)
|
133
|
+
{
|
134
|
+
msgpack_call_proc_args_t *args = (msgpack_call_proc_args_t *)value;
|
135
|
+
return rb_funcall(args->proc, s_call, 2, args->arg, args->packer);
|
136
|
+
}
|
137
|
+
|
138
|
+
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
|
125
139
|
{
|
126
|
-
int ext_type;
|
140
|
+
int ext_type, ext_flags;
|
127
141
|
|
128
|
-
VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type);
|
142
|
+
VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type, &ext_flags);
|
129
143
|
|
130
|
-
if(proc
|
144
|
+
if(proc == Qnil) {
|
145
|
+
return false;
|
146
|
+
}
|
147
|
+
|
148
|
+
if(ext_flags & MSGPACK_EXT_RECURSIVE) {
|
149
|
+
msgpack_buffer_t parent_buffer = pk->buffer;
|
150
|
+
msgpack_buffer_init(PACKER_BUFFER_(pk));
|
151
|
+
|
152
|
+
int exception_occured = 0;
|
153
|
+
msgpack_call_proc_args_t args = { proc, v, pk->to_msgpack_arg };
|
154
|
+
rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
|
155
|
+
|
156
|
+
if (exception_occured) {
|
157
|
+
msgpack_buffer_destroy(PACKER_BUFFER_(pk));
|
158
|
+
pk->buffer = parent_buffer;
|
159
|
+
rb_jump_tag(exception_occured); // re-raise the exception
|
160
|
+
} else {
|
161
|
+
VALUE payload = msgpack_buffer_all_as_string(PACKER_BUFFER_(pk));
|
162
|
+
StringValue(payload);
|
163
|
+
msgpack_buffer_destroy(PACKER_BUFFER_(pk));
|
164
|
+
pk->buffer = parent_buffer;
|
165
|
+
msgpack_packer_write_ext(pk, ext_type, payload);
|
166
|
+
}
|
167
|
+
} else {
|
131
168
|
VALUE payload = rb_funcall(proc, s_call, 1, v);
|
132
169
|
StringValue(payload);
|
133
170
|
msgpack_packer_write_ext(pk, ext_type, payload);
|
134
|
-
}
|
171
|
+
}
|
172
|
+
|
173
|
+
return true;
|
174
|
+
}
|
175
|
+
|
176
|
+
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
|
177
|
+
{
|
178
|
+
if(!(msgpack_packer_try_write_with_ext_type_lookup(pk, v))) {
|
135
179
|
rb_funcall(v, pk->to_msgpack_method, 1, pk->to_msgpack_arg);
|
136
180
|
}
|
137
181
|
}
|
@@ -155,13 +199,19 @@ void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v)
|
|
155
199
|
msgpack_packer_write_symbol_value(pk, v);
|
156
200
|
break;
|
157
201
|
case T_STRING:
|
158
|
-
|
202
|
+
if(rb_class_of(v) == rb_cString || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
203
|
+
msgpack_packer_write_string_value(pk, v);
|
204
|
+
}
|
159
205
|
break;
|
160
206
|
case T_ARRAY:
|
161
|
-
|
207
|
+
if(rb_class_of(v) == rb_cArray || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
208
|
+
msgpack_packer_write_array_value(pk, v);
|
209
|
+
}
|
162
210
|
break;
|
163
211
|
case T_HASH:
|
164
|
-
|
212
|
+
if(rb_class_of(v) == rb_cHash || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
213
|
+
msgpack_packer_write_hash_value(pk, v);
|
214
|
+
}
|
165
215
|
break;
|
166
216
|
case T_BIGNUM:
|
167
217
|
msgpack_packer_write_bignum_value(pk, 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
|
{
|
@@ -396,7 +399,6 @@ static inline void msgpack_packer_write_ext(msgpack_packer_t* pk, int ext_type,
|
|
396
399
|
msgpack_buffer_append_string(PACKER_BUFFER_(pk), payload);
|
397
400
|
}
|
398
401
|
|
399
|
-
#ifdef COMPAT_HAVE_ENCODING
|
400
402
|
static inline bool msgpack_packer_is_binary(VALUE v, int encindex)
|
401
403
|
{
|
402
404
|
return encindex == msgpack_rb_encindex_ascii8bit;
|
@@ -414,7 +416,6 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
|
|
414
416
|
#endif
|
415
417
|
;
|
416
418
|
}
|
417
|
-
#endif
|
418
419
|
|
419
420
|
static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
|
420
421
|
{
|
@@ -425,7 +426,6 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
425
426
|
rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %lu", len, 0xffffffffUL);
|
426
427
|
}
|
427
428
|
|
428
|
-
#ifdef COMPAT_HAVE_ENCODING
|
429
429
|
int encindex = ENCODING_GET(v);
|
430
430
|
if(msgpack_packer_is_binary(v, encindex) && !pk->compatibility_mode) {
|
431
431
|
/* write ASCII-8BIT string using Binary type */
|
@@ -443,24 +443,11 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
443
443
|
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
444
444
|
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
445
445
|
}
|
446
|
-
#else
|
447
|
-
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
448
|
-
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
449
|
-
#endif
|
450
446
|
}
|
451
447
|
|
452
448
|
static inline void msgpack_packer_write_symbol_string_value(msgpack_packer_t* pk, VALUE v)
|
453
449
|
{
|
454
|
-
#ifdef HAVE_RB_SYM2STR
|
455
|
-
/* rb_sym2str is added since MRI 2.2.0 */
|
456
450
|
msgpack_packer_write_string_value(pk, rb_sym2str(v));
|
457
|
-
#else
|
458
|
-
VALUE str = rb_id2str(SYM2ID(v));
|
459
|
-
if (!str) {
|
460
|
-
rb_raise(rb_eRuntimeError, "could not convert a symbol to string");
|
461
|
-
}
|
462
|
-
msgpack_packer_write_string_value(pk, str);
|
463
|
-
#endif
|
464
451
|
}
|
465
452
|
|
466
453
|
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v);
|
@@ -485,9 +472,30 @@ static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE
|
|
485
472
|
|
486
473
|
static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
|
487
474
|
{
|
475
|
+
int leading_zero_bits;
|
476
|
+
size_t required_size = rb_absint_size(v, &leading_zero_bits);
|
477
|
+
|
488
478
|
if(RBIGNUM_POSITIVE_P(v)) {
|
479
|
+
if(required_size > 8 && pk->has_bigint_ext_type) {
|
480
|
+
if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
481
|
+
return;
|
482
|
+
}
|
483
|
+
// if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
|
484
|
+
}
|
485
|
+
|
489
486
|
msgpack_packer_write_u64(pk, rb_big2ull(v));
|
490
487
|
} else {
|
488
|
+
if(leading_zero_bits == 0) {
|
489
|
+
required_size += 1;
|
490
|
+
}
|
491
|
+
|
492
|
+
if(required_size > 8 && pk->has_bigint_ext_type) {
|
493
|
+
if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
494
|
+
return;
|
495
|
+
}
|
496
|
+
// if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
|
497
|
+
}
|
498
|
+
|
491
499
|
msgpack_packer_write_long_long(pk, rb_big2ll(v));
|
492
500
|
}
|
493
501
|
}
|
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,11 +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
|
-
|
344
|
-
|
345
|
-
return
|
346
|
-
#endif
|
343
|
+
if (RTEST(pk->ext_registry.hash)) {
|
344
|
+
return rb_hash_dup(pk->ext_registry.hash);
|
345
|
+
}
|
346
|
+
return rb_hash_new();
|
347
347
|
}
|
348
348
|
|
349
349
|
static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
@@ -359,12 +359,7 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
|
359
359
|
case 2:
|
360
360
|
/* register_type(0x7f, Time) {|obj| block... } */
|
361
361
|
rb_need_block();
|
362
|
-
#ifdef HAVE_RB_BLOCK_LAMBDA
|
363
362
|
proc = rb_block_lambda();
|
364
|
-
#else
|
365
|
-
/* MRI 1.8 */
|
366
|
-
proc = rb_block_proc();
|
367
|
-
#endif
|
368
363
|
arg = proc;
|
369
364
|
break;
|
370
365
|
case 3:
|
@@ -386,7 +381,7 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
|
386
381
|
rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
|
387
382
|
}
|
388
383
|
|
389
|
-
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);
|
390
385
|
|
391
386
|
if (ext_module == rb_cSymbol) {
|
392
387
|
pk->has_symbol_ext_type = true;
|
@@ -418,6 +413,8 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
|
|
418
413
|
s_to_msgpack = rb_intern("to_msgpack");
|
419
414
|
s_write = rb_intern("write");
|
420
415
|
|
416
|
+
sym_compatibility_mode = ID2SYM(rb_intern("compatibility_mode"));
|
417
|
+
|
421
418
|
msgpack_packer_static_init();
|
422
419
|
msgpack_packer_ext_registry_static_init();
|
423
420
|
|
@@ -449,7 +446,8 @@ void MessagePack_Packer_module_init(VALUE mMessagePack)
|
|
449
446
|
rb_define_method(cMessagePack_Packer, "flush", Packer_flush, 0);
|
450
447
|
|
451
448
|
/* delegation methods */
|
452
|
-
rb_define_method(cMessagePack_Packer, "
|
449
|
+
rb_define_method(cMessagePack_Packer, "reset", Packer_reset, 0);
|
450
|
+
rb_define_alias(cMessagePack_Packer, "clear", "reset");
|
453
451
|
rb_define_method(cMessagePack_Packer, "size", Packer_size, 0);
|
454
452
|
rb_define_method(cMessagePack_Packer, "empty?", Packer_empty_p, 0);
|
455
453
|
rb_define_method(cMessagePack_Packer, "write_to", Packer_write_to, 1);
|