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
@@ -33,35 +33,58 @@ static VALUE eUnexpectedTypeError;
|
|
33
33
|
static VALUE eUnknownExtTypeError;
|
34
34
|
static VALUE mTypeError; // obsoleted. only for backward compatibility. See #86.
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
if(name == NULL) { \
|
40
|
-
rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \
|
41
|
-
}
|
36
|
+
static VALUE sym_symbolize_keys;
|
37
|
+
static VALUE sym_freeze;
|
38
|
+
static VALUE sym_allow_unknown_ext;
|
42
39
|
|
43
|
-
static void Unpacker_free(
|
40
|
+
static void Unpacker_free(void *ptr)
|
44
41
|
{
|
42
|
+
msgpack_unpacker_t* uk = ptr;
|
45
43
|
if(uk == NULL) {
|
46
44
|
return;
|
47
45
|
}
|
48
|
-
|
46
|
+
msgpack_unpacker_ext_registry_release(uk->ext_registry);
|
49
47
|
_msgpack_unpacker_destroy(uk);
|
50
48
|
xfree(uk);
|
51
49
|
}
|
52
50
|
|
53
|
-
static void Unpacker_mark(
|
51
|
+
static void Unpacker_mark(void *ptr)
|
54
52
|
{
|
53
|
+
msgpack_unpacker_t* uk = ptr;
|
55
54
|
msgpack_unpacker_mark(uk);
|
56
|
-
msgpack_unpacker_ext_registry_mark(
|
55
|
+
msgpack_unpacker_ext_registry_mark(uk->ext_registry);
|
56
|
+
}
|
57
|
+
|
58
|
+
static size_t Unpacker_memsize(const void *ptr)
|
59
|
+
{
|
60
|
+
size_t total_size = sizeof(msgpack_unpacker_t);
|
61
|
+
|
62
|
+
const msgpack_unpacker_t* uk = ptr;
|
63
|
+
if (uk->ext_registry) {
|
64
|
+
total_size += sizeof(msgpack_unpacker_ext_registry_t) / (uk->ext_registry->borrow_count + 1);
|
65
|
+
}
|
66
|
+
|
67
|
+
total_size += (uk->stack->depth + 1) * sizeof(msgpack_unpacker_stack_t);
|
68
|
+
|
69
|
+
return total_size + msgpack_buffer_memsize(&uk->buffer);
|
57
70
|
}
|
58
71
|
|
72
|
+
const rb_data_type_t unpacker_data_type = {
|
73
|
+
.wrap_struct_name = "msgpack:unpacker",
|
74
|
+
.function = {
|
75
|
+
.dmark = Unpacker_mark,
|
76
|
+
.dfree = Unpacker_free,
|
77
|
+
.dsize = Unpacker_memsize,
|
78
|
+
},
|
79
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
80
|
+
};
|
81
|
+
|
59
82
|
VALUE MessagePack_Unpacker_alloc(VALUE klass)
|
60
83
|
{
|
61
|
-
msgpack_unpacker_t* uk
|
84
|
+
msgpack_unpacker_t* uk;
|
85
|
+
VALUE self = TypedData_Make_Struct(klass, msgpack_unpacker_t, &unpacker_data_type, uk);
|
62
86
|
_msgpack_unpacker_init(uk);
|
63
|
-
|
64
|
-
VALUE self = Data_Wrap_Struct(klass, Unpacker_mark, Unpacker_free, uk);
|
87
|
+
uk->self = self;
|
65
88
|
return self;
|
66
89
|
}
|
67
90
|
|
@@ -84,7 +107,7 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
84
107
|
} else if(argc == 2) {
|
85
108
|
io = argv[0];
|
86
109
|
options = argv[1];
|
87
|
-
if(rb_type(options) != T_HASH) {
|
110
|
+
if(options != Qnil && rb_type(options) != T_HASH) {
|
88
111
|
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
89
112
|
}
|
90
113
|
|
@@ -92,9 +115,8 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
92
115
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
|
93
116
|
}
|
94
117
|
|
95
|
-
|
118
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
96
119
|
|
97
|
-
msgpack_unpacker_ext_registry_init(&uk->ext_registry);
|
98
120
|
uk->buffer_ref = MessagePack_Buffer_wrap(UNPACKER_BUFFER_(uk), self);
|
99
121
|
|
100
122
|
MessagePack_Buffer_set_options(UNPACKER_BUFFER_(uk), io, options);
|
@@ -102,10 +124,13 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
102
124
|
if(options != Qnil) {
|
103
125
|
VALUE v;
|
104
126
|
|
105
|
-
v = rb_hash_aref(options,
|
127
|
+
v = rb_hash_aref(options, sym_symbolize_keys);
|
106
128
|
msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
|
107
129
|
|
108
|
-
v = rb_hash_aref(options,
|
130
|
+
v = rb_hash_aref(options, sym_freeze);
|
131
|
+
msgpack_unpacker_set_freeze(uk, RTEST(v));
|
132
|
+
|
133
|
+
v = rb_hash_aref(options, sym_allow_unknown_ext);
|
109
134
|
msgpack_unpacker_set_allow_unknown_ext(uk, RTEST(v));
|
110
135
|
}
|
111
136
|
|
@@ -114,17 +139,23 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
114
139
|
|
115
140
|
static VALUE Unpacker_symbolized_keys_p(VALUE self)
|
116
141
|
{
|
117
|
-
|
142
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
118
143
|
return uk->symbolize_keys ? Qtrue : Qfalse;
|
119
144
|
}
|
120
145
|
|
146
|
+
static VALUE Unpacker_freeze_p(VALUE self)
|
147
|
+
{
|
148
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
149
|
+
return uk->freeze ? Qtrue : Qfalse;
|
150
|
+
}
|
151
|
+
|
121
152
|
static VALUE Unpacker_allow_unknown_ext_p(VALUE self)
|
122
153
|
{
|
123
|
-
|
154
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
124
155
|
return uk->allow_unknown_ext ? Qtrue : Qfalse;
|
125
156
|
}
|
126
157
|
|
127
|
-
static void raise_unpacker_error(int r)
|
158
|
+
NORETURN(static void raise_unpacker_error(int r))
|
128
159
|
{
|
129
160
|
switch(r) {
|
130
161
|
case PRIMITIVE_EOF:
|
@@ -136,6 +167,7 @@ static void raise_unpacker_error(int r)
|
|
136
167
|
case PRIMITIVE_UNEXPECTED_TYPE:
|
137
168
|
rb_raise(eUnexpectedTypeError, "unexpected type");
|
138
169
|
case PRIMITIVE_UNEXPECTED_EXT_TYPE:
|
170
|
+
// rb_bug("unexpected extension type");
|
139
171
|
rb_raise(eUnknownExtTypeError, "unexpected extension type");
|
140
172
|
default:
|
141
173
|
rb_raise(eUnpackError, "logically unknown error %d", r);
|
@@ -144,13 +176,13 @@ static void raise_unpacker_error(int r)
|
|
144
176
|
|
145
177
|
static VALUE Unpacker_buffer(VALUE self)
|
146
178
|
{
|
147
|
-
|
179
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
148
180
|
return uk->buffer_ref;
|
149
181
|
}
|
150
182
|
|
151
183
|
static VALUE Unpacker_read(VALUE self)
|
152
184
|
{
|
153
|
-
|
185
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
154
186
|
|
155
187
|
int r = msgpack_unpacker_read(uk, 0);
|
156
188
|
if(r < 0) {
|
@@ -162,7 +194,7 @@ static VALUE Unpacker_read(VALUE self)
|
|
162
194
|
|
163
195
|
static VALUE Unpacker_skip(VALUE self)
|
164
196
|
{
|
165
|
-
|
197
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
166
198
|
|
167
199
|
int r = msgpack_unpacker_skip(uk, 0);
|
168
200
|
if(r < 0) {
|
@@ -174,7 +206,7 @@ static VALUE Unpacker_skip(VALUE self)
|
|
174
206
|
|
175
207
|
static VALUE Unpacker_skip_nil(VALUE self)
|
176
208
|
{
|
177
|
-
|
209
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
178
210
|
|
179
211
|
int r = msgpack_unpacker_skip_nil(uk);
|
180
212
|
if(r < 0) {
|
@@ -189,7 +221,7 @@ static VALUE Unpacker_skip_nil(VALUE self)
|
|
189
221
|
|
190
222
|
static VALUE Unpacker_read_array_header(VALUE self)
|
191
223
|
{
|
192
|
-
|
224
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
193
225
|
|
194
226
|
uint32_t size;
|
195
227
|
int r = msgpack_unpacker_read_array_header(uk, &size);
|
@@ -197,12 +229,12 @@ static VALUE Unpacker_read_array_header(VALUE self)
|
|
197
229
|
raise_unpacker_error(r);
|
198
230
|
}
|
199
231
|
|
200
|
-
return ULONG2NUM(size);
|
232
|
+
return ULONG2NUM(size); // long at least 32 bits
|
201
233
|
}
|
202
234
|
|
203
235
|
static VALUE Unpacker_read_map_header(VALUE self)
|
204
236
|
{
|
205
|
-
|
237
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
206
238
|
|
207
239
|
uint32_t size;
|
208
240
|
int r = msgpack_unpacker_read_map_header(uk, &size);
|
@@ -210,41 +242,13 @@ static VALUE Unpacker_read_map_header(VALUE self)
|
|
210
242
|
raise_unpacker_error((int)r);
|
211
243
|
}
|
212
244
|
|
213
|
-
return ULONG2NUM(size);
|
245
|
+
return ULONG2NUM(size); // long at least 32 bits
|
214
246
|
}
|
215
247
|
|
216
|
-
static VALUE Unpacker_peek_next_type(VALUE self)
|
217
|
-
{
|
218
|
-
UNPACKER(self, uk);
|
219
|
-
|
220
|
-
int r = msgpack_unpacker_peek_next_object_type(uk);
|
221
|
-
if(r < 0) {
|
222
|
-
raise_unpacker_error(r);
|
223
|
-
}
|
224
|
-
|
225
|
-
switch((enum msgpack_unpacker_object_type) r) {
|
226
|
-
case TYPE_NIL:
|
227
|
-
return rb_intern("nil");
|
228
|
-
case TYPE_BOOLEAN:
|
229
|
-
return rb_intern("boolean");
|
230
|
-
case TYPE_INTEGER:
|
231
|
-
return rb_intern("integer");
|
232
|
-
case TYPE_FLOAT:
|
233
|
-
return rb_intern("float");
|
234
|
-
case TYPE_RAW:
|
235
|
-
return rb_intern("raw");
|
236
|
-
case TYPE_ARRAY:
|
237
|
-
return rb_intern("array");
|
238
|
-
case TYPE_MAP:
|
239
|
-
return rb_intern("map");
|
240
|
-
default:
|
241
|
-
rb_raise(eUnpackError, "logically unknown type %d", r);
|
242
|
-
}
|
243
|
-
}
|
244
248
|
|
245
249
|
static VALUE Unpacker_feed(VALUE self, VALUE data)
|
246
250
|
{
|
247
|
-
|
251
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
248
252
|
|
249
253
|
StringValue(data);
|
250
254
|
|
@@ -255,7 +259,7 @@ static VALUE Unpacker_feed(VALUE self, VALUE data)
|
|
255
259
|
|
256
260
|
static VALUE Unpacker_feed_reference(VALUE self, VALUE data)
|
257
261
|
{
|
258
|
-
|
262
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
259
263
|
|
260
264
|
StringValue(data);
|
261
265
|
|
@@ -266,7 +270,7 @@ static VALUE Unpacker_feed_reference(VALUE self, VALUE data)
|
|
266
270
|
|
267
271
|
static VALUE Unpacker_each_impl(VALUE self)
|
268
272
|
{
|
269
|
-
|
273
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
270
274
|
|
271
275
|
while(true) {
|
272
276
|
int r = msgpack_unpacker_read(uk, 0);
|
@@ -287,15 +291,16 @@ static VALUE Unpacker_each_impl(VALUE self)
|
|
287
291
|
}
|
288
292
|
}
|
289
293
|
|
290
|
-
static VALUE Unpacker_rescue_EOFError(VALUE
|
294
|
+
static VALUE Unpacker_rescue_EOFError(VALUE args, VALUE error)
|
291
295
|
{
|
292
|
-
UNUSED(
|
296
|
+
UNUSED(args);
|
297
|
+
UNUSED(error);
|
293
298
|
return Qnil;
|
294
299
|
}
|
295
300
|
|
296
301
|
static VALUE Unpacker_each(VALUE self)
|
297
302
|
{
|
298
|
-
|
303
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
299
304
|
|
300
305
|
#ifdef RETURN_ENUMERATOR
|
301
306
|
RETURN_ENUMERATOR(self, 0, 0);
|
@@ -326,7 +331,7 @@ static VALUE Unpacker_feed_each(VALUE self, VALUE data)
|
|
326
331
|
|
327
332
|
static VALUE Unpacker_reset(VALUE self)
|
328
333
|
{
|
329
|
-
|
334
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
330
335
|
|
331
336
|
_msgpack_unpacker_reset(uk);
|
332
337
|
|
@@ -335,12 +340,14 @@ static VALUE Unpacker_reset(VALUE self)
|
|
335
340
|
|
336
341
|
static VALUE Unpacker_registered_types_internal(VALUE self)
|
337
342
|
{
|
338
|
-
|
343
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
339
344
|
|
340
345
|
VALUE mapping = rb_hash_new();
|
341
|
-
|
342
|
-
|
343
|
-
|
346
|
+
if (uk->ext_registry) {
|
347
|
+
for(int i=0; i < 256; i++) {
|
348
|
+
if(uk->ext_registry->array[i] != Qnil) {
|
349
|
+
rb_hash_aset(mapping, INT2FIX(i - 128), uk->ext_registry->array[i]);
|
350
|
+
}
|
344
351
|
}
|
345
352
|
}
|
346
353
|
|
@@ -349,7 +356,7 @@ static VALUE Unpacker_registered_types_internal(VALUE self)
|
|
349
356
|
|
350
357
|
static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
|
351
358
|
{
|
352
|
-
|
359
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
353
360
|
|
354
361
|
int ext_type;
|
355
362
|
VALUE proc;
|
@@ -360,12 +367,7 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
|
|
360
367
|
case 1:
|
361
368
|
/* register_type(0x7f) {|data| block... } */
|
362
369
|
rb_need_block();
|
363
|
-
#ifdef HAVE_RB_BLOCK_LAMBDA
|
364
370
|
proc = rb_block_lambda();
|
365
|
-
#else
|
366
|
-
/* MRI 1.8 */
|
367
|
-
proc = rb_block_proc();
|
368
|
-
#endif
|
369
371
|
arg = proc;
|
370
372
|
ext_module = Qnil;
|
371
373
|
break;
|
@@ -384,14 +386,14 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
|
|
384
386
|
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
|
385
387
|
}
|
386
388
|
|
387
|
-
msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, proc, arg);
|
389
|
+
msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, 0, proc, arg);
|
388
390
|
|
389
391
|
return Qnil;
|
390
392
|
}
|
391
393
|
|
392
394
|
static VALUE Unpacker_full_unpack(VALUE self)
|
393
395
|
{
|
394
|
-
|
396
|
+
msgpack_unpacker_t *uk = MessagePack_Unpacker_get(self);
|
395
397
|
|
396
398
|
int r = msgpack_unpacker_read(uk, 0);
|
397
399
|
if(r < 0) {
|
@@ -434,10 +436,15 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
434
436
|
|
435
437
|
eUnknownExtTypeError = rb_define_class_under(mMessagePack, "UnknownExtTypeError", eUnpackError);
|
436
438
|
|
439
|
+
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
440
|
+
sym_freeze = ID2SYM(rb_intern("freeze"));
|
441
|
+
sym_allow_unknown_ext = ID2SYM(rb_intern("allow_unknown_ext"));
|
442
|
+
|
437
443
|
rb_define_alloc_func(cMessagePack_Unpacker, MessagePack_Unpacker_alloc);
|
438
444
|
|
439
445
|
rb_define_method(cMessagePack_Unpacker, "initialize", MessagePack_Unpacker_initialize, -1);
|
440
446
|
rb_define_method(cMessagePack_Unpacker, "symbolize_keys?", Unpacker_symbolized_keys_p, 0);
|
447
|
+
rb_define_method(cMessagePack_Unpacker, "freeze?", Unpacker_freeze_p, 0);
|
441
448
|
rb_define_method(cMessagePack_Unpacker, "allow_unknown_ext?", Unpacker_allow_unknown_ext_p, 0);
|
442
449
|
rb_define_method(cMessagePack_Unpacker, "buffer", Unpacker_buffer, 0);
|
443
450
|
rb_define_method(cMessagePack_Unpacker, "read", Unpacker_read, 0);
|
@@ -446,7 +453,6 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
446
453
|
rb_define_method(cMessagePack_Unpacker, "skip_nil", Unpacker_skip_nil, 0);
|
447
454
|
rb_define_method(cMessagePack_Unpacker, "read_array_header", Unpacker_read_array_header, 0);
|
448
455
|
rb_define_method(cMessagePack_Unpacker, "read_map_header", Unpacker_read_map_header, 0);
|
449
|
-
//rb_define_method(cMessagePack_Unpacker, "peek_next_type", Unpacker_peek_next_type, 0); // TODO
|
450
456
|
rb_define_method(cMessagePack_Unpacker, "feed", Unpacker_feed, 1);
|
451
457
|
rb_define_method(cMessagePack_Unpacker, "feed_reference", Unpacker_feed_reference, 1);
|
452
458
|
rb_define_method(cMessagePack_Unpacker, "each", Unpacker_each, 0);
|
@@ -464,4 +470,3 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
464
470
|
|
465
471
|
rb_define_method(cMessagePack_Unpacker, "full_unpack", Unpacker_full_unpack, 0);
|
466
472
|
}
|
467
|
-
|
@@ -20,6 +20,17 @@
|
|
20
20
|
|
21
21
|
#include "unpacker.h"
|
22
22
|
|
23
|
+
extern const rb_data_type_t unpacker_data_type;
|
24
|
+
|
25
|
+
static inline msgpack_unpacker_t *MessagePack_Unpacker_get(VALUE object) {
|
26
|
+
msgpack_unpacker_t *unpacker;
|
27
|
+
TypedData_Get_Struct(object, msgpack_unpacker_t, &unpacker_data_type, unpacker);
|
28
|
+
if (!unpacker) {
|
29
|
+
rb_raise(rb_eArgError, "Uninitialized Unpacker object");
|
30
|
+
}
|
31
|
+
return unpacker;
|
32
|
+
}
|
33
|
+
|
23
34
|
extern VALUE cMessagePack_Unpacker;
|
24
35
|
|
25
36
|
void MessagePack_Unpacker_module_init(VALUE mMessagePack);
|
@@ -21,42 +21,66 @@
|
|
21
21
|
static ID s_call;
|
22
22
|
static ID s_dup;
|
23
23
|
|
24
|
-
void msgpack_unpacker_ext_registry_static_init()
|
24
|
+
void msgpack_unpacker_ext_registry_static_init(void)
|
25
25
|
{
|
26
26
|
s_call = rb_intern("call");
|
27
27
|
s_dup = rb_intern("dup");
|
28
28
|
}
|
29
29
|
|
30
|
-
|
30
|
+
|
31
|
+
void msgpack_unpacker_ext_registry_static_destroy(void)
|
31
32
|
{ }
|
32
33
|
|
33
|
-
void
|
34
|
+
void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg)
|
34
35
|
{
|
35
|
-
|
36
|
-
|
36
|
+
if (ukrg) {
|
37
|
+
for(int i=0; i < 256; i++) {
|
38
|
+
if (ukrg->array[i] != Qnil) {
|
39
|
+
rb_gc_mark(ukrg->array[i]);
|
40
|
+
}
|
41
|
+
}
|
37
42
|
}
|
38
43
|
}
|
39
44
|
|
40
|
-
|
45
|
+
msgpack_unpacker_ext_registry_t* msgpack_unpacker_ext_registry_cow(msgpack_unpacker_ext_registry_t* src)
|
41
46
|
{
|
42
|
-
|
43
|
-
|
47
|
+
msgpack_unpacker_ext_registry_t* dst;
|
48
|
+
if (src) {
|
49
|
+
if (src->borrow_count) {
|
50
|
+
dst = ALLOC(msgpack_unpacker_ext_registry_t);
|
51
|
+
dst->borrow_count = 0;
|
52
|
+
MEMCPY(dst->array, src->array, VALUE, 256);
|
53
|
+
msgpack_unpacker_ext_registry_release(src);
|
54
|
+
return dst;
|
55
|
+
} else {
|
56
|
+
return src;
|
57
|
+
}
|
58
|
+
} else {
|
59
|
+
dst = ALLOC(msgpack_unpacker_ext_registry_t);
|
60
|
+
dst->borrow_count = 0;
|
61
|
+
for(int i=0; i < 256; i++) {
|
62
|
+
dst->array[i] = Qnil;
|
63
|
+
}
|
64
|
+
return dst;
|
44
65
|
}
|
45
66
|
}
|
46
67
|
|
47
|
-
void
|
48
|
-
msgpack_unpacker_ext_registry_t* dst)
|
68
|
+
void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg)
|
49
69
|
{
|
50
|
-
|
51
|
-
|
70
|
+
if (ukrg) {
|
71
|
+
if (ukrg->borrow_count) {
|
72
|
+
ukrg->borrow_count--;
|
73
|
+
} else {
|
74
|
+
xfree(ukrg);
|
75
|
+
}
|
52
76
|
}
|
53
77
|
}
|
54
78
|
|
55
|
-
|
56
|
-
VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
|
79
|
+
void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
|
80
|
+
VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
|
57
81
|
{
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
82
|
+
msgpack_unpacker_ext_registry_t* ext_registry = msgpack_unpacker_ext_registry_cow(*ukrg);
|
83
|
+
|
84
|
+
ext_registry->array[ext_type + 128] = rb_ary_new3(4, ext_module, proc, arg, INT2FIX(flags));
|
85
|
+
*ukrg = ext_registry;
|
62
86
|
}
|
@@ -21,39 +21,46 @@
|
|
21
21
|
#include "compat.h"
|
22
22
|
#include "ruby.h"
|
23
23
|
|
24
|
+
#define MSGPACK_EXT_RECURSIVE 0b0001
|
25
|
+
|
24
26
|
struct msgpack_unpacker_ext_registry_t;
|
25
27
|
typedef struct msgpack_unpacker_ext_registry_t msgpack_unpacker_ext_registry_t;
|
26
28
|
|
27
29
|
struct msgpack_unpacker_ext_registry_t {
|
30
|
+
unsigned int borrow_count;
|
28
31
|
VALUE array[256];
|
29
|
-
//int bitmap;
|
30
32
|
};
|
31
33
|
|
32
|
-
void msgpack_unpacker_ext_registry_static_init();
|
34
|
+
void msgpack_unpacker_ext_registry_static_init(void);
|
33
35
|
|
34
|
-
void msgpack_unpacker_ext_registry_static_destroy();
|
36
|
+
void msgpack_unpacker_ext_registry_static_destroy(void);
|
35
37
|
|
36
|
-
void
|
38
|
+
void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg);
|
37
39
|
|
38
|
-
static inline void
|
39
|
-
{
|
40
|
+
static inline void msgpack_unpacker_ext_registry_borrow(msgpack_unpacker_ext_registry_t* src, msgpack_unpacker_ext_registry_t** dst)
|
41
|
+
{
|
42
|
+
if (src) {
|
43
|
+
src->borrow_count++;
|
44
|
+
*dst = src;
|
45
|
+
}
|
46
|
+
}
|
40
47
|
|
41
48
|
void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg);
|
42
49
|
|
43
|
-
void
|
44
|
-
|
45
|
-
|
46
|
-
VALUE msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t* ukrg,
|
47
|
-
VALUE ext_module, int ext_type, VALUE proc, VALUE arg);
|
50
|
+
void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
|
51
|
+
VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
|
48
52
|
|
49
53
|
static inline VALUE msgpack_unpacker_ext_registry_lookup(msgpack_unpacker_ext_registry_t* ukrg,
|
50
|
-
int ext_type)
|
54
|
+
int ext_type, int* ext_flags_result)
|
51
55
|
{
|
52
|
-
|
53
|
-
|
54
|
-
|
56
|
+
if (ukrg) {
|
57
|
+
VALUE entry = ukrg->array[ext_type + 128];
|
58
|
+
if (entry != Qnil) {
|
59
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(entry, 3));
|
60
|
+
return rb_ary_entry(entry, 1);
|
61
|
+
}
|
55
62
|
}
|
56
|
-
return
|
63
|
+
return Qnil;
|
57
64
|
}
|
58
65
|
|
59
66
|
#endif
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MessagePack
|
4
|
+
module Bigint
|
5
|
+
# We split the bigint in 32bits chunks so that individual part fits into
|
6
|
+
# a MRI immediate Integer.
|
7
|
+
CHUNK_BITLENGTH = 32
|
8
|
+
FORMAT = 'CL>*'
|
9
|
+
|
10
|
+
if Integer.instance_method(:[]).arity != 1 # Ruby 2.7 and newer
|
11
|
+
# Starting from Ruby 2.7 we can address arbitrary bitranges inside an Integer with Integer#[]
|
12
|
+
# This allows to not allocate any Integer.
|
13
|
+
def self.to_msgpack_ext(bigint)
|
14
|
+
members = []
|
15
|
+
|
16
|
+
if bigint < 0
|
17
|
+
bigint = -bigint
|
18
|
+
members << 1
|
19
|
+
else
|
20
|
+
members << 0
|
21
|
+
end
|
22
|
+
|
23
|
+
offset = 0
|
24
|
+
length = bigint.bit_length
|
25
|
+
while offset < length
|
26
|
+
members << bigint[offset, CHUNK_BITLENGTH]
|
27
|
+
offset += CHUNK_BITLENGTH
|
28
|
+
end
|
29
|
+
|
30
|
+
members.pack(FORMAT)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
# On 2.6 and older since we can't address arbitrary bitranges, so we fallback to shifting the bigint.
|
34
|
+
# This means that after each shift, we may allocate another Integer instance.
|
35
|
+
BASE = (2**CHUNK_BITLENGTH) - 1
|
36
|
+
def self.to_msgpack_ext(bigint)
|
37
|
+
members = []
|
38
|
+
|
39
|
+
if bigint < 0
|
40
|
+
bigint = -bigint
|
41
|
+
members << 1
|
42
|
+
else
|
43
|
+
members << 0
|
44
|
+
end
|
45
|
+
|
46
|
+
while bigint > 0
|
47
|
+
members << (bigint & BASE)
|
48
|
+
bigint = bigint >> CHUNK_BITLENGTH
|
49
|
+
end
|
50
|
+
|
51
|
+
members.pack(FORMAT)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.from_msgpack_ext(data)
|
56
|
+
parts = data.unpack(FORMAT)
|
57
|
+
|
58
|
+
sign = parts.shift
|
59
|
+
sum = parts.pop.to_i
|
60
|
+
|
61
|
+
parts.reverse_each do |part|
|
62
|
+
sum = sum << CHUNK_BITLENGTH
|
63
|
+
sum += part
|
64
|
+
end
|
65
|
+
|
66
|
+
sign == 0 ? sum : -sum
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|