msgpack 1.7.3 → 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 +13 -0
- data/ext/msgpack/buffer.c +5 -4
- data/ext/msgpack/buffer.h +131 -27
- data/ext/msgpack/extconf.rb +5 -3
- data/ext/msgpack/packer.h +24 -17
- data/ext/msgpack/unpacker.c +178 -80
- data/ext/msgpack/unpacker.h +18 -8
- data/ext/msgpack/unpacker_class.c +27 -17
- 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
@@ -1,3 +1,16 @@
|
|
1
|
+
2025-02-06 1.8.0
|
2
|
+
|
3
|
+
* Numerous small optimizations.
|
4
|
+
* Added `key_cache` option to `Unpacker`.
|
5
|
+
|
6
|
+
2024-11-11 1.7.5
|
7
|
+
|
8
|
+
* Rerelease 1.7.4 with fixed java package.
|
9
|
+
|
10
|
+
2024-11-11 1.7.4
|
11
|
+
|
12
|
+
* Fixed a potental memory leak when recursive unpacker raise.
|
13
|
+
|
1
14
|
2024-10-03 1.7.3
|
2
15
|
|
3
16
|
* Limit initial containers pre-allocation to `SHRT_MAX` (32k) entries.
|
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
@@ -81,20 +81,6 @@ struct msgpack_buffer_chunk_t {
|
|
81
81
|
bool rmem;
|
82
82
|
};
|
83
83
|
|
84
|
-
union msgpack_buffer_cast_block_t {
|
85
|
-
char buffer[8];
|
86
|
-
uint8_t u8;
|
87
|
-
uint16_t u16;
|
88
|
-
uint32_t u32;
|
89
|
-
uint64_t u64;
|
90
|
-
int8_t i8;
|
91
|
-
int16_t i16;
|
92
|
-
int32_t i32;
|
93
|
-
int64_t i64;
|
94
|
-
float f;
|
95
|
-
double d;
|
96
|
-
};
|
97
|
-
|
98
84
|
struct msgpack_buffer_t {
|
99
85
|
char* read_buffer;
|
100
86
|
char* tail_buffer_end;
|
@@ -107,8 +93,6 @@ struct msgpack_buffer_t {
|
|
107
93
|
char* rmem_end;
|
108
94
|
void** rmem_owner;
|
109
95
|
|
110
|
-
union msgpack_buffer_cast_block_t cast_block;
|
111
|
-
|
112
96
|
VALUE io;
|
113
97
|
VALUE io_buffer;
|
114
98
|
ID io_write_all_method;
|
@@ -253,13 +237,14 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string);
|
|
253
237
|
|
254
238
|
static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE string)
|
255
239
|
{
|
256
|
-
size_t length
|
240
|
+
size_t length;
|
241
|
+
char *ptr;
|
242
|
+
RSTRING_GETMEM(string, ptr, length);
|
257
243
|
|
258
244
|
if(length > b->write_reference_threshold) {
|
259
245
|
_msgpack_buffer_append_long_string(b, string);
|
260
|
-
|
261
246
|
} else {
|
262
|
-
msgpack_buffer_append(b,
|
247
|
+
msgpack_buffer_append(b, ptr, length);
|
263
248
|
}
|
264
249
|
|
265
250
|
return length;
|
@@ -383,14 +368,6 @@ static inline size_t msgpack_buffer_skip_nonblock(msgpack_buffer_t* b, size_t le
|
|
383
368
|
return length;
|
384
369
|
}
|
385
370
|
|
386
|
-
static inline union msgpack_buffer_cast_block_t* msgpack_buffer_read_cast_block(msgpack_buffer_t* b, size_t n)
|
387
|
-
{
|
388
|
-
if(!msgpack_buffer_read_all(b, b->cast_block.buffer, n)) {
|
389
|
-
return NULL;
|
390
|
-
}
|
391
|
-
return &b->cast_block;
|
392
|
-
}
|
393
|
-
|
394
371
|
size_t msgpack_buffer_read_to_string_nonblock(msgpack_buffer_t* b, VALUE string, size_t length);
|
395
372
|
|
396
373
|
static inline size_t msgpack_buffer_read_to_string(msgpack_buffer_t* b, VALUE string, size_t length)
|
@@ -497,4 +474,131 @@ static inline VALUE msgpack_buffer_read_top_as_symbol(msgpack_buffer_t* b, size_
|
|
497
474
|
return rb_str_intern(msgpack_buffer_read_top_as_string(b, length, true, utf8));
|
498
475
|
}
|
499
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
|
+
|
500
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,21 +25,26 @@
|
|
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
|
|
31
36
|
struct msgpack_packer_t {
|
32
37
|
msgpack_buffer_t buffer;
|
33
38
|
|
34
|
-
bool compatibility_mode;
|
35
|
-
bool has_bigint_ext_type;
|
36
|
-
bool has_symbol_ext_type;
|
37
|
-
|
38
39
|
ID to_msgpack_method;
|
39
40
|
VALUE to_msgpack_arg;
|
40
41
|
|
41
42
|
VALUE buffer_ref;
|
42
43
|
|
44
|
+
bool compatibility_mode;
|
45
|
+
bool has_bigint_ext_type;
|
46
|
+
bool has_symbol_ext_type;
|
47
|
+
|
43
48
|
/* options */
|
44
49
|
bool comaptibility_mode;
|
45
50
|
msgpack_packer_ext_registry_t ext_registry;
|
@@ -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();
|
422
|
+
}
|
423
|
+
|
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;
|
417
428
|
}
|
418
429
|
|
419
|
-
int encindex =
|
420
|
-
if(msgpack_packer_is_binary(v, encindex)
|
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,40 @@
|
|
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
|
+
|
42
|
+
struct protected_proc_call_args {
|
43
|
+
VALUE proc;
|
44
|
+
int argc;
|
45
|
+
VALUE *argv;
|
46
|
+
};
|
47
|
+
|
48
|
+
static VALUE protected_proc_call_safe(VALUE _args) {
|
49
|
+
struct protected_proc_call_args *args = (struct protected_proc_call_args *)_args;
|
50
|
+
|
51
|
+
return rb_proc_call_with_block(args->proc, args->argc, args->argv, Qnil);
|
52
|
+
}
|
53
|
+
|
54
|
+
static VALUE protected_proc_call(VALUE proc, int argc, VALUE *argv, int *raised) {
|
55
|
+
struct protected_proc_call_args args = {
|
56
|
+
.proc = proc,
|
57
|
+
.argc = argc,
|
58
|
+
.argv = argv,
|
59
|
+
};
|
60
|
+
return rb_protect(protected_proc_call_safe, (VALUE)&args, raised);
|
61
|
+
}
|
62
|
+
|
29
63
|
static int RAW_TYPE_STRING = 256;
|
30
64
|
static int RAW_TYPE_BINARY = 257;
|
31
65
|
static int16_t INITIAL_BUFFER_CAPACITY_MAX = SHRT_MAX;
|
@@ -58,14 +92,29 @@ void msgpack_unpacker_static_destroy(void)
|
|
58
92
|
|
59
93
|
#define HEAD_BYTE_REQUIRED 0xc1
|
60
94
|
|
61
|
-
static inline msgpack_unpacker_stack_t*
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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;
|
103
|
+
}
|
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
|
+
}
|
67
113
|
}
|
68
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
|
+
|
69
118
|
void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
70
119
|
{
|
71
120
|
msgpack_buffer_init(UNPACKER_BUFFER_(uk));
|
@@ -74,41 +123,38 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
|
74
123
|
|
75
124
|
uk->last_object = Qnil;
|
76
125
|
uk->reading_raw = Qnil;
|
77
|
-
|
78
|
-
uk->stack = _msgpack_unpacker_new_stack();
|
79
|
-
}
|
80
|
-
|
81
|
-
static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
|
82
|
-
if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
|
83
|
-
rb_bug("Failed to free an rmem pointer, memory leak?");
|
84
|
-
}
|
85
|
-
xfree(stack);
|
86
126
|
}
|
87
127
|
|
88
128
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
|
89
129
|
{
|
90
|
-
_msgpack_unpacker_free_stack(uk->stack);
|
130
|
+
_msgpack_unpacker_free_stack(&uk->stack);
|
91
131
|
msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
|
92
132
|
}
|
93
133
|
|
94
134
|
void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
|
95
135
|
{
|
96
|
-
|
136
|
+
if (stack->data) {
|
97
137
|
msgpack_unpacker_stack_entry_t* s = stack->data;
|
98
138
|
msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
|
99
139
|
for(; s < send; s++) {
|
100
140
|
rb_gc_mark(s->object);
|
101
141
|
rb_gc_mark(s->key);
|
102
142
|
}
|
103
|
-
stack = stack->parent;
|
104
143
|
}
|
105
144
|
}
|
106
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
|
+
|
107
152
|
void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
|
108
153
|
{
|
109
154
|
rb_gc_mark(uk->last_object);
|
110
155
|
rb_gc_mark(uk->reading_raw);
|
111
|
-
msgpack_unpacker_mark_stack(uk->stack);
|
156
|
+
msgpack_unpacker_mark_stack(&uk->stack);
|
157
|
+
msgpack_unpacker_mark_key_cache(&uk->key_cache);
|
112
158
|
/* See MessagePack_Buffer_wrap */
|
113
159
|
/* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
|
114
160
|
rb_gc_mark(uk->buffer_ref);
|
@@ -121,8 +167,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
|
|
121
167
|
|
122
168
|
uk->head_byte = HEAD_BYTE_REQUIRED;
|
123
169
|
|
124
|
-
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack
|
125
|
-
uk->stack
|
170
|
+
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack.depth);*/
|
171
|
+
uk->stack.depth = 0;
|
126
172
|
uk->last_object = Qnil;
|
127
173
|
uk->reading_raw = Qnil;
|
128
174
|
uk->reading_raw_remaining = 0;
|
@@ -186,7 +232,12 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
|
|
186
232
|
if(proc != Qnil) {
|
187
233
|
VALUE obj;
|
188
234
|
VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
|
189
|
-
|
235
|
+
int raised;
|
236
|
+
obj = protected_proc_call(proc, 1, &arg, &raised);
|
237
|
+
if (raised) {
|
238
|
+
uk->last_object = rb_errinfo();
|
239
|
+
return PRIMITIVE_RECURSIVE_RAISED;
|
240
|
+
}
|
190
241
|
return object_complete(uk, obj);
|
191
242
|
}
|
192
243
|
|
@@ -201,35 +252,35 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
|
|
201
252
|
/* stack funcs */
|
202
253
|
static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
|
203
254
|
{
|
204
|
-
return &uk->stack
|
255
|
+
return &uk->stack.data[uk->stack.depth-1];
|
205
256
|
}
|
206
257
|
|
207
258
|
static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
|
208
259
|
{
|
209
260
|
reset_head_byte(uk);
|
210
261
|
|
211
|
-
if(uk->stack
|
262
|
+
if(uk->stack.capacity - uk->stack.depth <= 0) {
|
212
263
|
return PRIMITIVE_STACK_TOO_DEEP;
|
213
264
|
}
|
214
265
|
|
215
|
-
msgpack_unpacker_stack_entry_t* next = &uk->stack
|
266
|
+
msgpack_unpacker_stack_entry_t* next = &uk->stack.data[uk->stack.depth];
|
216
267
|
next->count = count;
|
217
268
|
next->type = type;
|
218
269
|
next->object = object;
|
219
270
|
next->key = Qnil;
|
220
271
|
|
221
|
-
uk->stack
|
272
|
+
uk->stack.depth++;
|
222
273
|
return PRIMITIVE_CONTAINER_START;
|
223
274
|
}
|
224
275
|
|
225
|
-
static inline
|
276
|
+
static inline size_t msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
|
226
277
|
{
|
227
|
-
return --uk->stack
|
278
|
+
return --uk->stack.depth;
|
228
279
|
}
|
229
280
|
|
230
281
|
static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
|
231
282
|
{
|
232
|
-
return uk->stack
|
283
|
+
return uk->stack.depth == 0;
|
233
284
|
}
|
234
285
|
|
235
286
|
#ifdef USE_CASE_RANGE
|
@@ -248,16 +299,29 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
|
|
248
299
|
|
249
300
|
#endif
|
250
301
|
|
302
|
+
union msgpack_buffer_cast_block_t {
|
303
|
+
char buffer[8];
|
304
|
+
uint8_t u8;
|
305
|
+
uint16_t u16;
|
306
|
+
uint32_t u32;
|
307
|
+
uint64_t u64;
|
308
|
+
int8_t i8;
|
309
|
+
int16_t i16;
|
310
|
+
int32_t i32;
|
311
|
+
int64_t i64;
|
312
|
+
float f;
|
313
|
+
double d;
|
314
|
+
};
|
251
315
|
|
252
316
|
#define READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, n) \
|
253
|
-
union msgpack_buffer_cast_block_t
|
254
|
-
if(
|
317
|
+
union msgpack_buffer_cast_block_t cb; \
|
318
|
+
if (!msgpack_buffer_read_all(UNPACKER_BUFFER_(uk), (char *)&cb.buffer, n)) { \
|
255
319
|
return PRIMITIVE_EOF; \
|
256
320
|
}
|
257
321
|
|
258
322
|
static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
|
259
323
|
{
|
260
|
-
if(uk->stack
|
324
|
+
if(uk->stack.depth > 0) {
|
261
325
|
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
262
326
|
if(top->type == STACK_TYPE_MAP_KEY) {
|
263
327
|
return true;
|
@@ -312,14 +376,15 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
312
376
|
reset_head_byte(uk);
|
313
377
|
uk->reading_raw_remaining = 0;
|
314
378
|
|
315
|
-
|
316
|
-
|
317
|
-
uk->
|
379
|
+
_msgpack_unpacker_stack_push(uk, STACK_TYPE_RECURSIVE, 1, Qnil);
|
380
|
+
int raised;
|
381
|
+
obj = protected_proc_call(proc, 1, &uk->self, &raised);
|
382
|
+
msgpack_unpacker_stack_pop(uk);
|
318
383
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
384
|
+
if (raised) {
|
385
|
+
uk->last_object = rb_errinfo();
|
386
|
+
return PRIMITIVE_RECURSIVE_RAISED;
|
387
|
+
}
|
323
388
|
|
324
389
|
return object_complete(uk, obj);
|
325
390
|
}
|
@@ -329,15 +394,32 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
329
394
|
size_t length = uk->reading_raw_remaining;
|
330
395
|
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
|
331
396
|
int ret;
|
332
|
-
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)) {
|
333
398
|
VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
|
334
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
|
+
}
|
335
420
|
} else {
|
336
421
|
bool will_freeze = uk->freeze;
|
337
422
|
if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
|
338
|
-
/* don't use zerocopy for hash keys but get a frozen string directly
|
339
|
-
* because rb_hash_aset freezes keys and it causes copying */
|
340
|
-
will_freeze = will_freeze || is_reading_map_key(uk);
|
341
423
|
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
342
424
|
ret = object_complete(uk, string);
|
343
425
|
} else {
|
@@ -407,8 +489,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
407
489
|
case 0xc7: // ext 8
|
408
490
|
{
|
409
491
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
410
|
-
uint8_t length = cb
|
411
|
-
int ext_type = (signed char) cb
|
492
|
+
uint8_t length = cb.u8;
|
493
|
+
int ext_type = (signed char) cb.buffer[1];
|
412
494
|
if(length == 0) {
|
413
495
|
return object_complete_ext(uk, ext_type, Qnil);
|
414
496
|
}
|
@@ -419,8 +501,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
419
501
|
case 0xc8: // ext 16
|
420
502
|
{
|
421
503
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 3);
|
422
|
-
uint16_t length = _msgpack_be16(cb
|
423
|
-
int ext_type = (signed char) cb
|
504
|
+
uint16_t length = _msgpack_be16(cb.u16);
|
505
|
+
int ext_type = (signed char) cb.buffer[2];
|
424
506
|
if(length == 0) {
|
425
507
|
return object_complete_ext(uk, ext_type, Qnil);
|
426
508
|
}
|
@@ -431,8 +513,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
431
513
|
case 0xc9: // ext 32
|
432
514
|
{
|
433
515
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 5);
|
434
|
-
uint32_t length = _msgpack_be32(cb
|
435
|
-
int ext_type = (signed char) cb
|
516
|
+
uint32_t length = _msgpack_be32(cb.u32);
|
517
|
+
int ext_type = (signed char) cb.buffer[4];
|
436
518
|
if(length == 0) {
|
437
519
|
return object_complete_ext(uk, ext_type, Qnil);
|
438
520
|
}
|
@@ -443,77 +525,77 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
443
525
|
case 0xca: // float
|
444
526
|
{
|
445
527
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
446
|
-
cb
|
447
|
-
return object_complete(uk, rb_float_new(cb
|
528
|
+
cb.u32 = _msgpack_be_float(cb.u32);
|
529
|
+
return object_complete(uk, rb_float_new(cb.f));
|
448
530
|
}
|
449
531
|
|
450
532
|
case 0xcb: // double
|
451
533
|
{
|
452
534
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
|
453
|
-
cb
|
454
|
-
return object_complete(uk, rb_float_new(cb
|
535
|
+
cb.u64 = _msgpack_be_double(cb.u64);
|
536
|
+
return object_complete(uk, rb_float_new(cb.d));
|
455
537
|
}
|
456
538
|
|
457
539
|
case 0xcc: // unsigned int 8
|
458
540
|
{
|
459
541
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
460
|
-
uint8_t u8 = cb
|
542
|
+
uint8_t u8 = cb.u8;
|
461
543
|
return object_complete(uk, INT2NUM((int)u8));
|
462
544
|
}
|
463
545
|
|
464
546
|
case 0xcd: // unsigned int 16
|
465
547
|
{
|
466
548
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
467
|
-
uint16_t u16 = _msgpack_be16(cb
|
549
|
+
uint16_t u16 = _msgpack_be16(cb.u16);
|
468
550
|
return object_complete(uk, INT2NUM((int)u16));
|
469
551
|
}
|
470
552
|
|
471
553
|
case 0xce: // unsigned int 32
|
472
554
|
{
|
473
555
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
474
|
-
uint32_t u32 = _msgpack_be32(cb
|
556
|
+
uint32_t u32 = _msgpack_be32(cb.u32);
|
475
557
|
return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
|
476
558
|
}
|
477
559
|
|
478
560
|
case 0xcf: // unsigned int 64
|
479
561
|
{
|
480
562
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
|
481
|
-
uint64_t u64 = _msgpack_be64(cb
|
563
|
+
uint64_t u64 = _msgpack_be64(cb.u64);
|
482
564
|
return object_complete(uk, rb_ull2inum(u64));
|
483
565
|
}
|
484
566
|
|
485
567
|
case 0xd0: // signed int 8
|
486
568
|
{
|
487
569
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
488
|
-
int8_t i8 = cb
|
570
|
+
int8_t i8 = cb.i8;
|
489
571
|
return object_complete(uk, INT2NUM((int)i8));
|
490
572
|
}
|
491
573
|
|
492
574
|
case 0xd1: // signed int 16
|
493
575
|
{
|
494
576
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
495
|
-
int16_t i16 = _msgpack_be16(cb
|
577
|
+
int16_t i16 = _msgpack_be16(cb.i16);
|
496
578
|
return object_complete(uk, INT2NUM((int)i16));
|
497
579
|
}
|
498
580
|
|
499
581
|
case 0xd2: // signed int 32
|
500
582
|
{
|
501
583
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
502
|
-
int32_t i32 = _msgpack_be32(cb
|
584
|
+
int32_t i32 = _msgpack_be32(cb.i32);
|
503
585
|
return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
|
504
586
|
}
|
505
587
|
|
506
588
|
case 0xd3: // signed int 64
|
507
589
|
{
|
508
590
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
|
509
|
-
int64_t i64 = _msgpack_be64(cb
|
591
|
+
int64_t i64 = _msgpack_be64(cb.i64);
|
510
592
|
return object_complete(uk, rb_ll2inum(i64));
|
511
593
|
}
|
512
594
|
|
513
595
|
case 0xd4: // fixext 1
|
514
596
|
{
|
515
597
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
516
|
-
int ext_type = cb
|
598
|
+
int ext_type = cb.i8;
|
517
599
|
uk->reading_raw_remaining = 1;
|
518
600
|
return read_raw_body_begin(uk, ext_type);
|
519
601
|
}
|
@@ -521,7 +603,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
521
603
|
case 0xd5: // fixext 2
|
522
604
|
{
|
523
605
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
524
|
-
int ext_type = cb
|
606
|
+
int ext_type = cb.i8;
|
525
607
|
uk->reading_raw_remaining = 2;
|
526
608
|
return read_raw_body_begin(uk, ext_type);
|
527
609
|
}
|
@@ -529,7 +611,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
529
611
|
case 0xd6: // fixext 4
|
530
612
|
{
|
531
613
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
532
|
-
int ext_type = cb
|
614
|
+
int ext_type = cb.i8;
|
533
615
|
uk->reading_raw_remaining = 4;
|
534
616
|
return read_raw_body_begin(uk, ext_type);
|
535
617
|
}
|
@@ -537,7 +619,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
537
619
|
case 0xd7: // fixext 8
|
538
620
|
{
|
539
621
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
540
|
-
int ext_type = cb
|
622
|
+
int ext_type = cb.i8;
|
541
623
|
uk->reading_raw_remaining = 8;
|
542
624
|
return read_raw_body_begin(uk, ext_type);
|
543
625
|
}
|
@@ -545,7 +627,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
545
627
|
case 0xd8: // fixext 16
|
546
628
|
{
|
547
629
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
548
|
-
int ext_type = cb
|
630
|
+
int ext_type = cb.i8;
|
549
631
|
uk->reading_raw_remaining = 16;
|
550
632
|
return read_raw_body_begin(uk, ext_type);
|
551
633
|
}
|
@@ -554,7 +636,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
554
636
|
case 0xd9: // raw 8 / str 8
|
555
637
|
{
|
556
638
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
557
|
-
uint8_t count = cb
|
639
|
+
uint8_t count = cb.u8;
|
558
640
|
/* read_raw_body_begin sets uk->reading_raw */
|
559
641
|
uk->reading_raw_remaining = count;
|
560
642
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -563,7 +645,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
563
645
|
case 0xda: // raw 16 / str 16
|
564
646
|
{
|
565
647
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
566
|
-
uint16_t count = _msgpack_be16(cb
|
648
|
+
uint16_t count = _msgpack_be16(cb.u16);
|
567
649
|
/* read_raw_body_begin sets uk->reading_raw */
|
568
650
|
uk->reading_raw_remaining = count;
|
569
651
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -572,7 +654,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
572
654
|
case 0xdb: // raw 32 / str 32
|
573
655
|
{
|
574
656
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
575
|
-
uint32_t count = _msgpack_be32(cb
|
657
|
+
uint32_t count = _msgpack_be32(cb.u32);
|
576
658
|
/* read_raw_body_begin sets uk->reading_raw */
|
577
659
|
uk->reading_raw_remaining = count;
|
578
660
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -581,7 +663,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
581
663
|
case 0xc4: // bin 8
|
582
664
|
{
|
583
665
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
584
|
-
uint8_t count = cb
|
666
|
+
uint8_t count = cb.u8;
|
585
667
|
/* read_raw_body_begin sets uk->reading_raw */
|
586
668
|
uk->reading_raw_remaining = count;
|
587
669
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -590,7 +672,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
590
672
|
case 0xc5: // bin 16
|
591
673
|
{
|
592
674
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
593
|
-
uint16_t count = _msgpack_be16(cb
|
675
|
+
uint16_t count = _msgpack_be16(cb.u16);
|
594
676
|
/* read_raw_body_begin sets uk->reading_raw */
|
595
677
|
uk->reading_raw_remaining = count;
|
596
678
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -599,7 +681,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
599
681
|
case 0xc6: // bin 32
|
600
682
|
{
|
601
683
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
602
|
-
uint32_t count = _msgpack_be32(cb
|
684
|
+
uint32_t count = _msgpack_be32(cb.u32);
|
603
685
|
/* read_raw_body_begin sets uk->reading_raw */
|
604
686
|
uk->reading_raw_remaining = count;
|
605
687
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -608,7 +690,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
608
690
|
case 0xdc: // array 16
|
609
691
|
{
|
610
692
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
611
|
-
uint16_t count = _msgpack_be16(cb
|
693
|
+
uint16_t count = _msgpack_be16(cb.u16);
|
612
694
|
if(count == 0) {
|
613
695
|
return object_complete(uk, rb_ary_new());
|
614
696
|
}
|
@@ -618,7 +700,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
618
700
|
case 0xdd: // array 32
|
619
701
|
{
|
620
702
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
621
|
-
uint32_t count = _msgpack_be32(cb
|
703
|
+
uint32_t count = _msgpack_be32(cb.u32);
|
622
704
|
if(count == 0) {
|
623
705
|
return object_complete(uk, rb_ary_new());
|
624
706
|
}
|
@@ -628,7 +710,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
628
710
|
case 0xde: // map 16
|
629
711
|
{
|
630
712
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
631
|
-
uint16_t count = _msgpack_be16(cb
|
713
|
+
uint16_t count = _msgpack_be16(cb.u16);
|
632
714
|
if(count == 0) {
|
633
715
|
return object_complete(uk, rb_hash_new());
|
634
716
|
}
|
@@ -638,7 +720,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
638
720
|
case 0xdf: // map 32
|
639
721
|
{
|
640
722
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
641
|
-
uint32_t count = _msgpack_be32(cb
|
723
|
+
uint32_t count = _msgpack_be32(cb.u32);
|
642
724
|
if(count == 0) {
|
643
725
|
return object_complete(uk, rb_hash_new());
|
644
726
|
}
|
@@ -668,12 +750,12 @@ int msgpack_unpacker_read_array_header(msgpack_unpacker_t* uk, uint32_t* result_
|
|
668
750
|
} else if(b == 0xdc) {
|
669
751
|
/* array 16 */
|
670
752
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
671
|
-
*result_size = _msgpack_be16(cb
|
753
|
+
*result_size = _msgpack_be16(cb.u16);
|
672
754
|
|
673
755
|
} else if(b == 0xdd) {
|
674
756
|
/* array 32 */
|
675
757
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
676
|
-
*result_size = _msgpack_be32(cb
|
758
|
+
*result_size = _msgpack_be32(cb.u32);
|
677
759
|
|
678
760
|
} else {
|
679
761
|
return PRIMITIVE_UNEXPECTED_TYPE;
|
@@ -696,12 +778,12 @@ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_si
|
|
696
778
|
} else if(b == 0xde) {
|
697
779
|
/* map 16 */
|
698
780
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
699
|
-
*result_size = _msgpack_be16(cb
|
781
|
+
*result_size = _msgpack_be16(cb.u16);
|
700
782
|
|
701
783
|
} else if(b == 0xdf) {
|
702
784
|
/* map 32 */
|
703
785
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
704
|
-
*result_size = _msgpack_be32(cb
|
786
|
+
*result_size = _msgpack_be32(cb.u32);
|
705
787
|
|
706
788
|
} else {
|
707
789
|
return PRIMITIVE_UNEXPECTED_TYPE;
|
@@ -713,9 +795,15 @@ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_si
|
|
713
795
|
|
714
796
|
int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
715
797
|
{
|
798
|
+
STACK_INIT(uk);
|
799
|
+
|
716
800
|
while(true) {
|
717
801
|
int r = read_primitive(uk);
|
718
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
|
+
}
|
719
807
|
return r;
|
720
808
|
}
|
721
809
|
if(r == PRIMITIVE_CONTAINER_START) {
|
@@ -724,6 +812,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
724
812
|
/* PRIMITIVE_OBJECT_COMPLETE */
|
725
813
|
|
726
814
|
if(msgpack_unpacker_stack_is_empty(uk)) {
|
815
|
+
STACK_FREE(uk);
|
727
816
|
return PRIMITIVE_OBJECT_COMPLETE;
|
728
817
|
}
|
729
818
|
|
@@ -747,12 +836,16 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
747
836
|
}
|
748
837
|
top->type = STACK_TYPE_MAP_KEY;
|
749
838
|
break;
|
839
|
+
case STACK_TYPE_RECURSIVE:
|
840
|
+
STACK_FREE(uk);
|
841
|
+
return PRIMITIVE_OBJECT_COMPLETE;
|
750
842
|
}
|
751
843
|
size_t count = --top->count;
|
752
844
|
|
753
845
|
if(count == 0) {
|
754
846
|
object_complete(uk, top->object);
|
755
847
|
if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
|
848
|
+
STACK_FREE(uk);
|
756
849
|
return PRIMITIVE_OBJECT_COMPLETE;
|
757
850
|
}
|
758
851
|
goto container_completed;
|
@@ -763,9 +856,12 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
763
856
|
|
764
857
|
int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
765
858
|
{
|
859
|
+
STACK_INIT(uk);
|
860
|
+
|
766
861
|
while(true) {
|
767
862
|
int r = read_primitive(uk);
|
768
863
|
if(r < 0) {
|
864
|
+
STACK_FREE(uk);
|
769
865
|
return r;
|
770
866
|
}
|
771
867
|
if(r == PRIMITIVE_CONTAINER_START) {
|
@@ -774,6 +870,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
774
870
|
/* PRIMITIVE_OBJECT_COMPLETE */
|
775
871
|
|
776
872
|
if(msgpack_unpacker_stack_is_empty(uk)) {
|
873
|
+
STACK_FREE(uk);
|
777
874
|
return PRIMITIVE_OBJECT_COMPLETE;
|
778
875
|
}
|
779
876
|
|
@@ -789,6 +886,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
789
886
|
if(count == 0) {
|
790
887
|
object_complete(uk, Qnil);
|
791
888
|
if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
|
889
|
+
STACK_FREE(uk);
|
792
890
|
return PRIMITIVE_OBJECT_COMPLETE;
|
793
891
|
}
|
794
892
|
goto container_completed;
|
data/ext/msgpack/unpacker.h
CHANGED
@@ -31,6 +31,7 @@ enum stack_type_t {
|
|
31
31
|
STACK_TYPE_ARRAY,
|
32
32
|
STACK_TYPE_MAP_KEY,
|
33
33
|
STACK_TYPE_MAP_VALUE,
|
34
|
+
STACK_TYPE_RECURSIVE,
|
34
35
|
};
|
35
36
|
|
36
37
|
typedef struct {
|
@@ -44,31 +45,34 @@ struct msgpack_unpacker_stack_t {
|
|
44
45
|
size_t depth;
|
45
46
|
size_t capacity;
|
46
47
|
msgpack_unpacker_stack_entry_t *data;
|
47
|
-
msgpack_unpacker_stack_t *parent;
|
48
48
|
};
|
49
49
|
|
50
50
|
struct msgpack_unpacker_t {
|
51
51
|
msgpack_buffer_t buffer;
|
52
|
-
msgpack_unpacker_stack_t
|
53
|
-
|
52
|
+
msgpack_unpacker_stack_t stack;
|
53
|
+
msgpack_key_cache_t key_cache;
|
54
54
|
|
55
55
|
VALUE self;
|
56
56
|
VALUE last_object;
|
57
57
|
|
58
58
|
VALUE reading_raw;
|
59
59
|
size_t reading_raw_remaining;
|
60
|
-
int reading_raw_type;
|
61
60
|
|
62
61
|
VALUE buffer_ref;
|
63
62
|
|
64
63
|
msgpack_unpacker_ext_registry_t *ext_registry;
|
65
64
|
|
65
|
+
int reading_raw_type;
|
66
|
+
unsigned int head_byte;
|
67
|
+
|
66
68
|
/* options */
|
67
|
-
bool symbolize_keys;
|
68
|
-
bool freeze;
|
69
|
-
bool allow_unknown_ext;
|
70
|
-
bool optimized_symbol_ext_type;
|
71
69
|
int symbol_ext_type;
|
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;
|
72
76
|
};
|
73
77
|
|
74
78
|
#define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
|
@@ -100,6 +104,11 @@ static inline void msgpack_unpacker_set_symbolized_keys(msgpack_unpacker_t* uk,
|
|
100
104
|
uk->symbolize_keys = enable;
|
101
105
|
}
|
102
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
|
+
|
103
112
|
static inline void msgpack_unpacker_set_freeze(msgpack_unpacker_t* uk, bool enable)
|
104
113
|
{
|
105
114
|
uk->freeze = enable;
|
@@ -119,6 +128,7 @@ static inline void msgpack_unpacker_set_allow_unknown_ext(msgpack_unpacker_t* uk
|
|
119
128
|
#define PRIMITIVE_STACK_TOO_DEEP -3
|
120
129
|
#define PRIMITIVE_UNEXPECTED_TYPE -4
|
121
130
|
#define PRIMITIVE_UNEXPECTED_EXT_TYPE -5
|
131
|
+
#define PRIMITIVE_RECURSIVE_RAISED -6
|
122
132
|
|
123
133
|
int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth);
|
124
134
|
|
@@ -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
|
|
@@ -58,14 +59,17 @@ static void Unpacker_mark(void *ptr)
|
|
58
59
|
|
59
60
|
static size_t Unpacker_memsize(const void *ptr)
|
60
61
|
{
|
62
|
+
const msgpack_unpacker_t* uk = ptr;
|
63
|
+
|
61
64
|
size_t total_size = sizeof(msgpack_unpacker_t);
|
62
65
|
|
63
|
-
const msgpack_unpacker_t* uk = ptr;
|
64
66
|
if (uk->ext_registry) {
|
65
67
|
total_size += sizeof(msgpack_unpacker_ext_registry_t) / (uk->ext_registry->borrow_count + 1);
|
66
68
|
}
|
67
69
|
|
68
|
-
|
70
|
+
if (uk->stack.data) {
|
71
|
+
total_size += (uk->stack.depth + 1) * sizeof(msgpack_unpacker_stack_t);
|
72
|
+
}
|
69
73
|
|
70
74
|
return total_size + msgpack_buffer_memsize(&uk->buffer);
|
71
75
|
}
|
@@ -125,6 +129,9 @@ VALUE MessagePack_Unpacker_initialize(int argc, VALUE* argv, VALUE self)
|
|
125
129
|
if(options != Qnil) {
|
126
130
|
VALUE v;
|
127
131
|
|
132
|
+
v = rb_hash_aref(options, sym_key_cache);
|
133
|
+
msgpack_unpacker_set_key_cache(uk, RTEST(v));
|
134
|
+
|
128
135
|
v = rb_hash_aref(options, sym_symbolize_keys);
|
129
136
|
msgpack_unpacker_set_symbolized_keys(uk, RTEST(v));
|
130
137
|
|
@@ -156,20 +163,28 @@ static VALUE Unpacker_allow_unknown_ext_p(VALUE self)
|
|
156
163
|
return uk->allow_unknown_ext ? Qtrue : Qfalse;
|
157
164
|
}
|
158
165
|
|
159
|
-
NORETURN(static void raise_unpacker_error(int r))
|
166
|
+
NORETURN(static void raise_unpacker_error(msgpack_unpacker_t *uk, int r))
|
160
167
|
{
|
168
|
+
uk->stack.depth = 0;
|
161
169
|
switch(r) {
|
162
170
|
case PRIMITIVE_EOF:
|
163
171
|
rb_raise(rb_eEOFError, "end of buffer reached");
|
172
|
+
break;
|
164
173
|
case PRIMITIVE_INVALID_BYTE:
|
165
174
|
rb_raise(eMalformedFormatError, "invalid byte");
|
175
|
+
break;
|
166
176
|
case PRIMITIVE_STACK_TOO_DEEP:
|
167
177
|
rb_raise(eStackError, "stack level too deep");
|
178
|
+
break;
|
168
179
|
case PRIMITIVE_UNEXPECTED_TYPE:
|
169
180
|
rb_raise(eUnexpectedTypeError, "unexpected type");
|
181
|
+
break;
|
170
182
|
case PRIMITIVE_UNEXPECTED_EXT_TYPE:
|
171
|
-
// rb_bug("unexpected extension type");
|
172
183
|
rb_raise(eUnknownExtTypeError, "unexpected extension type");
|
184
|
+
break;
|
185
|
+
case PRIMITIVE_RECURSIVE_RAISED:
|
186
|
+
rb_exc_raise(msgpack_unpacker_get_last_object(uk));
|
187
|
+
break;
|
173
188
|
default:
|
174
189
|
rb_raise(eUnpackError, "logically unknown error %d", r);
|
175
190
|
}
|
@@ -190,7 +205,7 @@ static VALUE Unpacker_read(VALUE self)
|
|
190
205
|
|
191
206
|
int r = msgpack_unpacker_read(uk, 0);
|
192
207
|
if(r < 0) {
|
193
|
-
raise_unpacker_error(r);
|
208
|
+
raise_unpacker_error(uk, r);
|
194
209
|
}
|
195
210
|
|
196
211
|
return msgpack_unpacker_get_last_object(uk);
|
@@ -202,7 +217,7 @@ static VALUE Unpacker_skip(VALUE self)
|
|
202
217
|
|
203
218
|
int r = msgpack_unpacker_skip(uk, 0);
|
204
219
|
if(r < 0) {
|
205
|
-
raise_unpacker_error(r);
|
220
|
+
raise_unpacker_error(uk, r);
|
206
221
|
}
|
207
222
|
|
208
223
|
return Qnil;
|
@@ -214,7 +229,7 @@ static VALUE Unpacker_skip_nil(VALUE self)
|
|
214
229
|
|
215
230
|
int r = msgpack_unpacker_skip_nil(uk);
|
216
231
|
if(r < 0) {
|
217
|
-
raise_unpacker_error(r);
|
232
|
+
raise_unpacker_error(uk, r);
|
218
233
|
}
|
219
234
|
|
220
235
|
if(r) {
|
@@ -230,7 +245,7 @@ static VALUE Unpacker_read_array_header(VALUE self)
|
|
230
245
|
uint32_t size;
|
231
246
|
int r = msgpack_unpacker_read_array_header(uk, &size);
|
232
247
|
if(r < 0) {
|
233
|
-
raise_unpacker_error(r);
|
248
|
+
raise_unpacker_error(uk, r);
|
234
249
|
}
|
235
250
|
|
236
251
|
return ULONG2NUM(size); // long at least 32 bits
|
@@ -243,7 +258,7 @@ static VALUE Unpacker_read_map_header(VALUE self)
|
|
243
258
|
uint32_t size;
|
244
259
|
int r = msgpack_unpacker_read_map_header(uk, &size);
|
245
260
|
if(r < 0) {
|
246
|
-
raise_unpacker_error(
|
261
|
+
raise_unpacker_error(uk, r);
|
247
262
|
}
|
248
263
|
|
249
264
|
return ULONG2NUM(size); // long at least 32 bits
|
@@ -270,15 +285,9 @@ static VALUE Unpacker_each_impl(VALUE self)
|
|
270
285
|
if(r == PRIMITIVE_EOF) {
|
271
286
|
return Qnil;
|
272
287
|
}
|
273
|
-
raise_unpacker_error(r);
|
288
|
+
raise_unpacker_error(uk, r);
|
274
289
|
}
|
275
290
|
VALUE v = msgpack_unpacker_get_last_object(uk);
|
276
|
-
#ifdef JRUBY
|
277
|
-
/* TODO JRuby's rb_yield behaves differently from Ruby 1.9.3 or Rubinius. */
|
278
|
-
if(rb_type(v) == T_ARRAY) {
|
279
|
-
v = rb_ary_new3(1, v);
|
280
|
-
}
|
281
|
-
#endif
|
282
291
|
rb_yield(v);
|
283
292
|
}
|
284
293
|
}
|
@@ -369,7 +378,7 @@ static VALUE Unpacker_full_unpack(VALUE self)
|
|
369
378
|
|
370
379
|
int r = msgpack_unpacker_read(uk, 0);
|
371
380
|
if(r < 0) {
|
372
|
-
raise_unpacker_error(r);
|
381
|
+
raise_unpacker_error(uk, r);
|
373
382
|
}
|
374
383
|
|
375
384
|
/* raise if extra bytes follow */
|
@@ -408,6 +417,7 @@ void MessagePack_Unpacker_module_init(VALUE mMessagePack)
|
|
408
417
|
eUnknownExtTypeError = rb_define_class_under(mMessagePack, "UnknownExtTypeError", eUnpackError);
|
409
418
|
|
410
419
|
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
420
|
+
sym_key_cache = ID2SYM(rb_intern("key_cache"));
|
411
421
|
sym_freeze = ID2SYM(rb_intern("freeze"));
|
412
422
|
sym_allow_unknown_ext = ID2SYM(rb_intern("allow_unknown_ext"));
|
413
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: []
|