msgpack 1.4.2 → 1.6.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 +57 -0
- data/ChangeLog +60 -0
- data/README.md +25 -1
- data/Rakefile +1 -2
- 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 +29 -21
- 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 +66 -42
- data/ext/msgpack/buffer.c +38 -57
- data/ext/msgpack/buffer.h +19 -10
- data/ext/msgpack/buffer_class.c +90 -52
- data/ext/msgpack/compat.h +0 -99
- data/ext/msgpack/extconf.rb +9 -22
- data/ext/msgpack/factory_class.c +133 -43
- data/ext/msgpack/packer.c +60 -36
- data/ext/msgpack/packer.h +27 -18
- 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 +128 -97
- data/ext/msgpack/unpacker.h +17 -10
- data/ext/msgpack/unpacker_class.c +75 -80
- 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 +1 -1
- data/lib/msgpack.rb +5 -7
- data/msgpack.gemspec +2 -2
- 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 +20 -3
- data/spec/timestamp_spec.rb +38 -0
- data/spec/unpacker_spec.rb +54 -4
- metadata +25 -41
- data/.travis.yml +0 -39
- 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
|
{
|
@@ -405,13 +408,7 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
|
|
405
408
|
{
|
406
409
|
return encindex == msgpack_rb_encindex_utf8
|
407
410
|
|| encindex == msgpack_rb_encindex_usascii
|
408
|
-
|
409
|
-
/* Because ENC_CODERANGE_ASCIIONLY does not scan string, it may return ENC_CODERANGE_UNKNOWN unlike */
|
410
|
-
/* rb_enc_str_asciionly_p. It is always faster than rb_str_encode if it is available. */
|
411
|
-
/* Very old Rubinius (< v1.3.1) doesn't have ENC_CODERANGE_ASCIIONLY. */
|
412
|
-
|| (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v))
|
413
|
-
#endif
|
414
|
-
;
|
411
|
+
|| (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v));
|
415
412
|
}
|
416
413
|
|
417
414
|
static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
|
@@ -444,16 +441,7 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
444
441
|
|
445
442
|
static inline void msgpack_packer_write_symbol_string_value(msgpack_packer_t* pk, VALUE v)
|
446
443
|
{
|
447
|
-
#ifdef HAVE_RB_SYM2STR
|
448
|
-
/* rb_sym2str is added since MRI 2.2.0 */
|
449
444
|
msgpack_packer_write_string_value(pk, rb_sym2str(v));
|
450
|
-
#else
|
451
|
-
VALUE str = rb_id2str(SYM2ID(v));
|
452
|
-
if (!str) {
|
453
|
-
rb_raise(rb_eRuntimeError, "could not convert a symbol to string");
|
454
|
-
}
|
455
|
-
msgpack_packer_write_string_value(pk, str);
|
456
|
-
#endif
|
457
445
|
}
|
458
446
|
|
459
447
|
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v);
|
@@ -478,9 +466,30 @@ static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE
|
|
478
466
|
|
479
467
|
static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
|
480
468
|
{
|
469
|
+
int leading_zero_bits;
|
470
|
+
size_t required_size = rb_absint_size(v, &leading_zero_bits);
|
471
|
+
|
481
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
|
+
|
482
480
|
msgpack_packer_write_u64(pk, rb_big2ull(v));
|
483
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
|
+
|
484
493
|
msgpack_packer_write_long_long(pk, rb_big2ll(v));
|
485
494
|
}
|
486
495
|
}
|