msgpack 1.4.5 → 1.5.6
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 +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
|