msgpack 1.3.3 → 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/.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
|
}
|