msgpack 1.3.3 → 1.7.2
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/ChangeLog +99 -0
- data/README.md +293 -0
- data/ext/java/org/msgpack/jruby/Buffer.java +26 -19
- 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 +43 -64
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +6 -9
- data/ext/java/org/msgpack/jruby/Factory.java +43 -42
- data/ext/java/org/msgpack/jruby/Packer.java +37 -40
- data/ext/java/org/msgpack/jruby/Unpacker.java +86 -68
- data/ext/msgpack/buffer.c +58 -85
- data/ext/msgpack/buffer.h +59 -20
- data/ext/msgpack/buffer_class.c +161 -52
- data/ext/msgpack/buffer_class.h +1 -0
- data/ext/msgpack/compat.h +1 -111
- data/ext/msgpack/extconf.rb +41 -23
- data/ext/msgpack/factory_class.c +143 -87
- data/ext/msgpack/packer.c +66 -43
- data/ext/msgpack/packer.h +25 -27
- data/ext/msgpack/packer_class.c +102 -130
- data/ext/msgpack/packer_class.h +11 -0
- data/ext/msgpack/packer_ext_registry.c +35 -40
- data/ext/msgpack/packer_ext_registry.h +41 -38
- data/ext/msgpack/rbinit.c +1 -1
- data/ext/msgpack/rmem.c +3 -4
- data/ext/msgpack/sysdep.h +5 -2
- data/ext/msgpack/unpacker.c +130 -126
- data/ext/msgpack/unpacker.h +22 -13
- data/ext/msgpack/unpacker_class.c +94 -124
- data/ext/msgpack/unpacker_class.h +11 -0
- data/ext/msgpack/unpacker_ext_registry.c +40 -28
- data/ext/msgpack/unpacker_ext_registry.h +21 -18
- data/lib/msgpack/bigint.rb +69 -0
- data/lib/msgpack/buffer.rb +9 -0
- data/lib/msgpack/factory.rb +140 -10
- data/lib/msgpack/packer.rb +10 -1
- data/lib/msgpack/symbol.rb +21 -4
- data/lib/msgpack/time.rb +1 -1
- data/lib/msgpack/unpacker.rb +14 -1
- data/lib/msgpack/version.rb +4 -8
- data/lib/msgpack.rb +7 -12
- data/msgpack.gemspec +9 -8
- metadata +37 -96
- data/.gitignore +0 -23
- data/.rubocop.yml +0 -36
- data/.travis.yml +0 -43
- data/Gemfile +0 -9
- data/README.rdoc +0 -225
- data/Rakefile +0 -78
- data/appveyor.yml +0 -18
- 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/doclib/msgpack/buffer.rb +0 -193
- data/doclib/msgpack/core_ext.rb +0 -101
- data/doclib/msgpack/error.rb +0 -19
- data/doclib/msgpack/extension_value.rb +0 -9
- data/doclib/msgpack/factory.rb +0 -101
- data/doclib/msgpack/packer.rb +0 -208
- data/doclib/msgpack/time.rb +0 -22
- data/doclib/msgpack/timestamp.rb +0 -44
- data/doclib/msgpack/unpacker.rb +0 -183
- data/doclib/msgpack.rb +0 -87
- data/msgpack.org.md +0 -46
- data/spec/cases.json +0 -1
- data/spec/cases.msg +0 -0
- data/spec/cases_compact.msg +0 -0
- data/spec/cases_spec.rb +0 -39
- data/spec/cruby/buffer_io_spec.rb +0 -255
- data/spec/cruby/buffer_packer.rb +0 -29
- data/spec/cruby/buffer_spec.rb +0 -575
- data/spec/cruby/buffer_unpacker.rb +0 -19
- data/spec/cruby/unpacker_spec.rb +0 -70
- data/spec/ext_value_spec.rb +0 -99
- data/spec/exttypes.rb +0 -51
- data/spec/factory_spec.rb +0 -367
- data/spec/format_spec.rb +0 -301
- data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
- data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
- data/spec/jruby/unpacker_spec.rb +0 -186
- data/spec/msgpack_spec.rb +0 -214
- data/spec/pack_spec.rb +0 -61
- data/spec/packer_spec.rb +0 -557
- data/spec/random_compat.rb +0 -24
- data/spec/spec_helper.rb +0 -38
- data/spec/timestamp_spec.rb +0 -121
- data/spec/unpack_spec.rb +0 -57
- data/spec/unpacker_spec.rb +0 -716
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 | RUBY_TYPED_WB_PROTECTED
|
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
|
-
msgpack_packer_ext_registry_init(&fc->pkrg);
|
73
|
-
|
101
|
+
msgpack_packer_ext_registry_init(self, &fc->pkrg);
|
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(clone, &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
|
+
RB_OBJ_WRITE(self, &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_borrow(packer, &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,102 +167,93 @@ 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(!NIL_P(fc->ukrg->array[i])) {
|
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
|
-
static VALUE
|
203
|
+
static VALUE Factory_register_type_internal(VALUE self, VALUE rb_ext_type, VALUE ext_module, VALUE options)
|
139
204
|
{
|
140
|
-
|
205
|
+
msgpack_factory_t *fc = Factory_get(self);
|
141
206
|
|
142
|
-
|
143
|
-
VALUE ext_module;
|
144
|
-
VALUE options;
|
145
|
-
VALUE packer_arg, unpacker_arg;
|
146
|
-
VALUE packer_proc, unpacker_proc;
|
207
|
+
Check_Type(rb_ext_type, T_FIXNUM);
|
147
208
|
|
148
|
-
if
|
149
|
-
rb_raise(
|
209
|
+
if(rb_type(ext_module) != T_MODULE && rb_type(ext_module) != T_CLASS) {
|
210
|
+
rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
|
150
211
|
}
|
151
212
|
|
152
|
-
|
153
|
-
case 2:
|
154
|
-
/* register_type(0x7f, Time) */
|
155
|
-
packer_arg = ID2SYM(rb_intern("to_msgpack_ext"));
|
156
|
-
unpacker_arg = ID2SYM(rb_intern("from_msgpack_ext"));
|
157
|
-
break;
|
158
|
-
case 3:
|
159
|
-
/* register_type(0x7f, Time, packer: proc-like, unapcker: proc-like) */
|
160
|
-
options = argv[2];
|
161
|
-
if(rb_type(options) != T_HASH) {
|
162
|
-
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
163
|
-
}
|
164
|
-
packer_arg = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
|
165
|
-
unpacker_arg = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
|
166
|
-
break;
|
167
|
-
default:
|
168
|
-
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2..3)", argc);
|
169
|
-
}
|
213
|
+
int flags = 0;
|
170
214
|
|
171
|
-
|
172
|
-
|
173
|
-
|
215
|
+
VALUE packer_proc = Qnil;
|
216
|
+
VALUE unpacker_proc = Qnil;
|
217
|
+
if(!NIL_P(options)) {
|
218
|
+
Check_Type(options, T_HASH);
|
219
|
+
packer_proc = rb_hash_aref(options, ID2SYM(rb_intern("packer")));
|
220
|
+
unpacker_proc = rb_hash_aref(options, ID2SYM(rb_intern("unpacker")));
|
174
221
|
}
|
175
222
|
|
176
|
-
|
177
|
-
|
178
|
-
rb_raise(rb_eArgError, "expected Module/Class but found %s.", rb_obj_classname(ext_module));
|
223
|
+
if (OBJ_FROZEN(self)) {
|
224
|
+
rb_raise(rb_eFrozenError, "can't modify frozen MessagePack::Factory");
|
179
225
|
}
|
180
226
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
if(packer_arg != Qnil) {
|
185
|
-
packer_proc = rb_funcall(packer_arg, rb_intern("to_proc"), 0);
|
227
|
+
int ext_type = NUM2INT(rb_ext_type);
|
228
|
+
if(ext_type < -128 || ext_type > 127) {
|
229
|
+
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
|
186
230
|
}
|
187
231
|
|
188
|
-
if(
|
189
|
-
if(
|
190
|
-
|
191
|
-
}
|
192
|
-
|
232
|
+
if(ext_module == rb_cSymbol) {
|
233
|
+
if(NIL_P(options) || RTEST(rb_hash_aref(options, ID2SYM(rb_intern("packer"))))) {
|
234
|
+
fc->has_symbol_ext_type = true;
|
235
|
+
}
|
236
|
+
if(RTEST(options) && RTEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
|
237
|
+
fc->optimized_symbol_ext_type = true;
|
193
238
|
}
|
194
239
|
}
|
195
240
|
|
196
|
-
|
241
|
+
if(RTEST(options)) {
|
242
|
+
if(RTEST(rb_hash_aref(options, ID2SYM(rb_intern("oversized_integer_extension"))))) {
|
243
|
+
if(ext_module == rb_cInteger) {
|
244
|
+
fc->has_bigint_ext_type = true;
|
245
|
+
} else {
|
246
|
+
rb_raise(rb_eArgError, "oversized_integer_extension: true is only for Integer class");
|
247
|
+
}
|
248
|
+
}
|
197
249
|
|
198
|
-
|
199
|
-
|
250
|
+
if(RTEST(rb_hash_aref(options, ID2SYM(rb_intern("recursive"))))) {
|
251
|
+
flags |= MSGPACK_EXT_RECURSIVE;
|
252
|
+
}
|
200
253
|
}
|
201
254
|
|
202
|
-
|
255
|
+
msgpack_packer_ext_registry_put(self, &fc->pkrg, ext_module, ext_type, flags, packer_proc);
|
256
|
+
msgpack_unpacker_ext_registry_put(self, &fc->ukrg, ext_module, ext_type, flags, unpacker_proc);
|
203
257
|
|
204
258
|
return Qnil;
|
205
259
|
}
|
@@ -211,10 +265,12 @@ void MessagePack_Factory_module_init(VALUE mMessagePack)
|
|
211
265
|
rb_define_alloc_func(cMessagePack_Factory, Factory_alloc);
|
212
266
|
|
213
267
|
rb_define_method(cMessagePack_Factory, "initialize", Factory_initialize, -1);
|
268
|
+
rb_define_method(cMessagePack_Factory, "dup", Factory_dup, 0);
|
269
|
+
rb_define_method(cMessagePack_Factory, "freeze", Factory_freeze, 0);
|
214
270
|
|
215
271
|
rb_define_method(cMessagePack_Factory, "packer", MessagePack_Factory_packer, -1);
|
216
272
|
rb_define_method(cMessagePack_Factory, "unpacker", MessagePack_Factory_unpacker, -1);
|
217
273
|
|
218
274
|
rb_define_private_method(cMessagePack_Factory, "registered_types_internal", Factory_registered_types_internal, 0);
|
219
|
-
|
275
|
+
rb_define_private_method(cMessagePack_Factory, "register_type_internal", Factory_register_type_internal, 3);
|
220
276
|
}
|
data/ext/msgpack/packer.c
CHANGED
@@ -17,35 +17,14 @@
|
|
17
17
|
*/
|
18
18
|
|
19
19
|
#include "packer.h"
|
20
|
+
#include "buffer_class.h"
|
20
21
|
|
21
|
-
#
|
22
|
-
|
23
|
-
static ID s_next;
|
24
|
-
static ID s_key;
|
25
|
-
static ID s_value;
|
22
|
+
#if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
|
23
|
+
#define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
|
26
24
|
#endif
|
27
25
|
|
28
|
-
static ID s_call;
|
29
|
-
|
30
|
-
void msgpack_packer_static_init()
|
31
|
-
{
|
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
|
-
s_call = rb_intern("call");
|
40
|
-
}
|
41
|
-
|
42
|
-
void msgpack_packer_static_destroy()
|
43
|
-
{ }
|
44
|
-
|
45
26
|
void msgpack_packer_init(msgpack_packer_t* pk)
|
46
27
|
{
|
47
|
-
memset(pk, 0, sizeof(msgpack_packer_t));
|
48
|
-
|
49
28
|
msgpack_buffer_init(PACKER_BUFFER_(pk));
|
50
29
|
}
|
51
30
|
|
@@ -59,6 +38,7 @@ void msgpack_packer_mark(msgpack_packer_t* pk)
|
|
59
38
|
/* See MessagePack_Buffer_wrap */
|
60
39
|
/* msgpack_buffer_mark(PACKER_BUFFER_(pk)); */
|
61
40
|
rb_gc_mark(pk->buffer_ref);
|
41
|
+
rb_gc_mark(pk->to_msgpack_arg);
|
62
42
|
}
|
63
43
|
|
64
44
|
void msgpack_packer_reset(msgpack_packer_t* pk)
|
@@ -108,30 +88,67 @@ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
|
|
108
88
|
unsigned int len32 = (unsigned int)len;
|
109
89
|
msgpack_packer_write_map_header(pk, len32);
|
110
90
|
|
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
91
|
rb_hash_foreach(v, write_hash_foreach, (VALUE) pk);
|
121
|
-
#endif
|
122
92
|
}
|
123
93
|
|
124
|
-
|
94
|
+
struct msgpack_call_proc_args_t;
|
95
|
+
typedef struct msgpack_call_proc_args_t msgpack_call_proc_args_t;
|
96
|
+
struct msgpack_call_proc_args_t {
|
97
|
+
VALUE proc;
|
98
|
+
VALUE args[2];
|
99
|
+
};
|
100
|
+
|
101
|
+
VALUE msgpack_packer_try_calling_proc(VALUE value)
|
125
102
|
{
|
126
|
-
|
103
|
+
msgpack_call_proc_args_t *args = (msgpack_call_proc_args_t *)value;
|
104
|
+
return rb_proc_call_with_block(args->proc, 2, args->args, Qnil);
|
105
|
+
}
|
127
106
|
|
128
|
-
|
107
|
+
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
|
108
|
+
{
|
109
|
+
int ext_type, ext_flags;
|
110
|
+
|
111
|
+
VALUE proc = msgpack_packer_ext_registry_lookup(&pk->ext_registry, v, &ext_type, &ext_flags);
|
112
|
+
|
113
|
+
if(proc == Qnil) {
|
114
|
+
return false;
|
115
|
+
}
|
129
116
|
|
130
|
-
if(
|
131
|
-
VALUE
|
117
|
+
if(ext_flags & MSGPACK_EXT_RECURSIVE) {
|
118
|
+
VALUE held_buffer = MessagePack_Buffer_hold(&pk->buffer);
|
119
|
+
|
120
|
+
msgpack_buffer_t parent_buffer = pk->buffer;
|
121
|
+
msgpack_buffer_init(PACKER_BUFFER_(pk));
|
122
|
+
|
123
|
+
int exception_occured = 0;
|
124
|
+
msgpack_call_proc_args_t args = { proc, { v, pk->to_msgpack_arg } };
|
125
|
+
rb_protect(msgpack_packer_try_calling_proc, (VALUE)&args, &exception_occured);
|
126
|
+
|
127
|
+
if (exception_occured) {
|
128
|
+
msgpack_buffer_destroy(PACKER_BUFFER_(pk));
|
129
|
+
pk->buffer = parent_buffer;
|
130
|
+
rb_jump_tag(exception_occured); // re-raise the exception
|
131
|
+
} else {
|
132
|
+
VALUE payload = msgpack_buffer_all_as_string(PACKER_BUFFER_(pk));
|
133
|
+
StringValue(payload);
|
134
|
+
msgpack_buffer_destroy(PACKER_BUFFER_(pk));
|
135
|
+
pk->buffer = parent_buffer;
|
136
|
+
msgpack_packer_write_ext(pk, ext_type, payload);
|
137
|
+
}
|
138
|
+
|
139
|
+
RB_GC_GUARD(held_buffer);
|
140
|
+
} else {
|
141
|
+
VALUE payload = rb_proc_call_with_block(proc, 1, &v, Qnil);
|
132
142
|
StringValue(payload);
|
133
143
|
msgpack_packer_write_ext(pk, ext_type, payload);
|
134
|
-
}
|
144
|
+
}
|
145
|
+
|
146
|
+
return true;
|
147
|
+
}
|
148
|
+
|
149
|
+
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
|
150
|
+
{
|
151
|
+
if(!(msgpack_packer_try_write_with_ext_type_lookup(pk, v))) {
|
135
152
|
rb_funcall(v, pk->to_msgpack_method, 1, pk->to_msgpack_arg);
|
136
153
|
}
|
137
154
|
}
|
@@ -155,13 +172,19 @@ void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v)
|
|
155
172
|
msgpack_packer_write_symbol_value(pk, v);
|
156
173
|
break;
|
157
174
|
case T_STRING:
|
158
|
-
|
175
|
+
if(rb_class_of(v) == rb_cString || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
176
|
+
msgpack_packer_write_string_value(pk, v);
|
177
|
+
}
|
159
178
|
break;
|
160
179
|
case T_ARRAY:
|
161
|
-
|
180
|
+
if(rb_class_of(v) == rb_cArray || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
181
|
+
msgpack_packer_write_array_value(pk, v);
|
182
|
+
}
|
162
183
|
break;
|
163
184
|
case T_HASH:
|
164
|
-
|
185
|
+
if(rb_class_of(v) == rb_cHash || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
186
|
+
msgpack_packer_write_hash_value(pk, v);
|
187
|
+
}
|
165
188
|
break;
|
166
189
|
case T_BIGNUM:
|
167
190
|
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,16 +47,14 @@ struct msgpack_packer_t {
|
|
46
47
|
|
47
48
|
#define PACKER_BUFFER_(pk) (&(pk)->buffer)
|
48
49
|
|
49
|
-
void msgpack_packer_static_init();
|
50
|
-
|
51
|
-
void msgpack_packer_static_destroy();
|
52
|
-
|
53
50
|
void msgpack_packer_init(msgpack_packer_t* pk);
|
54
51
|
|
55
52
|
void msgpack_packer_destroy(msgpack_packer_t* pk);
|
56
53
|
|
57
54
|
void msgpack_packer_mark(msgpack_packer_t* pk);
|
58
55
|
|
56
|
+
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v);
|
57
|
+
|
59
58
|
static inline void msgpack_packer_set_to_msgpack_method(msgpack_packer_t* pk,
|
60
59
|
ID to_msgpack_method, VALUE to_msgpack_arg)
|
61
60
|
{
|
@@ -396,7 +395,6 @@ static inline void msgpack_packer_write_ext(msgpack_packer_t* pk, int ext_type,
|
|
396
395
|
msgpack_buffer_append_string(PACKER_BUFFER_(pk), payload);
|
397
396
|
}
|
398
397
|
|
399
|
-
#ifdef COMPAT_HAVE_ENCODING
|
400
398
|
static inline bool msgpack_packer_is_binary(VALUE v, int encindex)
|
401
399
|
{
|
402
400
|
return encindex == msgpack_rb_encindex_ascii8bit;
|
@@ -406,15 +404,8 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
|
|
406
404
|
{
|
407
405
|
return encindex == msgpack_rb_encindex_utf8
|
408
406
|
|| 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
|
-
;
|
407
|
+
|| (rb_enc_asciicompat(rb_enc_from_index(encindex)) && ENC_CODERANGE_ASCIIONLY(v));
|
416
408
|
}
|
417
|
-
#endif
|
418
409
|
|
419
410
|
static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
|
420
411
|
{
|
@@ -425,7 +416,6 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
425
416
|
rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %lu", len, 0xffffffffUL);
|
426
417
|
}
|
427
418
|
|
428
|
-
#ifdef COMPAT_HAVE_ENCODING
|
429
419
|
int encindex = ENCODING_GET(v);
|
430
420
|
if(msgpack_packer_is_binary(v, encindex) && !pk->compatibility_mode) {
|
431
421
|
/* write ASCII-8BIT string using Binary type */
|
@@ -443,24 +433,11 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
443
433
|
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
444
434
|
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
445
435
|
}
|
446
|
-
#else
|
447
|
-
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
448
|
-
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
449
|
-
#endif
|
450
436
|
}
|
451
437
|
|
452
438
|
static inline void msgpack_packer_write_symbol_string_value(msgpack_packer_t* pk, VALUE v)
|
453
439
|
{
|
454
|
-
#ifdef HAVE_RB_SYM2STR
|
455
|
-
/* rb_sym2str is added since MRI 2.2.0 */
|
456
440
|
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
441
|
}
|
465
442
|
|
466
443
|
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v);
|
@@ -485,9 +462,30 @@ static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE
|
|
485
462
|
|
486
463
|
static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
|
487
464
|
{
|
465
|
+
int leading_zero_bits;
|
466
|
+
size_t required_size = rb_absint_size(v, &leading_zero_bits);
|
467
|
+
|
488
468
|
if(RBIGNUM_POSITIVE_P(v)) {
|
469
|
+
if(required_size > 8 && pk->has_bigint_ext_type) {
|
470
|
+
if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
471
|
+
return;
|
472
|
+
}
|
473
|
+
// if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
|
474
|
+
}
|
475
|
+
|
489
476
|
msgpack_packer_write_u64(pk, rb_big2ull(v));
|
490
477
|
} else {
|
478
|
+
if(leading_zero_bits == 0) {
|
479
|
+
required_size += 1;
|
480
|
+
}
|
481
|
+
|
482
|
+
if(required_size > 8 && pk->has_bigint_ext_type) {
|
483
|
+
if(msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
484
|
+
return;
|
485
|
+
}
|
486
|
+
// if we didn't return here `msgpack_packer_write_u64` will raise a RangeError
|
487
|
+
}
|
488
|
+
|
491
489
|
msgpack_packer_write_long_long(pk, rb_big2ll(v));
|
492
490
|
}
|
493
491
|
}
|