msgpack 1.7.5 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ChangeLog +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: []
|