msgpack 1.7.5 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog +5 -0
- data/ext/msgpack/buffer.c +5 -4
- data/ext/msgpack/buffer.h +131 -3
- data/ext/msgpack/extconf.rb +5 -3
- data/ext/msgpack/packer.h +20 -13
- data/ext/msgpack/unpacker.c +76 -17
- data/ext/msgpack/unpacker.h +12 -4
- data/ext/msgpack/unpacker_class.c +5 -6
- data/lib/msgpack/version.rb +1 -1
- data/msgpack.gemspec +2 -0
- metadata +5 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: efdb772bf54b74587a6c99e9513f9c16c78bbef3e5e3c17064a4be79fd5adb7a
|
4
|
+
data.tar.gz: d2f74cb1115947f5337cd730b6283fac61ceeed3a9457597cc90155b3dc93d7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92da2466eac162f0d6d319496d7af3dbbef0d76b77c3aefb4787213e3b957464603859101ae28ac9620be82feb29278b2ed601adf2fd9d9811b364c258061d4b
|
7
|
+
data.tar.gz: a469586178eb44bbd50abf4cb34684f6a3fd4038063a80d9b3bf7f5cb9e6a2b34c1fed853be669f0bfb356d618efff3a2eaa51b86dd34d5427787a05453b8e11
|
data/ChangeLog
CHANGED
data/ext/msgpack/buffer.c
CHANGED
@@ -300,7 +300,7 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
|
|
300
300
|
static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE string)
|
301
301
|
{
|
302
302
|
VALUE mapped_string;
|
303
|
-
if(
|
303
|
+
if(ENCODING_GET_INLINED(string) == msgpack_rb_encindex_ascii8bit && RB_OBJ_FROZEN_RAW(string)) {
|
304
304
|
mapped_string = string;
|
305
305
|
} else {
|
306
306
|
mapped_string = rb_str_dup(string);
|
@@ -309,8 +309,9 @@ static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE s
|
|
309
309
|
|
310
310
|
_msgpack_buffer_add_new_chunk(b);
|
311
311
|
|
312
|
-
char* data
|
313
|
-
size_t length
|
312
|
+
char* data;
|
313
|
+
size_t length;
|
314
|
+
RSTRING_GETMEM(mapped_string, data, length);
|
314
315
|
|
315
316
|
b->tail.first = (char*) data;
|
316
317
|
b->tail.last = (char*) data + length;
|
@@ -330,7 +331,7 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
|
|
330
331
|
{
|
331
332
|
if(b->io != Qnil) {
|
332
333
|
msgpack_buffer_flush(b);
|
333
|
-
if (
|
334
|
+
if (ENCODING_GET_INLINED(string) == msgpack_rb_encindex_ascii8bit) {
|
334
335
|
rb_funcall(b->io, b->io_write_all_method, 1, string);
|
335
336
|
} else {
|
336
337
|
msgpack_buffer_append(b, RSTRING_PTR(string), RSTRING_LEN(string));
|
data/ext/msgpack/buffer.h
CHANGED
@@ -237,13 +237,14 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string);
|
|
237
237
|
|
238
238
|
static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE string)
|
239
239
|
{
|
240
|
-
size_t length
|
240
|
+
size_t length;
|
241
|
+
char *ptr;
|
242
|
+
RSTRING_GETMEM(string, ptr, length);
|
241
243
|
|
242
244
|
if(length > b->write_reference_threshold) {
|
243
245
|
_msgpack_buffer_append_long_string(b, string);
|
244
|
-
|
245
246
|
} else {
|
246
|
-
msgpack_buffer_append(b,
|
247
|
+
msgpack_buffer_append(b, ptr, length);
|
247
248
|
}
|
248
249
|
|
249
250
|
return length;
|
@@ -473,4 +474,131 @@ static inline VALUE msgpack_buffer_read_top_as_symbol(msgpack_buffer_t* b, size_
|
|
473
474
|
return rb_str_intern(msgpack_buffer_read_top_as_string(b, length, true, utf8));
|
474
475
|
}
|
475
476
|
|
477
|
+
// Hash keys are likely to be repeated, and are frozen.
|
478
|
+
// As such we can re-use them if we keep a cache of the ones we've seen so far,
|
479
|
+
// and save much more expensive lookups into the global fstring table.
|
480
|
+
// This cache implementation is deliberately simple, as we're optimizing for compactness,
|
481
|
+
// to be able to fit easily embeded inside msgpack_unpacker_t.
|
482
|
+
// As such, binary search into a sorted array gives a good tradeoff between compactness and
|
483
|
+
// performance.
|
484
|
+
#define MSGPACK_KEY_CACHE_CAPACITY 63
|
485
|
+
|
486
|
+
typedef struct msgpack_key_cache_t msgpack_key_cache_t;
|
487
|
+
struct msgpack_key_cache_t {
|
488
|
+
int length;
|
489
|
+
VALUE entries[MSGPACK_KEY_CACHE_CAPACITY];
|
490
|
+
};
|
491
|
+
|
492
|
+
static inline VALUE build_interned_string(const char *str, const long length)
|
493
|
+
{
|
494
|
+
# ifdef HAVE_RB_ENC_INTERNED_STR
|
495
|
+
return rb_enc_interned_str(str, length, rb_utf8_encoding());
|
496
|
+
# else
|
497
|
+
VALUE rstring = rb_utf8_str_new(str, length);
|
498
|
+
return rb_funcall(rb_str_freeze(rstring), s_uminus, 0);
|
499
|
+
# endif
|
500
|
+
}
|
501
|
+
|
502
|
+
static inline VALUE build_symbol(const char *str, const long length)
|
503
|
+
{
|
504
|
+
return rb_str_intern(build_interned_string(str, length));
|
505
|
+
}
|
506
|
+
|
507
|
+
static void rvalue_cache_insert_at(msgpack_key_cache_t *cache, int index, VALUE rstring)
|
508
|
+
{
|
509
|
+
MEMMOVE(&cache->entries[index + 1], &cache->entries[index], VALUE, cache->length - index);
|
510
|
+
cache->length++;
|
511
|
+
cache->entries[index] = rstring;
|
512
|
+
}
|
513
|
+
|
514
|
+
static inline int rstring_cache_cmp(const char *str, const long length, VALUE rstring)
|
515
|
+
{
|
516
|
+
long rstring_length = RSTRING_LEN(rstring);
|
517
|
+
if (length == rstring_length) {
|
518
|
+
return memcmp(str, RSTRING_PTR(rstring), length);
|
519
|
+
} else {
|
520
|
+
return (int)(length - rstring_length);
|
521
|
+
}
|
522
|
+
}
|
523
|
+
|
524
|
+
static VALUE rstring_cache_fetch(msgpack_key_cache_t *cache, const char *str, const long length)
|
525
|
+
{
|
526
|
+
int low = 0;
|
527
|
+
int high = cache->length - 1;
|
528
|
+
int mid = 0;
|
529
|
+
int last_cmp = 0;
|
530
|
+
|
531
|
+
while (low <= high) {
|
532
|
+
mid = (high + low) >> 1;
|
533
|
+
VALUE entry = cache->entries[mid];
|
534
|
+
last_cmp = rstring_cache_cmp(str, length, entry);
|
535
|
+
|
536
|
+
if (last_cmp == 0) {
|
537
|
+
return entry;
|
538
|
+
} else if (last_cmp > 0) {
|
539
|
+
low = mid + 1;
|
540
|
+
} else {
|
541
|
+
high = mid - 1;
|
542
|
+
}
|
543
|
+
}
|
544
|
+
|
545
|
+
VALUE rstring = build_interned_string(str, length);
|
546
|
+
|
547
|
+
if (cache->length < MSGPACK_KEY_CACHE_CAPACITY) {
|
548
|
+
if (last_cmp > 0) {
|
549
|
+
mid += 1;
|
550
|
+
}
|
551
|
+
|
552
|
+
rvalue_cache_insert_at(cache, mid, rstring);
|
553
|
+
}
|
554
|
+
return rstring;
|
555
|
+
}
|
556
|
+
|
557
|
+
static VALUE rsymbol_cache_fetch(msgpack_key_cache_t *cache, const char *str, const long length)
|
558
|
+
{
|
559
|
+
int low = 0;
|
560
|
+
int high = cache->length - 1;
|
561
|
+
int mid = 0;
|
562
|
+
int last_cmp = 0;
|
563
|
+
|
564
|
+
while (low <= high) {
|
565
|
+
mid = (high + low) >> 1;
|
566
|
+
VALUE entry = cache->entries[mid];
|
567
|
+
last_cmp = rstring_cache_cmp(str, length, rb_sym2str(entry));
|
568
|
+
|
569
|
+
if (last_cmp == 0) {
|
570
|
+
return entry;
|
571
|
+
} else if (last_cmp > 0) {
|
572
|
+
low = mid + 1;
|
573
|
+
} else {
|
574
|
+
high = mid - 1;
|
575
|
+
}
|
576
|
+
}
|
577
|
+
|
578
|
+
VALUE rsymbol = build_symbol(str, length);
|
579
|
+
|
580
|
+
if (cache->length < MSGPACK_KEY_CACHE_CAPACITY) {
|
581
|
+
if (last_cmp > 0) {
|
582
|
+
mid += 1;
|
583
|
+
}
|
584
|
+
|
585
|
+
rvalue_cache_insert_at(cache, mid, rsymbol);
|
586
|
+
}
|
587
|
+
return rsymbol;
|
588
|
+
}
|
589
|
+
|
590
|
+
static inline VALUE msgpack_buffer_read_top_as_interned_symbol(msgpack_buffer_t* b, msgpack_key_cache_t *cache, size_t length)
|
591
|
+
{
|
592
|
+
VALUE result = rsymbol_cache_fetch(cache, b->read_buffer, length);
|
593
|
+
_msgpack_buffer_consumed(b, length);
|
594
|
+
return result;
|
595
|
+
}
|
596
|
+
|
597
|
+
static inline VALUE msgpack_buffer_read_top_as_interned_string(msgpack_buffer_t* b, msgpack_key_cache_t *cache, size_t length)
|
598
|
+
{
|
599
|
+
VALUE result = rstring_cache_fetch(cache, b->read_buffer, length);
|
600
|
+
_msgpack_buffer_consumed(b, length);
|
601
|
+
return result;
|
602
|
+
}
|
603
|
+
|
476
604
|
#endif
|
data/ext/msgpack/extconf.rb
CHANGED
@@ -3,17 +3,19 @@ require 'mkmf'
|
|
3
3
|
have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
|
4
4
|
have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
|
5
5
|
have_func("rb_proc_call_with_block", "ruby.h") # CRuby (TruffleRuby doesn't have it)
|
6
|
+
have_func("rb_gc_mark_locations", "ruby.h") # Missing on TruffleRuby
|
6
7
|
|
7
8
|
append_cflags([
|
8
9
|
"-fvisibility=hidden",
|
9
10
|
"-I..",
|
10
11
|
"-Wall",
|
11
|
-
"-O3",
|
12
12
|
"-std=gnu99"
|
13
13
|
])
|
14
|
-
append_cflags(RbConfig::CONFIG["debugflags"]) if RbConfig::CONFIG["debugflags"]
|
15
14
|
|
16
|
-
|
15
|
+
if ENV["MSGPACK_DEBUG"]
|
16
|
+
append_cflags(RbConfig::CONFIG["debugflags"]) if RbConfig::CONFIG["debugflags"]
|
17
|
+
append_cflags("-DRUBY_DEBUG=1")
|
18
|
+
end
|
17
19
|
|
18
20
|
if RUBY_VERSION.start_with?('3.0.') && RUBY_VERSION <= '3.0.5'
|
19
21
|
# https://bugs.ruby-lang.org/issues/18772
|
data/ext/msgpack/packer.h
CHANGED
@@ -25,6 +25,11 @@
|
|
25
25
|
#define MSGPACK_PACKER_IO_FLUSH_THRESHOLD_TO_WRITE_STRING_BODY (1024)
|
26
26
|
#endif
|
27
27
|
|
28
|
+
#ifndef UNREACHABLE_RETURN
|
29
|
+
// Ruby 2.5
|
30
|
+
#define UNREACHABLE_RETURN() return
|
31
|
+
#endif
|
32
|
+
|
28
33
|
struct msgpack_packer_t;
|
29
34
|
typedef struct msgpack_packer_t msgpack_packer_t;
|
30
35
|
|
@@ -404,27 +409,33 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
|
|
404
409
|
{
|
405
410
|
return encindex == msgpack_rb_encindex_utf8
|
406
411
|
|| encindex == msgpack_rb_encindex_usascii
|
407
|
-
||
|
412
|
+
|| ENC_CODERANGE_ASCIIONLY(v);
|
408
413
|
}
|
409
414
|
|
410
415
|
static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
|
411
416
|
{
|
412
|
-
|
413
|
-
|
414
|
-
if(len >
|
415
|
-
|
416
|
-
|
417
|
+
long len = RSTRING_LEN(v);
|
418
|
+
|
419
|
+
if(RB_UNLIKELY(len > 0xffffffffL)) {
|
420
|
+
rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %ld", len, 0xffffffffL);
|
421
|
+
UNREACHABLE_RETURN();
|
417
422
|
}
|
418
423
|
|
419
|
-
|
420
|
-
|
424
|
+
if (RB_UNLIKELY(pk->compatibility_mode)) {
|
425
|
+
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
426
|
+
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
427
|
+
return;
|
428
|
+
}
|
429
|
+
|
430
|
+
int encindex = ENCODING_GET_INLINED(v);
|
431
|
+
if(msgpack_packer_is_binary(v, encindex)) {
|
421
432
|
/* write ASCII-8BIT string using Binary type */
|
422
433
|
msgpack_packer_write_bin_header(pk, (unsigned int)len);
|
423
434
|
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
424
435
|
} else {
|
425
436
|
/* write UTF-8, US-ASCII, or 7bit-safe ascii-compatible string using String type directly */
|
426
437
|
/* in compatibility mode, packer packs String values as is */
|
427
|
-
if(!
|
438
|
+
if(RB_UNLIKELY(!msgpack_packer_is_utf8_compat_string(v, encindex))) {
|
428
439
|
/* transcode other strings to UTF-8 and write using String type */
|
429
440
|
VALUE enc = rb_enc_from_encoding(rb_utf8_encoding()); /* rb_enc_from_encoding_index is not extern */
|
430
441
|
v = rb_str_encode(v, enc, 0, Qnil);
|
@@ -453,11 +464,7 @@ static inline void msgpack_packer_write_symbol_value(msgpack_packer_t* pk, VALUE
|
|
453
464
|
|
454
465
|
static inline void msgpack_packer_write_fixnum_value(msgpack_packer_t* pk, VALUE v)
|
455
466
|
{
|
456
|
-
#ifdef JRUBY
|
457
|
-
msgpack_packer_write_long(pk, FIXNUM_P(v) ? FIX2LONG(v) : rb_num2ll(v));
|
458
|
-
#else
|
459
467
|
msgpack_packer_write_long(pk, FIX2LONG(v));
|
460
|
-
#endif
|
461
468
|
}
|
462
469
|
|
463
470
|
static inline void msgpack_packer_write_bignum_value(msgpack_packer_t* pk, VALUE v)
|
data/ext/msgpack/unpacker.c
CHANGED
@@ -26,6 +26,19 @@
|
|
26
26
|
#define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
|
27
27
|
#endif
|
28
28
|
|
29
|
+
#ifndef HAVE_RB_GC_MARK_LOCATIONS
|
30
|
+
// For TruffleRuby
|
31
|
+
void rb_gc_mark_locations(const VALUE *start, const VALUE *end)
|
32
|
+
{
|
33
|
+
VALUE *value = start;
|
34
|
+
|
35
|
+
while (value < end) {
|
36
|
+
rb_gc_mark(*value);
|
37
|
+
value++;
|
38
|
+
}
|
39
|
+
}
|
40
|
+
#endif
|
41
|
+
|
29
42
|
struct protected_proc_call_args {
|
30
43
|
VALUE proc;
|
31
44
|
int argc;
|
@@ -79,11 +92,29 @@ void msgpack_unpacker_static_destroy(void)
|
|
79
92
|
|
80
93
|
#define HEAD_BYTE_REQUIRED 0xc1
|
81
94
|
|
82
|
-
static inline
|
83
|
-
stack->
|
84
|
-
|
95
|
+
static inline bool _msgpack_unpacker_stack_init(msgpack_unpacker_stack_t *stack) {
|
96
|
+
if (!stack->data) {
|
97
|
+
stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
98
|
+
stack->data = msgpack_rmem_alloc(&s_stack_rmem);
|
99
|
+
stack->depth = 0;
|
100
|
+
return true;
|
101
|
+
}
|
102
|
+
return false;
|
85
103
|
}
|
86
104
|
|
105
|
+
static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
|
106
|
+
if (stack->data) {
|
107
|
+
if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
|
108
|
+
rb_bug("Failed to free an rmem pointer, memory leak?");
|
109
|
+
}
|
110
|
+
stack->data = NULL;
|
111
|
+
stack->depth = 0;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
#define STACK_INIT(uk) bool stack_allocated = _msgpack_unpacker_stack_init(&uk->stack);
|
116
|
+
#define STACK_FREE(uk) if (stack_allocated) { _msgpack_unpacker_free_stack(&uk->stack); }
|
117
|
+
|
87
118
|
void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
88
119
|
{
|
89
120
|
msgpack_buffer_init(UNPACKER_BUFFER_(uk));
|
@@ -92,16 +123,6 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
|
92
123
|
|
93
124
|
uk->last_object = Qnil;
|
94
125
|
uk->reading_raw = Qnil;
|
95
|
-
|
96
|
-
_msgpack_unpacker_stack_init(&uk->stack);
|
97
|
-
}
|
98
|
-
|
99
|
-
static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
|
100
|
-
if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
|
101
|
-
rb_bug("Failed to free an rmem pointer, memory leak?");
|
102
|
-
}
|
103
|
-
stack->data = NULL;
|
104
|
-
stack->depth = 0;
|
105
126
|
}
|
106
127
|
|
107
128
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
|
@@ -122,11 +143,18 @@ void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
|
|
122
143
|
}
|
123
144
|
}
|
124
145
|
|
146
|
+
void msgpack_unpacker_mark_key_cache(msgpack_key_cache_t *cache)
|
147
|
+
{
|
148
|
+
const VALUE *entries = &cache->entries[0];
|
149
|
+
rb_gc_mark_locations(entries, entries + cache->length);
|
150
|
+
}
|
151
|
+
|
125
152
|
void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
|
126
153
|
{
|
127
154
|
rb_gc_mark(uk->last_object);
|
128
155
|
rb_gc_mark(uk->reading_raw);
|
129
156
|
msgpack_unpacker_mark_stack(&uk->stack);
|
157
|
+
msgpack_unpacker_mark_key_cache(&uk->key_cache);
|
130
158
|
/* See MessagePack_Buffer_wrap */
|
131
159
|
/* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
|
132
160
|
rb_gc_mark(uk->buffer_ref);
|
@@ -366,15 +394,32 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
366
394
|
size_t length = uk->reading_raw_remaining;
|
367
395
|
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
|
368
396
|
int ret;
|
369
|
-
if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type)
|
397
|
+
if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type)) {
|
370
398
|
VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
|
371
399
|
ret = object_complete_symbol(uk, symbol);
|
400
|
+
} else if (is_reading_map_key(uk) && raw_type == RAW_TYPE_STRING) {
|
401
|
+
/* don't use zerocopy for hash keys but get a frozen string directly
|
402
|
+
* because rb_hash_aset freezes keys and it causes copying */
|
403
|
+
VALUE key;
|
404
|
+
if (uk->symbolize_keys) {
|
405
|
+
if (uk->use_key_cache) {
|
406
|
+
key = msgpack_buffer_read_top_as_interned_symbol(UNPACKER_BUFFER_(uk), &uk->key_cache, length);
|
407
|
+
} else {
|
408
|
+
key = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, true);
|
409
|
+
}
|
410
|
+
ret = object_complete_symbol(uk, key);
|
411
|
+
} else {
|
412
|
+
if (uk->use_key_cache) {
|
413
|
+
key = msgpack_buffer_read_top_as_interned_string(UNPACKER_BUFFER_(uk), &uk->key_cache, length);
|
414
|
+
} else {
|
415
|
+
key = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, true, true);
|
416
|
+
}
|
417
|
+
|
418
|
+
ret = object_complete(uk, key);
|
419
|
+
}
|
372
420
|
} else {
|
373
421
|
bool will_freeze = uk->freeze;
|
374
422
|
if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
|
375
|
-
/* don't use zerocopy for hash keys but get a frozen string directly
|
376
|
-
* because rb_hash_aset freezes keys and it causes copying */
|
377
|
-
will_freeze = will_freeze || is_reading_map_key(uk);
|
378
423
|
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
379
424
|
ret = object_complete(uk, string);
|
380
425
|
} else {
|
@@ -750,9 +795,15 @@ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_si
|
|
750
795
|
|
751
796
|
int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
752
797
|
{
|
798
|
+
STACK_INIT(uk);
|
799
|
+
|
753
800
|
while(true) {
|
754
801
|
int r = read_primitive(uk);
|
755
802
|
if(r < 0) {
|
803
|
+
if (r != PRIMITIVE_EOF) {
|
804
|
+
// We keep the stack on EOF as the parsing may be resumed.
|
805
|
+
STACK_FREE(uk);
|
806
|
+
}
|
756
807
|
return r;
|
757
808
|
}
|
758
809
|
if(r == PRIMITIVE_CONTAINER_START) {
|
@@ -761,6 +812,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
761
812
|
/* PRIMITIVE_OBJECT_COMPLETE */
|
762
813
|
|
763
814
|
if(msgpack_unpacker_stack_is_empty(uk)) {
|
815
|
+
STACK_FREE(uk);
|
764
816
|
return PRIMITIVE_OBJECT_COMPLETE;
|
765
817
|
}
|
766
818
|
|
@@ -785,6 +837,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
785
837
|
top->type = STACK_TYPE_MAP_KEY;
|
786
838
|
break;
|
787
839
|
case STACK_TYPE_RECURSIVE:
|
840
|
+
STACK_FREE(uk);
|
788
841
|
return PRIMITIVE_OBJECT_COMPLETE;
|
789
842
|
}
|
790
843
|
size_t count = --top->count;
|
@@ -792,6 +845,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
792
845
|
if(count == 0) {
|
793
846
|
object_complete(uk, top->object);
|
794
847
|
if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
|
848
|
+
STACK_FREE(uk);
|
795
849
|
return PRIMITIVE_OBJECT_COMPLETE;
|
796
850
|
}
|
797
851
|
goto container_completed;
|
@@ -802,9 +856,12 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
802
856
|
|
803
857
|
int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
804
858
|
{
|
859
|
+
STACK_INIT(uk);
|
860
|
+
|
805
861
|
while(true) {
|
806
862
|
int r = read_primitive(uk);
|
807
863
|
if(r < 0) {
|
864
|
+
STACK_FREE(uk);
|
808
865
|
return r;
|
809
866
|
}
|
810
867
|
if(r == PRIMITIVE_CONTAINER_START) {
|
@@ -813,6 +870,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
813
870
|
/* PRIMITIVE_OBJECT_COMPLETE */
|
814
871
|
|
815
872
|
if(msgpack_unpacker_stack_is_empty(uk)) {
|
873
|
+
STACK_FREE(uk);
|
816
874
|
return PRIMITIVE_OBJECT_COMPLETE;
|
817
875
|
}
|
818
876
|
|
@@ -828,6 +886,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
828
886
|
if(count == 0) {
|
829
887
|
object_complete(uk, Qnil);
|
830
888
|
if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
|
889
|
+
STACK_FREE(uk);
|
831
890
|
return PRIMITIVE_OBJECT_COMPLETE;
|
832
891
|
}
|
833
892
|
goto container_completed;
|
data/ext/msgpack/unpacker.h
CHANGED
@@ -50,6 +50,7 @@ struct msgpack_unpacker_stack_t {
|
|
50
50
|
struct msgpack_unpacker_t {
|
51
51
|
msgpack_buffer_t buffer;
|
52
52
|
msgpack_unpacker_stack_t stack;
|
53
|
+
msgpack_key_cache_t key_cache;
|
53
54
|
|
54
55
|
VALUE self;
|
55
56
|
VALUE last_object;
|
@@ -66,10 +67,12 @@ struct msgpack_unpacker_t {
|
|
66
67
|
|
67
68
|
/* options */
|
68
69
|
int symbol_ext_type;
|
69
|
-
|
70
|
-
bool
|
71
|
-
bool
|
72
|
-
bool
|
70
|
+
|
71
|
+
bool use_key_cache: 1;
|
72
|
+
bool symbolize_keys: 1;
|
73
|
+
bool freeze: 1;
|
74
|
+
bool allow_unknown_ext: 1;
|
75
|
+
bool optimized_symbol_ext_type: 1;
|
73
76
|
};
|
74
77
|
|
75
78
|
#define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
|
@@ -101,6 +104,11 @@ static inline void msgpack_unpacker_set_symbolized_keys(msgpack_unpacker_t* uk,
|
|
101
104
|
uk->symbolize_keys = enable;
|
102
105
|
}
|
103
106
|
|
107
|
+
static inline void msgpack_unpacker_set_key_cache(msgpack_unpacker_t* uk, bool enable)
|
108
|
+
{
|
109
|
+
uk->use_key_cache = enable;
|
110
|
+
}
|
111
|
+
|
104
112
|
static inline void msgpack_unpacker_set_freeze(msgpack_unpacker_t* uk, bool enable)
|
105
113
|
{
|
106
114
|
uk->freeze = enable;
|
@@ -34,6 +34,7 @@ static VALUE eUnknownExtTypeError;
|
|
34
34
|
static VALUE mTypeError; // obsoleted. only for backward compatibility. See #86.
|
35
35
|
|
36
36
|
static VALUE sym_symbolize_keys;
|
37
|
+
static VALUE sym_key_cache;
|
37
38
|
static VALUE sym_freeze;
|
38
39
|
static VALUE sym_allow_unknown_ext;
|
39
40
|
|
@@ -128,6 +129,9 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
128
129
|
if(options != Qnil) {
|
129
130
|
VALUE v;
|
130
131
|
|
132
|
+
v = rb_hash_aref(options, sym_key_cache);
|
133
|
+
msgpack_unpacker_set_key_cache(uk, RTEST(v));
|
134
|
+
|
131
135
|
v = rb_hash_aref(options, sym_symbolize_keys);
|
132
136
|
msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
|
133
137
|
|
@@ -284,12 +288,6 @@ static VALUE Unpacker_each_impl(VALUE self)
|
|
284
288
|
raise_unpacker_error(uk, r);
|
285
289
|
}
|
286
290
|
VALUE v = msgpack_unpacker_get_last_object(uk);
|
287
|
-
#ifdef JRUBY
|
288
|
-
/* TODO JRuby's rb_yield behaves differently from Ruby 1.9.3 or Rubinius. */
|
289
|
-
if(rb_type(v) == T_ARRAY) {
|
290
|
-
v = rb_ary_new3(1, v);
|
291
|
-
}
|
292
|
-
#endif
|
293
291
|
rb_yield(v);
|
294
292
|
}
|
295
293
|
}
|
@@ -419,6 +417,7 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
419
417
|
eUnknownExtTypeError = rb_define_class_under(mMessagePack, "UnknownExtTypeError", eUnpackError);
|
420
418
|
|
421
419
|
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
420
|
+
sym_key_cache = ID2SYM(rb_intern("key_cache"));
|
422
421
|
sym_freeze = ID2SYM(rb_intern("freeze"));
|
423
422
|
sym_allow_unknown_ext = ID2SYM(rb_intern("allow_unknown_ext"));
|
424
423
|
|
data/lib/msgpack/version.rb
CHANGED
data/msgpack.gemspec
CHANGED
@@ -31,4 +31,6 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.add_development_dependency 'yard'
|
32
32
|
s.add_development_dependency 'json'
|
33
33
|
s.add_development_dependency 'benchmark-ips', ['~> 2.10.0']
|
34
|
+
|
35
|
+
s.metadata["changelog_uri"] = "https://github.com/msgpack/msgpack-ruby/blob/master/ChangeLog"
|
34
36
|
end
|
metadata
CHANGED
@@ -1,16 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: msgpack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
- Theo Hultberg
|
9
9
|
- Satoshi Tagomori
|
10
|
-
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2025-02-06 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: bundler
|
@@ -192,8 +191,8 @@ files:
|
|
192
191
|
homepage: http://msgpack.org/
|
193
192
|
licenses:
|
194
193
|
- Apache 2.0
|
195
|
-
metadata:
|
196
|
-
|
194
|
+
metadata:
|
195
|
+
changelog_uri: https://github.com/msgpack/msgpack-ruby/blob/master/ChangeLog
|
197
196
|
rdoc_options: []
|
198
197
|
require_paths:
|
199
198
|
- lib
|
@@ -208,8 +207,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
208
207
|
- !ruby/object:Gem::Version
|
209
208
|
version: '0'
|
210
209
|
requirements: []
|
211
|
-
rubygems_version: 3.
|
212
|
-
signing_key:
|
210
|
+
rubygems_version: 3.6.2
|
213
211
|
specification_version: 4
|
214
212
|
summary: MessagePack, a binary-based efficient data interchange format.
|
215
213
|
test_files: []
|