msgpack 1.3.3 → 1.6.0
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 +57 -0
- data/.rubocop.yml +2 -2
- data/ChangeLog +74 -0
- data/Gemfile +1 -1
- data/README.md +266 -0
- data/Rakefile +1 -9
- data/bench/bench.rb +78 -0
- data/bin/console +8 -0
- data/doclib/msgpack/factory.rb +47 -3
- data/doclib/msgpack/packer.rb +5 -4
- 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 +42 -68
- data/ext/msgpack/buffer.h +59 -14
- data/ext/msgpack/buffer_class.c +90 -52
- data/ext/msgpack/compat.h +1 -111
- data/ext/msgpack/extconf.rb +45 -19
- data/ext/msgpack/factory_class.c +133 -43
- data/ext/msgpack/packer.c +60 -36
- data/ext/msgpack/packer.h +27 -25
- data/ext/msgpack/packer_class.c +84 -77
- data/ext/msgpack/packer_class.h +11 -0
- data/ext/msgpack/packer_ext_registry.c +24 -32
- data/ext/msgpack/packer_ext_registry.h +40 -33
- data/ext/msgpack/sysdep.h +5 -2
- data/ext/msgpack/unpacker.c +132 -115
- data/ext/msgpack/unpacker.h +23 -10
- data/ext/msgpack/unpacker_class.c +83 -78
- data/ext/msgpack/unpacker_class.h +11 -0
- data/ext/msgpack/unpacker_ext_registry.c +42 -18
- data/ext/msgpack/unpacker_ext_registry.h +23 -16
- 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 +1 -1
- data/lib/msgpack/version.rb +4 -8
- data/lib/msgpack.rb +6 -12
- data/msgpack.gemspec +4 -6
- data/spec/bigint_spec.rb +26 -0
- data/spec/cruby/buffer_spec.rb +17 -0
- data/spec/factory_spec.rb +351 -12
- data/spec/msgpack_spec.rb +1 -1
- data/spec/packer_spec.rb +18 -0
- data/spec/spec_helper.rb +37 -3
- data/spec/timestamp_spec.rb +38 -0
- data/spec/unpacker_spec.rb +157 -4
- metadata +31 -61
- data/.travis.yml +0 -43
- data/README.rdoc +0 -225
- 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
@@ -30,47 +30,76 @@ 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
|
-
|
38
|
-
msgpack_factory_t *name = NULL; \
|
39
|
-
Data_Get_Struct(from, msgpack_factory_t, name); \
|
40
|
-
if(name == NULL) { \
|
41
|
-
rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \
|
42
|
-
}
|
43
|
-
|
44
|
-
static void Factory_free(msgpack_factory_t* fc)
|
40
|
+
static void Factory_free(void *ptr)
|
45
41
|
{
|
42
|
+
msgpack_factory_t *fc = ptr;
|
43
|
+
|
46
44
|
if(fc == NULL) {
|
47
45
|
return;
|
48
46
|
}
|
49
47
|
msgpack_packer_ext_registry_destroy(&fc->pkrg);
|
50
|
-
|
48
|
+
msgpack_unpacker_ext_registry_release(fc->ukrg);
|
51
49
|
xfree(fc);
|
52
50
|
}
|
53
51
|
|
54
|
-
void Factory_mark(
|
52
|
+
void Factory_mark(void *ptr)
|
55
53
|
{
|
54
|
+
msgpack_factory_t *fc = ptr;
|
56
55
|
msgpack_packer_ext_registry_mark(&fc->pkrg);
|
57
|
-
msgpack_unpacker_ext_registry_mark(
|
56
|
+
msgpack_unpacker_ext_registry_mark(fc->ukrg);
|
58
57
|
}
|
59
58
|
|
60
|
-
static
|
59
|
+
static size_t Factory_memsize(const void *ptr)
|
61
60
|
{
|
62
|
-
msgpack_factory_t*
|
61
|
+
const msgpack_factory_t *fc = ptr;
|
62
|
+
size_t total_size = sizeof(msgpack_factory_t);
|
63
63
|
|
64
|
-
|
65
|
-
|
64
|
+
if (fc->ukrg) {
|
65
|
+
total_size += sizeof(msgpack_unpacker_ext_registry_t) / (fc->ukrg->borrow_count + 1);
|
66
|
+
}
|
67
|
+
|
68
|
+
return total_size;
|
69
|
+
}
|
70
|
+
|
71
|
+
static const rb_data_type_t factory_data_type = {
|
72
|
+
.wrap_struct_name = "msgpack:factory",
|
73
|
+
.function = {
|
74
|
+
.dmark = Factory_mark,
|
75
|
+
.dfree = Factory_free,
|
76
|
+
.dsize = Factory_memsize,
|
77
|
+
},
|
78
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
79
|
+
};
|
80
|
+
|
81
|
+
static inline msgpack_factory_t *Factory_get(VALUE object)
|
82
|
+
{
|
83
|
+
msgpack_factory_t *factory;
|
84
|
+
TypedData_Get_Struct(object, msgpack_factory_t, &factory_data_type, factory);
|
85
|
+
if (!factory) {
|
86
|
+
rb_raise(rb_eArgError, "Uninitialized Factory object");
|
87
|
+
}
|
88
|
+
return factory;
|
89
|
+
}
|
90
|
+
|
91
|
+
static VALUE Factory_alloc(VALUE klass)
|
92
|
+
{
|
93
|
+
msgpack_factory_t *fc;
|
94
|
+
return TypedData_Make_Struct(klass, msgpack_factory_t, &factory_data_type, fc);
|
66
95
|
}
|
67
96
|
|
68
97
|
static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
|
69
98
|
{
|
70
|
-
|
99
|
+
msgpack_factory_t *fc = Factory_get(self);
|
71
100
|
|
72
101
|
msgpack_packer_ext_registry_init(&fc->pkrg);
|
73
|
-
|
102
|
+
// fc->ukrg is lazily initialized
|
74
103
|
|
75
104
|
fc->has_symbol_ext_type = false;
|
76
105
|
|
@@ -85,18 +114,52 @@ static VALUE Factory_initialize(int argc, VALUE* argv, VALUE self)
|
|
85
114
|
return Qnil;
|
86
115
|
}
|
87
116
|
|
117
|
+
static VALUE Factory_dup(VALUE self)
|
118
|
+
{
|
119
|
+
VALUE clone = Factory_alloc(rb_obj_class(self));
|
120
|
+
|
121
|
+
msgpack_factory_t *fc = Factory_get(self);
|
122
|
+
msgpack_factory_t *cloned_fc = Factory_get(clone);
|
123
|
+
|
124
|
+
cloned_fc->has_symbol_ext_type = fc->has_symbol_ext_type;
|
125
|
+
cloned_fc->pkrg = fc->pkrg;
|
126
|
+
msgpack_unpacker_ext_registry_borrow(fc->ukrg, &cloned_fc->ukrg);
|
127
|
+
msgpack_packer_ext_registry_dup(&fc->pkrg, &cloned_fc->pkrg);
|
128
|
+
|
129
|
+
return clone;
|
130
|
+
}
|
131
|
+
|
132
|
+
static VALUE Factory_freeze(VALUE self) {
|
133
|
+
if(!rb_obj_frozen_p(self)) {
|
134
|
+
msgpack_factory_t *fc = Factory_get(self);
|
135
|
+
|
136
|
+
if (RTEST(fc->pkrg.hash)) {
|
137
|
+
rb_hash_freeze(fc->pkrg.hash);
|
138
|
+
if (!RTEST(fc->pkrg.cache)) {
|
139
|
+
// If the factory is frozen, we can safely share the packer cache between
|
140
|
+
// all packers. So we eagerly create it now so it's available when #packer
|
141
|
+
// is called.
|
142
|
+
fc->pkrg.cache = rb_hash_new();
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
rb_obj_freeze(self);
|
147
|
+
}
|
148
|
+
|
149
|
+
return self;
|
150
|
+
}
|
151
|
+
|
88
152
|
VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
|
89
153
|
{
|
90
|
-
|
154
|
+
msgpack_factory_t *fc = Factory_get(self);
|
91
155
|
|
92
156
|
VALUE packer = MessagePack_Packer_alloc(cMessagePack_Packer);
|
93
157
|
MessagePack_Packer_initialize(argc, argv, packer);
|
94
158
|
|
95
|
-
msgpack_packer_t* pk;
|
96
|
-
Data_Get_Struct(packer, msgpack_packer_t, pk);
|
97
|
-
|
159
|
+
msgpack_packer_t* pk = MessagePack_Packer_get(packer);
|
98
160
|
msgpack_packer_ext_registry_destroy(&pk->ext_registry);
|
99
161
|
msgpack_packer_ext_registry_dup(&fc->pkrg, &pk->ext_registry);
|
162
|
+
pk->has_bigint_ext_type = fc->has_bigint_ext_type;
|
100
163
|
pk->has_symbol_ext_type = fc->has_symbol_ext_type;
|
101
164
|
|
102
165
|
return packer;
|
@@ -104,44 +167,47 @@ VALUE MessagePack_Factory_packer(int argc, VALUE* argv, VALUE self)
|
|
104
167
|
|
105
168
|
VALUE MessagePack_Factory_unpacker(int argc, VALUE* argv, VALUE self)
|
106
169
|
{
|
107
|
-
|
170
|
+
msgpack_factory_t *fc = Factory_get(self);
|
108
171
|
|
109
172
|
VALUE unpacker = MessagePack_Unpacker_alloc(cMessagePack_Unpacker);
|
110
173
|
MessagePack_Unpacker_initialize(argc, argv, unpacker);
|
111
174
|
|
112
|
-
msgpack_unpacker_t* uk;
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
msgpack_unpacker_ext_registry_dup(&fc->ukrg, &uk->ext_registry);
|
175
|
+
msgpack_unpacker_t* uk = MessagePack_Unpacker_get(unpacker);
|
176
|
+
msgpack_unpacker_ext_registry_borrow(fc->ukrg, &uk->ext_registry);
|
177
|
+
uk->optimized_symbol_ext_type = fc->optimized_symbol_ext_type;
|
178
|
+
uk->symbol_ext_type = fc->symbol_ext_type;
|
117
179
|
|
118
180
|
return unpacker;
|
119
181
|
}
|
120
182
|
|
121
183
|
static VALUE Factory_registered_types_internal(VALUE self)
|
122
184
|
{
|
123
|
-
|
185
|
+
msgpack_factory_t *fc = Factory_get(self);
|
124
186
|
|
125
187
|
VALUE uk_mapping = rb_hash_new();
|
126
|
-
|
127
|
-
|
128
|
-
|
188
|
+
if (fc->ukrg) {
|
189
|
+
for(int i=0; i < 256; i++) {
|
190
|
+
if(fc->ukrg->array[i] != Qnil) {
|
191
|
+
rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg->array[i]);
|
192
|
+
}
|
129
193
|
}
|
130
194
|
}
|
131
|
-
|
132
|
-
return rb_ary_new3(
|
133
|
-
|
134
|
-
|
135
|
-
|
195
|
+
|
196
|
+
return rb_ary_new3(
|
197
|
+
2,
|
198
|
+
RTEST(fc->pkrg.hash) ? rb_hash_dup(fc->pkrg.hash) : rb_hash_new(),
|
199
|
+
uk_mapping
|
200
|
+
);
|
136
201
|
}
|
137
202
|
|
138
203
|
static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
139
204
|
{
|
140
|
-
|
205
|
+
msgpack_factory_t *fc = Factory_get(self);
|
141
206
|
|
142
207
|
int ext_type;
|
208
|
+
int flags = 0;
|
143
209
|
VALUE ext_module;
|
144
|
-
VALUE options;
|
210
|
+
VALUE options = Qnil;
|
145
211
|
VALUE packer_arg, unpacker_arg;
|
146
212
|
VALUE packer_proc, unpacker_proc;
|
147
213
|
|
@@ -168,6 +234,10 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
168
234
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
|
169
235
|
}
|
170
236
|
|
237
|
+
if (options != Qnil) {
|
238
|
+
Check_Type(options, T_HASH);
|
239
|
+
}
|
240
|
+
|
171
241
|
ext_type = NUM2INT(argv[0]);
|
172
242
|
if(ext_type < -128 || ext_type > 127) {
|
173
243
|
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
|
@@ -188,18 +258,36 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
188
258
|
if(unpacker_arg != Qnil) {
|
189
259
|
if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
|
190
260
|
unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
|
261
|
+
} else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
|
262
|
+
unpacker_proc = unpacker_arg;
|
191
263
|
} else {
|
192
264
|
unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
|
193
265
|
}
|
194
266
|
}
|
195
267
|
|
196
|
-
|
197
|
-
|
198
|
-
if (ext_module == rb_cSymbol) {
|
268
|
+
if(ext_module == rb_cSymbol) {
|
199
269
|
fc->has_symbol_ext_type = true;
|
270
|
+
if(RTEST(options) && RTEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
|
271
|
+
fc->optimized_symbol_ext_type = true;
|
272
|
+
}
|
273
|
+
}
|
274
|
+
|
275
|
+
if(RTEST(options)) {
|
276
|
+
if(RTEST(rb_hash_aref(options, ID2SYM(rb_intern("oversized_integer_extension"))))) {
|
277
|
+
if(ext_module == rb_cInteger) {
|
278
|
+
fc->has_bigint_ext_type = true;
|
279
|
+
} else {
|
280
|
+
rb_raise(rb_eArgError, "oversized_integer_extension: true is only for Integer class");
|
281
|
+
}
|
282
|
+
}
|
283
|
+
|
284
|
+
if(RTEST(rb_hash_aref(options, ID2SYM(rb_intern("recursive"))))) {
|
285
|
+
flags |= MSGPACK_EXT_RECURSIVE;
|
286
|
+
}
|
200
287
|
}
|
201
288
|
|
202
|
-
|
289
|
+
msgpack_packer_ext_registry_put(&fc->pkrg, ext_module, ext_type, flags, packer_proc, packer_arg);
|
290
|
+
msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, flags, unpacker_proc, unpacker_arg);
|
203
291
|
|
204
292
|
return Qnil;
|
205
293
|
}
|
@@ -211,6 +299,8 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
|
|
211
299
|
rb_define_alloc_func(cMessagePack_Factory, Factory_alloc);
|
212
300
|
|
213
301
|
rb_define_method(cMessagePack_Factory, "initialize", Factory_initialize, -1);
|
302
|
+
rb_define_method(cMessagePack_Factory, "dup", Factory_dup, 0);
|
303
|
+
rb_define_method(cMessagePack_Factory, "freeze", Factory_freeze, 0);
|
214
304
|
|
215
305
|
rb_define_method(cMessagePack_Factory, "packer", MessagePack_Factory_packer, -1);
|
216
306
|
rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
|
data/ext/msgpack/packer.c
CHANGED
@@ -18,34 +18,18 @@
|
|
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
|
-
void msgpack_packer_static_init()
|
23
|
+
void msgpack_packer_static_init(void)
|
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
|
|
42
|
-
void msgpack_packer_static_destroy()
|
28
|
+
void msgpack_packer_static_destroy(void)
|
43
29
|
{ }
|
44
30
|
|
45
31
|
void msgpack_packer_init(msgpack_packer_t* pk)
|
46
32
|
{
|
47
|
-
memset(pk, 0, sizeof(msgpack_packer_t));
|
48
|
-
|
49
33
|
msgpack_buffer_init(PACKER_BUFFER_(pk));
|
50
34
|
}
|
51
35
|
|
@@ -108,30 +92,64 @@ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
|
|
108
92
|
unsigned int len32 = (unsigned int)len;
|
109
93
|
msgpack_packer_write_map_header(pk, len32);
|
110
94
|
|
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
95
|
rb_hash_foreach(v, write_hash_foreach, (VALUE) pk);
|
121
|
-
#endif
|
122
96
|
}
|
123
97
|
|
124
|
-
|
98
|
+
struct msgpack_call_proc_args_t;
|
99
|
+
typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
|
100
|
+
struct msgpack_call_proc_args_t {
|
101
|
+
VALUE proc;
|
102
|
+
VALUE arg;
|
103
|
+
VALUE packer;
|
104
|
+
};
|
105
|
+
|
106
|
+
VALUE msgpack_packer_try_calling_proc(VALUE value)
|
125
107
|
{
|
126
|
-
|
108
|
+
msgpack_call_proc_args_t *args = (msgpack_call_proc_args_t *)value;
|
109
|
+
return rb_funcall(args->proc, s_call, 2, args->arg, args->packer);
|
110
|
+
}
|
127
111
|
|
128
|
-
|
112
|
+
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
|
113
|
+
{
|
114
|
+
int ext_type, ext_flags;
|
129
115
|
|
130
|
-
|
116
|
+
VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type, &ext_flags);
|
117
|
+
|
118
|
+
if(proc == Qnil) {
|
119
|
+
return false;
|
120
|
+
}
|
121
|
+
|
122
|
+
if(ext_flags & MSGPACK_EXT_RECURSIVE) {
|
123
|
+
msgpack_buffer_t parent_buffer = pk->buffer;
|
124
|
+
msgpack_buffer_init(PACKER_BUFFER_(pk));
|
125
|
+
|
126
|
+
int exception_occured = 0;
|
127
|
+
msgpack_call_proc_args_t args = { proc, v, pk->to_msgpack_arg };
|
128
|
+
rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
|
129
|
+
|
130
|
+
if (exception_occured) {
|
131
|
+
msgpack_buffer_destroy(PACKER_BUFFER_(pk));
|
132
|
+
pk->buffer = parent_buffer;
|
133
|
+
rb_jump_tag(exception_occured); // re-raise the exception
|
134
|
+
} else {
|
135
|
+
VALUE payload = msgpack_buffer_all_as_string(PACKER_BUFFER_(pk));
|
136
|
+
StringValue(payload);
|
137
|
+
msgpack_buffer_destroy(PACKER_BUFFER_(pk));
|
138
|
+
pk->buffer = parent_buffer;
|
139
|
+
msgpack_packer_write_ext(pk, ext_type, payload);
|
140
|
+
}
|
141
|
+
} else {
|
131
142
|
VALUE payload = rb_funcall(proc, s_call, 1, v);
|
132
143
|
StringValue(payload);
|
133
144
|
msgpack_packer_write_ext(pk, ext_type, payload);
|
134
|
-
}
|
145
|
+
}
|
146
|
+
|
147
|
+
return true;
|
148
|
+
}
|
149
|
+
|
150
|
+
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
|
151
|
+
{
|
152
|
+
if(!(msgpack_packer_try_write_with_ext_type_lookup(pk, v))) {
|
135
153
|
rb_funcall(v, pk->to_msgpack_method, 1, pk->to_msgpack_arg);
|
136
154
|
}
|
137
155
|
}
|
@@ -155,13 +173,19 @@ void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v)
|
|
155
173
|
msgpack_packer_write_symbol_value(pk, v);
|
156
174
|
break;
|
157
175
|
case T_STRING:
|
158
|
-
|
176
|
+
if(rb_class_of(v) == rb_cString || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
177
|
+
msgpack_packer_write_string_value(pk, v);
|
178
|
+
}
|
159
179
|
break;
|
160
180
|
case T_ARRAY:
|
161
|
-
|
181
|
+
if(rb_class_of(v) == rb_cArray || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
182
|
+
msgpack_packer_write_array_value(pk, v);
|
183
|
+
}
|
162
184
|
break;
|
163
185
|
case T_HASH:
|
164
|
-
|
186
|
+
if(rb_class_of(v) == rb_cHash || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
187
|
+
msgpack_packer_write_hash_value(pk, v);
|
188
|
+
}
|
165
189
|
break;
|
166
190
|
case T_BIGNUM:
|
167
191
|
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;
|
@@ -46,9 +47,9 @@ struct msgpack_packer_t {
|
|
46
47
|
|
47
48
|
#define PACKER_BUFFER_(pk) (&(pk)->buffer)
|
48
49
|
|
49
|
-
void msgpack_packer_static_init();
|
50
|
+
void msgpack_packer_static_init(void);
|
50
51
|
|
51
|
-
void msgpack_packer_static_destroy();
|
52
|
+
void msgpack_packer_static_destroy(void);
|
52
53
|
|
53
54
|
void msgpack_packer_init(msgpack_packer_t* pk);
|
54
55
|
|
@@ -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;
|
@@ -406,15 +408,8 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
|
|
406
408
|
{
|
407
409
|
return encindex == msgpack_rb_encindex_utf8
|
408
410
|
|| encindex == msgpack_rb_encindex_usascii
|
409
|
-
|
410
|
-
/* Because ENC_CODERANGE_ASCIIONLY does not scan string, it may return ENC_CODERANGE_UNKNOWN unlike */
|
411
|
-
/* rb_enc_str_asciionly_p. It is always faster than rb_str_encode if it is available. */
|
412
|
-
/* Very old Rubinius (< v1.3.1) doesn't have ENC_CODERANGE_ASCIIONLY. */
|
413
|
-
|| (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v))
|
414
|
-
#endif
|
415
|
-
;
|
411
|
+
|| (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v));
|
416
412
|
}
|
417
|
-
#endif
|
418
413
|
|
419
414
|
static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
|
420
415
|
{
|
@@ -425,7 +420,6 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
425
420
|
rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %lu", len, 0xffffffffUL);
|
426
421
|
}
|
427
422
|
|
428
|
-
#ifdef COMPAT_HAVE_ENCODING
|
429
423
|
int encindex = ENCODING_GET(v);
|
430
424
|
if(msgpack_packer_is_binary(v, encindex) && !pk->compatibility_mode) {
|
431
425
|
/* write ASCII-8BIT string using Binary type */
|
@@ -443,24 +437,11 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
443
437
|
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
444
438
|
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
445
439
|
}
|
446
|
-
#else
|
447
|
-
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
448
|
-
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
449
|
-
#endif
|
450
440
|
}
|
451
441
|
|
452
442
|
static inline void msgpack_packer_write_symbol_string_value(msgpack_packer_t* pk, VALUE v)
|
453
443
|
{
|
454
|
-
#ifdef HAVE_RB_SYM2STR
|
455
|
-
/* rb_sym2str is added since MRI 2.2.0 */
|
456
444
|
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
445
|
}
|
465
446
|
|
466
447
|
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v);
|
@@ -485,9 +466,30 @@ static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE
|
|
485
466
|
|
486
467
|
static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
|
487
468
|
{
|
469
|
+
int leading_zero_bits;
|
470
|
+
size_t required_size = rb_absint_size(v, &leading_zero_bits);
|
471
|
+
|
488
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
|
+
|
489
480
|
msgpack_packer_write_u64(pk, rb_big2ull(v));
|
490
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
|
+
|
491
493
|
msgpack_packer_write_long_long(pk, rb_big2ll(v));
|
492
494
|
}
|
493
495
|
}
|