msgpack 1.4.5 → 1.5.6
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 +5 -5
- data/ChangeLog +32 -0
- data/README.md +25 -1
- data/bench/bench.rb +78 -0
- data/doclib/msgpack/factory.rb +45 -2
- data/ext/java/org/msgpack/jruby/Buffer.java +6 -0
- data/ext/java/org/msgpack/jruby/Decoder.java +23 -19
- data/ext/java/org/msgpack/jruby/Encoder.java +46 -18
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +24 -31
- data/ext/java/org/msgpack/jruby/Factory.java +40 -5
- data/ext/java/org/msgpack/jruby/Packer.java +21 -11
- data/ext/java/org/msgpack/jruby/Unpacker.java +44 -22
- data/ext/msgpack/buffer.c +9 -36
- data/ext/msgpack/buffer.h +9 -1
- data/ext/msgpack/buffer_class.c +18 -9
- data/ext/msgpack/compat.h +0 -99
- data/ext/msgpack/extconf.rb +9 -11
- data/ext/msgpack/factory_class.c +62 -5
- data/ext/msgpack/packer.c +42 -29
- data/ext/msgpack/packer.h +25 -7
- data/ext/msgpack/packer_class.c +23 -20
- data/ext/msgpack/packer_ext_registry.c +13 -4
- data/ext/msgpack/packer_ext_registry.h +10 -5
- data/ext/msgpack/unpacker.c +99 -68
- data/ext/msgpack/unpacker.h +10 -6
- data/ext/msgpack/unpacker_class.c +16 -8
- data/ext/msgpack/unpacker_ext_registry.c +3 -2
- data/ext/msgpack/unpacker_ext_registry.h +5 -2
- data/lib/msgpack/bigint.rb +69 -0
- data/lib/msgpack/factory.rb +103 -0
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +4 -5
- data/msgpack.gemspec +1 -0
- data/spec/bigint_spec.rb +26 -0
- data/spec/factory_spec.rb +248 -0
- data/spec/spec_helper.rb +9 -1
- data/spec/timestamp_spec.rb +2 -2
- data/spec/unpacker_spec.rb +12 -0
- metadata +20 -13
- 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/unpacker.c
CHANGED
@@ -34,6 +34,13 @@ static ID s_call;
|
|
34
34
|
static msgpack_rmem_t s_stack_rmem;
|
35
35
|
#endif
|
36
36
|
|
37
|
+
#if !defined(HAVE_RB_HASH_NEW_CAPA)
|
38
|
+
static inline VALUE rb_hash_new_capa(long capa)
|
39
|
+
{
|
40
|
+
return rb_hash_new();
|
41
|
+
}
|
42
|
+
#endif
|
43
|
+
|
37
44
|
void msgpack_unpacker_static_init()
|
38
45
|
{
|
39
46
|
#ifdef UNPACKER_STACK_RMEM
|
@@ -52,6 +59,19 @@ void msgpack_unpacker_static_destroy()
|
|
52
59
|
|
53
60
|
#define HEAD_BYTE_REQUIRED 0xc1
|
54
61
|
|
62
|
+
static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
|
63
|
+
msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
|
64
|
+
stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
65
|
+
#ifdef UNPACKER_STACK_RMEM
|
66
|
+
stack->data = msgpack_rmem_alloc(&s_stack_rmem);
|
67
|
+
/*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
|
68
|
+
#else
|
69
|
+
/*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_entry_t));*/
|
70
|
+
stack->data = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_entry_t));
|
71
|
+
#endif
|
72
|
+
return stack;
|
73
|
+
}
|
74
|
+
|
55
75
|
msgpack_unpacker_t* _msgpack_unpacker_new(void)
|
56
76
|
{
|
57
77
|
msgpack_unpacker_t* uk = ZALLOC_N(msgpack_unpacker_t, 1);
|
@@ -63,41 +83,44 @@ msgpack_unpacker_t* _msgpack_unpacker_new(void)
|
|
63
83
|
uk->last_object = Qnil;
|
64
84
|
uk->reading_raw = Qnil;
|
65
85
|
|
66
|
-
|
67
|
-
uk->stack = msgpack_rmem_alloc(&s_stack_rmem);
|
68
|
-
/*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
|
69
|
-
#else
|
70
|
-
/*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
|
71
|
-
uk->stack = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
|
72
|
-
#endif
|
73
|
-
uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
86
|
+
uk->stack = _msgpack_unpacker_new_stack();
|
74
87
|
|
75
88
|
return uk;
|
76
89
|
}
|
77
90
|
|
91
|
+
static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
|
92
|
+
#ifdef UNPACKER_STACK_RMEM
|
93
|
+
msgpack_rmem_free(&s_stack_rmem, stack->data);
|
94
|
+
#else
|
95
|
+
xfree(stack->data);
|
96
|
+
#endif
|
97
|
+
xfree(stack);
|
98
|
+
}
|
99
|
+
|
78
100
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
|
79
101
|
{
|
80
|
-
|
81
|
-
msgpack_rmem_free(&s_stack_rmem, uk->stack);
|
82
|
-
#else
|
83
|
-
xfree(uk->stack);
|
84
|
-
#endif
|
85
|
-
|
102
|
+
_msgpack_unpacker_free_stack(uk->stack);
|
86
103
|
msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
|
87
104
|
}
|
88
105
|
|
106
|
+
void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
|
107
|
+
{
|
108
|
+
while (stack) {
|
109
|
+
msgpack_unpacker_stack_entry_t* s = stack->data;
|
110
|
+
msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
|
111
|
+
for(; s < send; s++) {
|
112
|
+
rb_gc_mark(s->object);
|
113
|
+
rb_gc_mark(s->key);
|
114
|
+
}
|
115
|
+
stack = stack->parent;
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
89
119
|
void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
|
90
120
|
{
|
91
121
|
rb_gc_mark(uk->last_object);
|
92
122
|
rb_gc_mark(uk->reading_raw);
|
93
|
-
|
94
|
-
msgpack_unpacker_stack_t* s = uk->stack;
|
95
|
-
msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
|
96
|
-
for(; s < send; s++) {
|
97
|
-
rb_gc_mark(s->object);
|
98
|
-
rb_gc_mark(s->key);
|
99
|
-
}
|
100
|
-
|
123
|
+
msgpack_unpacker_mark_stack(uk->stack);
|
101
124
|
/* See MessagePack_Buffer_wrap */
|
102
125
|
/* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
|
103
126
|
rb_gc_mark(uk->buffer_ref);
|
@@ -109,9 +132,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
|
|
109
132
|
|
110
133
|
uk->head_byte = HEAD_BYTE_REQUIRED;
|
111
134
|
|
112
|
-
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->
|
113
|
-
uk->
|
114
|
-
|
135
|
+
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
|
136
|
+
uk->stack->depth = 0;
|
115
137
|
uk->last_object = Qnil;
|
116
138
|
uk->reading_raw = Qnil;
|
117
139
|
uk->reading_raw_remaining = 0;
|
@@ -163,17 +185,23 @@ static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
|
|
163
185
|
static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
|
164
186
|
{
|
165
187
|
if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
|
188
|
+
if (RB_UNLIKELY(NIL_P(str))) { // empty extension is returned as Qnil
|
189
|
+
return object_complete_symbol(uk, ID2SYM(rb_intern3("", 0, rb_utf8_encoding())));
|
190
|
+
}
|
166
191
|
return object_complete_symbol(uk, rb_str_intern(str));
|
167
192
|
}
|
168
193
|
|
169
|
-
|
194
|
+
int ext_flags;
|
195
|
+
VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
|
196
|
+
|
170
197
|
if(proc != Qnil) {
|
171
|
-
VALUE obj
|
198
|
+
VALUE obj;
|
199
|
+
obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
|
172
200
|
return object_complete(uk, obj);
|
173
201
|
}
|
174
202
|
|
175
203
|
if(uk->allow_unknown_ext) {
|
176
|
-
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
|
204
|
+
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
|
177
205
|
return object_complete(uk, obj);
|
178
206
|
}
|
179
207
|
|
@@ -181,37 +209,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
|
|
181
209
|
}
|
182
210
|
|
183
211
|
/* stack funcs */
|
184
|
-
static inline
|
212
|
+
static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
|
185
213
|
{
|
186
|
-
return &uk->stack[uk->
|
214
|
+
return &uk->stack->data[uk->stack->depth-1];
|
187
215
|
}
|
188
216
|
|
189
217
|
static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
|
190
218
|
{
|
191
219
|
reset_head_byte(uk);
|
192
220
|
|
193
|
-
if(uk->
|
221
|
+
if(uk->stack->capacity - uk->stack->depth <= 0) {
|
194
222
|
return PRIMITIVE_STACK_TOO_DEEP;
|
195
223
|
}
|
196
224
|
|
197
|
-
|
225
|
+
msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
|
198
226
|
next->count = count;
|
199
227
|
next->type = type;
|
200
228
|
next->object = object;
|
201
229
|
next->key = Qnil;
|
202
230
|
|
203
|
-
uk->
|
231
|
+
uk->stack->depth++;
|
204
232
|
return PRIMITIVE_CONTAINER_START;
|
205
233
|
}
|
206
234
|
|
207
235
|
static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
|
208
236
|
{
|
209
|
-
return --uk->
|
237
|
+
return --uk->stack->depth;
|
210
238
|
}
|
211
239
|
|
212
240
|
static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
|
213
241
|
{
|
214
|
-
return uk->
|
242
|
+
return uk->stack->depth == 0;
|
215
243
|
}
|
216
244
|
|
217
245
|
#ifdef USE_CASE_RANGE
|
@@ -239,8 +267,8 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
|
|
239
267
|
|
240
268
|
static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
|
241
269
|
{
|
242
|
-
if(uk->
|
243
|
-
|
270
|
+
if(uk->stack->depth > 0) {
|
271
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
244
272
|
if(top->type == STACK_TYPE_MAP_KEY) {
|
245
273
|
return true;
|
246
274
|
}
|
@@ -283,6 +311,30 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
283
311
|
{
|
284
312
|
/* assuming uk->reading_raw == Qnil */
|
285
313
|
|
314
|
+
int ext_flags;
|
315
|
+
VALUE proc;
|
316
|
+
|
317
|
+
if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
|
318
|
+
proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
|
319
|
+
if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
|
320
|
+
VALUE obj;
|
321
|
+
uk->last_object = Qnil;
|
322
|
+
reset_head_byte(uk);
|
323
|
+
uk->reading_raw_remaining = 0;
|
324
|
+
|
325
|
+
msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
|
326
|
+
child_stack->parent = uk->stack;
|
327
|
+
uk->stack = child_stack;
|
328
|
+
|
329
|
+
obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
|
330
|
+
|
331
|
+
uk->stack = child_stack->parent;
|
332
|
+
_msgpack_unpacker_free_stack(child_stack);
|
333
|
+
|
334
|
+
return object_complete(uk, obj);
|
335
|
+
}
|
336
|
+
}
|
337
|
+
|
286
338
|
/* try optimized read */
|
287
339
|
size_t length = uk->reading_raw_remaining;
|
288
340
|
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
|
@@ -331,9 +383,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
331
383
|
|
332
384
|
SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
|
333
385
|
int count = b & 0x1f;
|
334
|
-
if(count == 0) {
|
335
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
336
|
-
}
|
337
386
|
/* read_raw_body_begin sets uk->reading_raw */
|
338
387
|
uk->reading_raw_remaining = count;
|
339
388
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -350,7 +399,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
350
399
|
if(count == 0) {
|
351
400
|
return object_complete(uk, rb_hash_new());
|
352
401
|
}
|
353
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
402
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
354
403
|
|
355
404
|
SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
|
356
405
|
switch(b) {
|
@@ -371,7 +420,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
371
420
|
uint8_t length = cb->u8;
|
372
421
|
int ext_type = (signed char) cb->buffer[1];
|
373
422
|
if(length == 0) {
|
374
|
-
return object_complete_ext(uk, ext_type,
|
423
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
375
424
|
}
|
376
425
|
uk->reading_raw_remaining = length;
|
377
426
|
return read_raw_body_begin(uk, ext_type);
|
@@ -383,7 +432,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
383
432
|
uint16_t length = _msgpack_be16(cb->u16);
|
384
433
|
int ext_type = (signed char) cb->buffer[2];
|
385
434
|
if(length == 0) {
|
386
|
-
return object_complete_ext(uk, ext_type,
|
435
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
387
436
|
}
|
388
437
|
uk->reading_raw_remaining = length;
|
389
438
|
return read_raw_body_begin(uk, ext_type);
|
@@ -395,7 +444,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
395
444
|
uint32_t length = _msgpack_be32(cb->u32);
|
396
445
|
int ext_type = (signed char) cb->buffer[4];
|
397
446
|
if(length == 0) {
|
398
|
-
return object_complete_ext(uk, ext_type,
|
447
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
399
448
|
}
|
400
449
|
uk->reading_raw_remaining = length;
|
401
450
|
return read_raw_body_begin(uk, ext_type);
|
@@ -433,7 +482,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
433
482
|
{
|
434
483
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
435
484
|
uint32_t u32 = _msgpack_be32(cb->u32);
|
436
|
-
return object_complete(uk, ULONG2NUM(
|
485
|
+
return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
|
437
486
|
}
|
438
487
|
|
439
488
|
case 0xcf: // unsigned int 64
|
@@ -461,7 +510,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
461
510
|
{
|
462
511
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
463
512
|
int32_t i32 = _msgpack_be32(cb->i32);
|
464
|
-
return object_complete(uk, LONG2NUM(
|
513
|
+
return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
|
465
514
|
}
|
466
515
|
|
467
516
|
case 0xd3: // signed int 64
|
@@ -516,9 +565,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
516
565
|
{
|
517
566
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
518
567
|
uint8_t count = cb->u8;
|
519
|
-
if(count == 0) {
|
520
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
521
|
-
}
|
522
568
|
/* read_raw_body_begin sets uk->reading_raw */
|
523
569
|
uk->reading_raw_remaining = count;
|
524
570
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -528,9 +574,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
528
574
|
{
|
529
575
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
530
576
|
uint16_t count = _msgpack_be16(cb->u16);
|
531
|
-
if(count == 0) {
|
532
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
533
|
-
}
|
534
577
|
/* read_raw_body_begin sets uk->reading_raw */
|
535
578
|
uk->reading_raw_remaining = count;
|
536
579
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -540,9 +583,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
540
583
|
{
|
541
584
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
542
585
|
uint32_t count = _msgpack_be32(cb->u32);
|
543
|
-
if(count == 0) {
|
544
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
545
|
-
}
|
546
586
|
/* read_raw_body_begin sets uk->reading_raw */
|
547
587
|
uk->reading_raw_remaining = count;
|
548
588
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -552,9 +592,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
552
592
|
{
|
553
593
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
554
594
|
uint8_t count = cb->u8;
|
555
|
-
if(count == 0) {
|
556
|
-
return object_complete(uk, rb_str_new_static("", 0));
|
557
|
-
}
|
558
595
|
/* read_raw_body_begin sets uk->reading_raw */
|
559
596
|
uk->reading_raw_remaining = count;
|
560
597
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -564,9 +601,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
564
601
|
{
|
565
602
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
566
603
|
uint16_t count = _msgpack_be16(cb->u16);
|
567
|
-
if(count == 0) {
|
568
|
-
return object_complete(uk, rb_str_new_static("", 0));
|
569
|
-
}
|
570
604
|
/* read_raw_body_begin sets uk->reading_raw */
|
571
605
|
uk->reading_raw_remaining = count;
|
572
606
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -576,9 +610,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
576
610
|
{
|
577
611
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
578
612
|
uint32_t count = _msgpack_be32(cb->u32);
|
579
|
-
if(count == 0) {
|
580
|
-
return object_complete(uk, rb_str_new_static("", 0));
|
581
|
-
}
|
582
613
|
/* read_raw_body_begin sets uk->reading_raw */
|
583
614
|
uk->reading_raw_remaining = count;
|
584
615
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -611,7 +642,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
611
642
|
if(count == 0) {
|
612
643
|
return object_complete(uk, rb_hash_new());
|
613
644
|
}
|
614
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
645
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
615
646
|
}
|
616
647
|
|
617
648
|
case 0xdf: // map 32
|
@@ -621,7 +652,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
621
652
|
if(count == 0) {
|
622
653
|
return object_complete(uk, rb_hash_new());
|
623
654
|
}
|
624
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
655
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
625
656
|
}
|
626
657
|
|
627
658
|
default:
|
@@ -708,7 +739,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
708
739
|
|
709
740
|
container_completed:
|
710
741
|
{
|
711
|
-
|
742
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
712
743
|
switch(top->type) {
|
713
744
|
case STACK_TYPE_ARRAY:
|
714
745
|
rb_ary_push(top->object, uk->last_object);
|
@@ -758,7 +789,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
758
789
|
|
759
790
|
container_completed:
|
760
791
|
{
|
761
|
-
|
792
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
762
793
|
|
763
794
|
/* this section optimized out */
|
764
795
|
// TODO object_complete still creates objects which should be optimized out
|
data/ext/msgpack/unpacker.h
CHANGED
@@ -27,6 +27,7 @@
|
|
27
27
|
|
28
28
|
struct msgpack_unpacker_t;
|
29
29
|
typedef struct msgpack_unpacker_t msgpack_unpacker_t;
|
30
|
+
typedef struct msgpack_unpacker_stack_t msgpack_unpacker_stack_t;
|
30
31
|
|
31
32
|
enum stack_type_t {
|
32
33
|
STACK_TYPE_ARRAY,
|
@@ -39,19 +40,22 @@ typedef struct {
|
|
39
40
|
enum stack_type_t type;
|
40
41
|
VALUE object;
|
41
42
|
VALUE key;
|
42
|
-
}
|
43
|
+
} msgpack_unpacker_stack_entry_t;
|
44
|
+
|
45
|
+
struct msgpack_unpacker_stack_t {
|
46
|
+
size_t depth;
|
47
|
+
size_t capacity;
|
48
|
+
msgpack_unpacker_stack_entry_t *data;
|
49
|
+
msgpack_unpacker_stack_t *parent;
|
50
|
+
};
|
43
51
|
|
44
52
|
#define MSGPACK_UNPACKER_STACK_SIZE (8+4+8+8) /* assumes size_t <= 64bit, enum <= 32bit, VALUE <= 64bit */
|
45
53
|
|
46
54
|
struct msgpack_unpacker_t {
|
47
55
|
msgpack_buffer_t buffer;
|
48
|
-
|
56
|
+
msgpack_unpacker_stack_t *stack;
|
49
57
|
unsigned int head_byte;
|
50
58
|
|
51
|
-
msgpack_unpacker_stack_t* stack;
|
52
|
-
size_t stack_depth;
|
53
|
-
size_t stack_capacity;
|
54
|
-
|
55
59
|
VALUE last_object;
|
56
60
|
|
57
61
|
VALUE reading_raw;
|
@@ -33,6 +33,10 @@ static VALUE eUnexpectedTypeError;
|
|
33
33
|
static VALUE eUnknownExtTypeError;
|
34
34
|
static VALUE mTypeError; // obsoleted. only for backward compatibility. See #86.
|
35
35
|
|
36
|
+
static VALUE sym_symbolize_keys;
|
37
|
+
static VALUE sym_freeze;
|
38
|
+
static VALUE sym_allow_unknown_ext;
|
39
|
+
|
36
40
|
#define UNPACKER(from, name) \
|
37
41
|
msgpack_unpacker_t *name = NULL; \
|
38
42
|
Data_Get_Struct(from, msgpack_unpacker_t, name); \
|
@@ -83,7 +87,7 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
83
87
|
} else if(argc == 2) {
|
84
88
|
io = argv[0];
|
85
89
|
options = argv[1];
|
86
|
-
if(rb_type(options) != T_HASH) {
|
90
|
+
if(options != Qnil && rb_type(options) != T_HASH) {
|
87
91
|
rb_raise(rb_eArgError, "expected Hash but found %s.", rb_obj_classname(options));
|
88
92
|
}
|
89
93
|
|
@@ -100,13 +104,13 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
100
104
|
if(options != Qnil) {
|
101
105
|
VALUE v;
|
102
106
|
|
103
|
-
v = rb_hash_aref(options,
|
107
|
+
v = rb_hash_aref(options, sym_symbolize_keys);
|
104
108
|
msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
|
105
109
|
|
106
|
-
v = rb_hash_aref(options,
|
110
|
+
v = rb_hash_aref(options, sym_freeze);
|
107
111
|
msgpack_unpacker_set_freeze(uk, RTEST(v));
|
108
112
|
|
109
|
-
v = rb_hash_aref(options,
|
113
|
+
v = rb_hash_aref(options, sym_allow_unknown_ext);
|
110
114
|
msgpack_unpacker_set_allow_unknown_ext(uk, RTEST(v));
|
111
115
|
}
|
112
116
|
|
@@ -143,6 +147,7 @@ NORETURN(static void raise_unpacker_error(int r))
|
|
143
147
|
case PRIMITIVE_UNEXPECTED_TYPE:
|
144
148
|
rb_raise(eUnexpectedTypeError, "unexpected type");
|
145
149
|
case PRIMITIVE_UNEXPECTED_EXT_TYPE:
|
150
|
+
// rb_bug("unexpected extension type");
|
146
151
|
rb_raise(eUnknownExtTypeError, "unexpected extension type");
|
147
152
|
default:
|
148
153
|
rb_raise(eUnpackError, "logically unknown error %d", r);
|
@@ -204,7 +209,7 @@ static VALUE Unpacker_read_array_header(VALUE self)
|
|
204
209
|
raise_unpacker_error(r);
|
205
210
|
}
|
206
211
|
|
207
|
-
return ULONG2NUM(size);
|
212
|
+
return ULONG2NUM(size); // long at least 32 bits
|
208
213
|
}
|
209
214
|
|
210
215
|
static VALUE Unpacker_read_map_header(VALUE self)
|
@@ -217,7 +222,7 @@ static VALUE Unpacker_read_map_header(VALUE self)
|
|
217
222
|
raise_unpacker_error((int)r);
|
218
223
|
}
|
219
224
|
|
220
|
-
return ULONG2NUM(size);
|
225
|
+
return ULONG2NUM(size); // long at least 32 bits
|
221
226
|
}
|
222
227
|
|
223
228
|
|
@@ -361,7 +366,7 @@ static VALUE Unpacker_register_type(int argc, VALUE* argv, VALUE self)
|
|
361
366
|
rb_raise(rb_eRangeError, "integer %d too big to convert to `signed char'", ext_type);
|
362
367
|
}
|
363
368
|
|
364
|
-
msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, proc, arg);
|
369
|
+
msgpack_unpacker_ext_registry_put(&uk->ext_registry, ext_module, ext_type, 0, proc, arg);
|
365
370
|
|
366
371
|
return Qnil;
|
367
372
|
}
|
@@ -411,6 +416,10 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
411
416
|
|
412
417
|
eUnknownExtTypeError = rb_define_class_under(mMessagePack, "UnknownExtTypeError", eUnpackError);
|
413
418
|
|
419
|
+
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
420
|
+
sym_freeze = ID2SYM(rb_intern("freeze"));
|
421
|
+
sym_allow_unknown_ext = ID2SYM(rb_intern("allow_unknown_ext"));
|
422
|
+
|
414
423
|
rb_define_alloc_func(cMessagePack_Unpacker, MessagePack_Unpacker_alloc);
|
415
424
|
|
416
425
|
rb_define_method(cMessagePack_Unpacker, "initialize", MessagePack_Unpacker_initialize, -1);
|
@@ -441,4 +450,3 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
441
450
|
|
442
451
|
rb_define_method(cMessagePack_Unpacker, "full_unpack", Unpacker_full_unpack, 0);
|
443
452
|
}
|
444
|
-
|
@@ -77,9 +77,10 @@ void msgpack_unpacker_ext_registry_release(msgpack_unpacker_ext_registry_t* ukrg
|
|
77
77
|
}
|
78
78
|
|
79
79
|
void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
|
80
|
-
VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
|
80
|
+
VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg)
|
81
81
|
{
|
82
82
|
msgpack_unpacker_ext_registry_t* ext_registry = msgpack_unpacker_ext_registry_cow(*ukrg);
|
83
|
-
|
83
|
+
|
84
|
+
ext_registry->array[ext_type + 128] = rb_ary_new3(4, ext_module, proc, arg, INT2FIX(flags));
|
84
85
|
*ukrg = ext_registry;
|
85
86
|
}
|
@@ -21,6 +21,8 @@
|
|
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
|
|
@@ -46,14 +48,15 @@ static inline void msgpack_unpacker_ext_registry_borrow(msgpack_unpacker_ext_reg
|
|
46
48
|
void msgpack_unpacker_ext_registry_mark(msgpack_unpacker_ext_registry_t* ukrg);
|
47
49
|
|
48
50
|
void msgpack_unpacker_ext_registry_put(msgpack_unpacker_ext_registry_t** ukrg,
|
49
|
-
VALUE ext_module, int ext_type, VALUE proc, VALUE arg);
|
51
|
+
VALUE ext_module, int ext_type, int flags, VALUE proc, VALUE arg);
|
50
52
|
|
51
53
|
static inline VALUE msgpack_unpacker_ext_registry_lookup(msgpack_unpacker_ext_registry_t* ukrg,
|
52
|
-
int ext_type)
|
54
|
+
int ext_type, int* ext_flags_result)
|
53
55
|
{
|
54
56
|
if (ukrg) {
|
55
57
|
VALUE entry = ukrg->array[ext_type + 128];
|
56
58
|
if (entry != Qnil) {
|
59
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(entry, 3));
|
57
60
|
return rb_ary_entry(entry, 1);
|
58
61
|
}
|
59
62
|
}
|
@@ -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
|