msgpack 1.4.2 → 1.7.2
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 +85 -0
- data/README.md +52 -1
- data/ext/java/org/msgpack/jruby/Buffer.java +26 -19
- data/ext/java/org/msgpack/jruby/Decoder.java +29 -21
- data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +43 -64
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +6 -9
- data/ext/java/org/msgpack/jruby/Factory.java +43 -42
- data/ext/java/org/msgpack/jruby/Packer.java +37 -40
- data/ext/java/org/msgpack/jruby/Unpacker.java +80 -73
- data/ext/msgpack/buffer.c +54 -74
- data/ext/msgpack/buffer.h +21 -18
- data/ext/msgpack/buffer_class.c +161 -52
- data/ext/msgpack/buffer_class.h +1 -0
- data/ext/msgpack/compat.h +0 -99
- data/ext/msgpack/extconf.rb +25 -46
- data/ext/msgpack/factory_class.c +143 -87
- data/ext/msgpack/packer.c +66 -43
- data/ext/msgpack/packer.h +25 -20
- data/ext/msgpack/packer_class.c +102 -130
- data/ext/msgpack/packer_class.h +11 -0
- data/ext/msgpack/packer_ext_registry.c +35 -40
- data/ext/msgpack/packer_ext_registry.h +41 -38
- data/ext/msgpack/rbinit.c +1 -1
- data/ext/msgpack/rmem.c +3 -4
- data/ext/msgpack/sysdep.h +5 -2
- data/ext/msgpack/unpacker.c +126 -108
- data/ext/msgpack/unpacker.h +16 -13
- data/ext/msgpack/unpacker_class.c +86 -126
- data/ext/msgpack/unpacker_class.h +11 -0
- data/ext/msgpack/unpacker_ext_registry.c +40 -28
- data/ext/msgpack/unpacker_ext_registry.h +21 -18
- data/lib/msgpack/bigint.rb +69 -0
- data/lib/msgpack/buffer.rb +9 -0
- data/lib/msgpack/factory.rb +140 -10
- data/lib/msgpack/packer.rb +10 -1
- data/lib/msgpack/symbol.rb +21 -4
- data/lib/msgpack/time.rb +1 -1
- data/lib/msgpack/unpacker.rb +14 -1
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +6 -7
- data/msgpack.gemspec +8 -5
- metadata +37 -82
- data/.gitignore +0 -23
- data/.rubocop.yml +0 -36
- data/.travis.yml +0 -39
- data/Gemfile +0 -9
- data/Rakefile +0 -71
- data/appveyor.yml +0 -18
- data/bench/pack.rb +0 -23
- data/bench/pack_log.rb +0 -33
- data/bench/pack_log_long.rb +0 -65
- data/bench/pack_symbols.rb +0 -28
- data/bench/run.sh +0 -14
- data/bench/run_long.sh +0 -35
- data/bench/run_symbols.sh +0 -26
- data/bench/unpack.rb +0 -21
- data/bench/unpack_log.rb +0 -34
- data/bench/unpack_log_long.rb +0 -67
- data/doclib/msgpack/buffer.rb +0 -193
- data/doclib/msgpack/core_ext.rb +0 -101
- data/doclib/msgpack/error.rb +0 -19
- data/doclib/msgpack/extension_value.rb +0 -9
- data/doclib/msgpack/factory.rb +0 -101
- data/doclib/msgpack/packer.rb +0 -208
- data/doclib/msgpack/time.rb +0 -22
- data/doclib/msgpack/timestamp.rb +0 -44
- data/doclib/msgpack/unpacker.rb +0 -183
- data/doclib/msgpack.rb +0 -87
- data/msgpack.org.md +0 -46
- data/spec/cases.json +0 -1
- data/spec/cases.msg +0 -0
- data/spec/cases_compact.msg +0 -0
- data/spec/cases_spec.rb +0 -39
- data/spec/cruby/buffer_io_spec.rb +0 -255
- data/spec/cruby/buffer_packer.rb +0 -29
- data/spec/cruby/buffer_spec.rb +0 -575
- data/spec/cruby/buffer_unpacker.rb +0 -19
- data/spec/cruby/unpacker_spec.rb +0 -70
- data/spec/ext_value_spec.rb +0 -99
- data/spec/exttypes.rb +0 -51
- data/spec/factory_spec.rb +0 -367
- data/spec/format_spec.rb +0 -301
- data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
- data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
- data/spec/jruby/unpacker_spec.rb +0 -186
- data/spec/msgpack_spec.rb +0 -214
- data/spec/pack_spec.rb +0 -61
- data/spec/packer_spec.rb +0 -557
- data/spec/random_compat.rb +0 -24
- data/spec/spec_helper.rb +0 -55
- data/spec/timestamp_spec.rb +0 -121
- data/spec/unpack_spec.rb +0 -57
- data/spec/unpacker_spec.rb +0 -819
@@ -21,6 +21,8 @@
|
|
21
21
|
#include "compat.h"
|
22
22
|
#include "ruby.h"
|
23
23
|
|
24
|
+
#define MSGPACK_EXT_RECURSIVE 0b0001
|
25
|
+
|
24
26
|
struct msgpack_packer_ext_registry_t;
|
25
27
|
typedef struct msgpack_packer_ext_registry_t msgpack_packer_ext_registry_t;
|
26
28
|
|
@@ -29,22 +31,21 @@ struct msgpack_packer_ext_registry_t {
|
|
29
31
|
VALUE cache; // lookup cache for ext types inherited from a super class
|
30
32
|
};
|
31
33
|
|
32
|
-
void
|
33
|
-
|
34
|
-
void msgpack_packer_ext_registry_static_destroy();
|
35
|
-
|
36
|
-
void msgpack_packer_ext_registry_init(msgpack_packer_ext_registry_t* pkrg);
|
34
|
+
void msgpack_packer_ext_registry_init(VALUE owner, msgpack_packer_ext_registry_t* pkrg);
|
37
35
|
|
38
36
|
static inline void msgpack_packer_ext_registry_destroy(msgpack_packer_ext_registry_t* pkrg)
|
39
37
|
{ }
|
40
38
|
|
41
39
|
void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg);
|
42
40
|
|
43
|
-
void
|
41
|
+
void msgpack_packer_ext_registry_borrow(VALUE owner, msgpack_packer_ext_registry_t* src,
|
44
42
|
msgpack_packer_ext_registry_t* dst);
|
45
43
|
|
46
|
-
VALUE
|
47
|
-
|
44
|
+
void msgpack_packer_ext_registry_dup(VALUE owner, msgpack_packer_ext_registry_t* src,
|
45
|
+
msgpack_packer_ext_registry_t* dst);
|
46
|
+
|
47
|
+
void msgpack_packer_ext_registry_put(VALUE owner, msgpack_packer_ext_registry_t* pkrg,
|
48
|
+
VALUE ext_module, int ext_type, int flags, VALUE proc);
|
48
49
|
|
49
50
|
static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
|
50
51
|
{
|
@@ -60,59 +61,60 @@ static int msgpack_packer_ext_find_superclass(VALUE key, VALUE value, VALUE arg)
|
|
60
61
|
}
|
61
62
|
|
62
63
|
static inline VALUE msgpack_packer_ext_registry_fetch(msgpack_packer_ext_registry_t* pkrg,
|
63
|
-
VALUE lookup_class, int* ext_type_result)
|
64
|
+
VALUE lookup_class, int* ext_type_result, int* ext_flags_result)
|
64
65
|
{
|
65
66
|
// fetch lookup_class from hash, which is a hash to register classes
|
66
67
|
VALUE type = rb_hash_lookup(pkrg->hash, lookup_class);
|
67
68
|
if(type != Qnil) {
|
68
69
|
*ext_type_result = FIX2INT(rb_ary_entry(type, 0));
|
70
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(type, 2));
|
69
71
|
return rb_ary_entry(type, 1);
|
70
72
|
}
|
71
73
|
|
72
74
|
// fetch lookup_class from cache, which stores results of searching ancestors from pkrg->hash
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
75
|
+
if (RTEST(pkrg->cache)) {
|
76
|
+
VALUE type_inht = rb_hash_lookup(pkrg->cache, lookup_class);
|
77
|
+
if(type_inht != Qnil) {
|
78
|
+
*ext_type_result = FIX2INT(rb_ary_entry(type_inht, 0));
|
79
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(type_inht, 2));
|
80
|
+
return rb_ary_entry(type_inht, 1);
|
81
|
+
}
|
77
82
|
}
|
78
83
|
|
79
84
|
return Qnil;
|
80
85
|
}
|
81
86
|
|
82
87
|
static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_registry_t* pkrg,
|
83
|
-
VALUE instance, int* ext_type_result)
|
88
|
+
VALUE instance, int* ext_type_result, int* ext_flags_result)
|
84
89
|
{
|
85
|
-
VALUE lookup_class;
|
86
90
|
VALUE type;
|
87
91
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
* Objects of type Integer (Fixnum, Bignum), Float, Symbol and frozen
|
92
|
-
* String have no singleton class and raise a TypeError when trying to get
|
93
|
-
* it. See implementation of #singleton_class in ruby's source code:
|
94
|
-
* VALUE rb_singleton_class(VALUE obj);
|
95
|
-
*
|
96
|
-
* Since all but symbols are already filtered out when reaching this code
|
97
|
-
* only symbols are checked here.
|
98
|
-
*/
|
99
|
-
if (!SYMBOL_P(instance)) {
|
100
|
-
lookup_class = rb_singleton_class(instance);
|
101
|
-
|
102
|
-
type = msgpack_packer_ext_registry_fetch(pkrg, lookup_class, ext_type_result);
|
92
|
+
if (pkrg->hash == Qnil) { // No extensions registered
|
93
|
+
return Qnil;
|
94
|
+
}
|
103
95
|
|
104
|
-
|
105
|
-
|
106
|
-
|
96
|
+
/*
|
97
|
+
* 1. check whether singleton_class or class of this instance is registered (or resolved in past) or not.
|
98
|
+
*
|
99
|
+
* Objects of type Integer (Fixnum, Bignum), Float, Symbol and frozen
|
100
|
+
* `rb_class_of` returns the singleton_class if the object has one, or the "real class" otherwise.
|
101
|
+
*/
|
102
|
+
VALUE lookup_class = rb_class_of(instance);
|
103
|
+
type = msgpack_packer_ext_registry_fetch(pkrg, lookup_class, ext_type_result, ext_flags_result);
|
104
|
+
if(type != Qnil) {
|
105
|
+
return type;
|
107
106
|
}
|
108
107
|
|
109
108
|
/*
|
110
|
-
* 2. check the class of instance is registered
|
109
|
+
* 2. If the object had a singleton_class check if the real class of instance is registered
|
110
|
+
* (or resolved in past) or not.
|
111
111
|
*/
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
112
|
+
VALUE real_class = rb_obj_class(instance);
|
113
|
+
if(lookup_class != real_class) {
|
114
|
+
type = msgpack_packer_ext_registry_fetch(pkrg, real_class, ext_type_result, ext_flags_result);
|
115
|
+
if(type != Qnil) {
|
116
|
+
return type;
|
117
|
+
}
|
116
118
|
}
|
117
119
|
|
118
120
|
/*
|
@@ -128,6 +130,7 @@ static inline VALUE msgpack_packer_ext_registry_lookup(msgpack_packer_ext_regist
|
|
128
130
|
VALUE superclass_type = rb_hash_lookup(pkrg->hash, superclass);
|
129
131
|
rb_hash_aset(pkrg->cache, lookup_class, superclass_type);
|
130
132
|
*ext_type_result = FIX2INT(rb_ary_entry(superclass_type, 0));
|
133
|
+
*ext_flags_result = FIX2INT(rb_ary_entry(superclass_type, 2));
|
131
134
|
return rb_ary_entry(superclass_type, 1);
|
132
135
|
}
|
133
136
|
|
data/ext/msgpack/rbinit.c
CHANGED
data/ext/msgpack/rmem.c
CHANGED
@@ -65,11 +65,10 @@ void* _msgpack_rmem_alloc2(msgpack_rmem_t* pm)
|
|
65
65
|
/* allocate new chunk */
|
66
66
|
c = pm->array_last++;
|
67
67
|
|
68
|
-
/* move to
|
69
|
-
|
70
|
-
pm->head = *c;
|
71
|
-
*c = tmp;
|
68
|
+
/* move head to array */
|
69
|
+
*c = pm->head;
|
72
70
|
|
71
|
+
pm->head.pages = NULL; /* make sure we don't point to another chunk's pages in case xmalloc triggers GC */
|
73
72
|
pm->head.mask = 0xffffffff & (~1); /* "& (~1)" means first chunk is already allocated */
|
74
73
|
pm->head.pages = xmalloc(MSGPACK_RMEM_PAGE_SIZE * 32);
|
75
74
|
|
data/ext/msgpack/sysdep.h
CHANGED
@@ -35,8 +35,11 @@
|
|
35
35
|
# define _msgpack_be16(x) ((uint16_t)_byteswap_ushort((unsigned short)x))
|
36
36
|
# else
|
37
37
|
# define _msgpack_be16(x) ( \
|
38
|
-
(
|
39
|
-
|
38
|
+
( \
|
39
|
+
((((uint16_t)x) << 8) ) | \
|
40
|
+
((((uint16_t)x) >> 8) ) \
|
41
|
+
) \
|
42
|
+
& 0x0000FFFF )
|
40
43
|
# endif
|
41
44
|
#else
|
42
45
|
# define _msgpack_be16(x) ntohs(x)
|
data/ext/msgpack/unpacker.c
CHANGED
@@ -19,43 +19,48 @@
|
|
19
19
|
#include "unpacker.h"
|
20
20
|
#include "rmem.h"
|
21
21
|
#include "extension_value_class.h"
|
22
|
+
#include <assert.h>
|
22
23
|
|
23
|
-
#if !defined(
|
24
|
-
|
25
|
-
#define UNPACKER_STACK_RMEM
|
24
|
+
#if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
|
25
|
+
#define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
|
26
26
|
#endif
|
27
27
|
|
28
28
|
static int RAW_TYPE_STRING = 256;
|
29
29
|
static int RAW_TYPE_BINARY = 257;
|
30
30
|
|
31
|
-
static ID s_call;
|
32
|
-
|
33
|
-
#ifdef UNPACKER_STACK_RMEM
|
34
31
|
static msgpack_rmem_t s_stack_rmem;
|
35
|
-
#endif
|
36
32
|
|
37
|
-
|
33
|
+
#if !defined(HAVE_RB_HASH_NEW_CAPA)
|
34
|
+
static inline VALUE rb_hash_new_capa(long capa)
|
38
35
|
{
|
39
|
-
|
40
|
-
|
36
|
+
return rb_hash_new();
|
37
|
+
}
|
41
38
|
#endif
|
42
39
|
|
43
|
-
|
40
|
+
void msgpack_unpacker_static_init(void)
|
41
|
+
{
|
42
|
+
assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
|
43
|
+
|
44
|
+
msgpack_rmem_init(&s_stack_rmem);
|
44
45
|
}
|
45
46
|
|
46
|
-
void msgpack_unpacker_static_destroy()
|
47
|
+
void msgpack_unpacker_static_destroy(void)
|
47
48
|
{
|
48
|
-
#ifdef UNPACKER_STACK_RMEM
|
49
49
|
msgpack_rmem_destroy(&s_stack_rmem);
|
50
|
-
#endif
|
51
50
|
}
|
52
51
|
|
53
52
|
#define HEAD_BYTE_REQUIRED 0xc1
|
54
53
|
|
54
|
+
static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
|
55
|
+
msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
|
56
|
+
stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
57
|
+
stack->data = msgpack_rmem_alloc(&s_stack_rmem);
|
58
|
+
/*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
|
59
|
+
return stack;
|
60
|
+
}
|
61
|
+
|
55
62
|
void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
56
63
|
{
|
57
|
-
memset(uk, 0, sizeof(msgpack_unpacker_t));
|
58
|
-
|
59
64
|
msgpack_buffer_init(UNPACKER_BUFFER_(uk));
|
60
65
|
|
61
66
|
uk->head_byte = HEAD_BYTE_REQUIRED;
|
@@ -63,42 +68,44 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
|
63
68
|
uk->last_object = Qnil;
|
64
69
|
uk->reading_raw = Qnil;
|
65
70
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
uk->stack = _msgpack_unpacker_new_stack();
|
72
|
+
}
|
73
|
+
|
74
|
+
static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
|
75
|
+
if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
|
76
|
+
rb_bug("Failed to free an rmem pointer, memory leak?");
|
77
|
+
}
|
78
|
+
xfree(stack);
|
74
79
|
}
|
75
80
|
|
76
81
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
|
77
82
|
{
|
78
|
-
|
79
|
-
msgpack_rmem_free(&s_stack_rmem, uk->stack);
|
80
|
-
#else
|
81
|
-
xfree(uk->stack);
|
82
|
-
#endif
|
83
|
-
|
83
|
+
_msgpack_unpacker_free_stack(uk->stack);
|
84
84
|
msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
|
85
85
|
}
|
86
86
|
|
87
|
+
void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
|
88
|
+
{
|
89
|
+
while (stack) {
|
90
|
+
msgpack_unpacker_stack_entry_t* s = stack->data;
|
91
|
+
msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
|
92
|
+
for(; s < send; s++) {
|
93
|
+
rb_gc_mark(s->object);
|
94
|
+
rb_gc_mark(s->key);
|
95
|
+
}
|
96
|
+
stack = stack->parent;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
87
100
|
void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
|
88
101
|
{
|
89
102
|
rb_gc_mark(uk->last_object);
|
90
103
|
rb_gc_mark(uk->reading_raw);
|
91
|
-
|
92
|
-
msgpack_unpacker_stack_t* s = uk->stack;
|
93
|
-
msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
|
94
|
-
for(; s < send; s++) {
|
95
|
-
rb_gc_mark(s->object);
|
96
|
-
rb_gc_mark(s->key);
|
97
|
-
}
|
98
|
-
|
104
|
+
msgpack_unpacker_mark_stack(uk->stack);
|
99
105
|
/* See MessagePack_Buffer_wrap */
|
100
106
|
/* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
|
101
107
|
rb_gc_mark(uk->buffer_ref);
|
108
|
+
rb_gc_mark(uk->self);
|
102
109
|
}
|
103
110
|
|
104
111
|
void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
|
@@ -107,9 +114,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
|
|
107
114
|
|
108
115
|
uk->head_byte = HEAD_BYTE_REQUIRED;
|
109
116
|
|
110
|
-
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->
|
111
|
-
uk->
|
112
|
-
|
117
|
+
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
|
118
|
+
uk->stack->depth = 0;
|
113
119
|
uk->last_object = Qnil;
|
114
120
|
uk->reading_raw = Qnil;
|
115
121
|
uk->reading_raw_remaining = 0;
|
@@ -151,16 +157,34 @@ static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
|
|
151
157
|
return PRIMITIVE_OBJECT_COMPLETE;
|
152
158
|
}
|
153
159
|
|
160
|
+
static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
|
161
|
+
{
|
162
|
+
uk->last_object = object;
|
163
|
+
reset_head_byte(uk);
|
164
|
+
return PRIMITIVE_OBJECT_COMPLETE;
|
165
|
+
}
|
166
|
+
|
154
167
|
static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
|
155
168
|
{
|
156
|
-
|
169
|
+
if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
|
170
|
+
if (RB_UNLIKELY(NIL_P(str))) { // empty extension is returned as Qnil
|
171
|
+
return object_complete_symbol(uk, ID2SYM(rb_intern3("", 0, rb_utf8_encoding())));
|
172
|
+
}
|
173
|
+
return object_complete_symbol(uk, rb_str_intern(str));
|
174
|
+
}
|
175
|
+
|
176
|
+
int ext_flags;
|
177
|
+
VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
|
178
|
+
|
157
179
|
if(proc != Qnil) {
|
158
|
-
VALUE obj
|
180
|
+
VALUE obj;
|
181
|
+
VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
|
182
|
+
obj = rb_proc_call_with_block(proc, 1, &arg, Qnil);
|
159
183
|
return object_complete(uk, obj);
|
160
184
|
}
|
161
185
|
|
162
186
|
if(uk->allow_unknown_ext) {
|
163
|
-
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
|
187
|
+
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
|
164
188
|
return object_complete(uk, obj);
|
165
189
|
}
|
166
190
|
|
@@ -168,37 +192,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
|
|
168
192
|
}
|
169
193
|
|
170
194
|
/* stack funcs */
|
171
|
-
static inline
|
195
|
+
static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
|
172
196
|
{
|
173
|
-
return &uk->stack[uk->
|
197
|
+
return &uk->stack->data[uk->stack->depth-1];
|
174
198
|
}
|
175
199
|
|
176
200
|
static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
|
177
201
|
{
|
178
202
|
reset_head_byte(uk);
|
179
203
|
|
180
|
-
if(uk->
|
204
|
+
if(uk->stack->capacity - uk->stack->depth <= 0) {
|
181
205
|
return PRIMITIVE_STACK_TOO_DEEP;
|
182
206
|
}
|
183
207
|
|
184
|
-
|
208
|
+
msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
|
185
209
|
next->count = count;
|
186
210
|
next->type = type;
|
187
211
|
next->object = object;
|
188
212
|
next->key = Qnil;
|
189
213
|
|
190
|
-
uk->
|
214
|
+
uk->stack->depth++;
|
191
215
|
return PRIMITIVE_CONTAINER_START;
|
192
216
|
}
|
193
217
|
|
194
218
|
static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
|
195
219
|
{
|
196
|
-
return --uk->
|
220
|
+
return --uk->stack->depth;
|
197
221
|
}
|
198
222
|
|
199
223
|
static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
|
200
224
|
{
|
201
|
-
return uk->
|
225
|
+
return uk->stack->depth == 0;
|
202
226
|
}
|
203
227
|
|
204
228
|
#ifdef USE_CASE_RANGE
|
@@ -226,8 +250,8 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
|
|
226
250
|
|
227
251
|
static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
|
228
252
|
{
|
229
|
-
if(uk->
|
230
|
-
|
253
|
+
if(uk->stack->depth > 0) {
|
254
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
231
255
|
if(top->type == STACK_TYPE_MAP_KEY) {
|
232
256
|
return true;
|
233
257
|
}
|
@@ -270,25 +294,50 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
270
294
|
{
|
271
295
|
/* assuming uk->reading_raw == Qnil */
|
272
296
|
|
297
|
+
int ext_flags;
|
298
|
+
VALUE proc;
|
299
|
+
|
300
|
+
if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
|
301
|
+
proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
|
302
|
+
if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
|
303
|
+
VALUE obj;
|
304
|
+
uk->last_object = Qnil;
|
305
|
+
reset_head_byte(uk);
|
306
|
+
uk->reading_raw_remaining = 0;
|
307
|
+
|
308
|
+
msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
|
309
|
+
child_stack->parent = uk->stack;
|
310
|
+
uk->stack = child_stack;
|
311
|
+
|
312
|
+
obj = rb_proc_call_with_block(proc, 1, &uk->self, Qnil);
|
313
|
+
|
314
|
+
uk->stack = child_stack->parent;
|
315
|
+
_msgpack_unpacker_free_stack(child_stack);
|
316
|
+
|
317
|
+
return object_complete(uk, obj);
|
318
|
+
}
|
319
|
+
}
|
320
|
+
|
273
321
|
/* try optimized read */
|
274
322
|
size_t length = uk->reading_raw_remaining;
|
275
323
|
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
|
276
|
-
/* don't use zerocopy for hash keys but get a frozen string directly
|
277
|
-
* because rb_hash_aset freezes keys and it causes copying */
|
278
|
-
bool will_freeze = uk->freeze || is_reading_map_key(uk);
|
279
|
-
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
280
324
|
int ret;
|
281
|
-
if(
|
282
|
-
|
325
|
+
if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
|
326
|
+
VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
|
327
|
+
ret = object_complete_symbol(uk, symbol);
|
283
328
|
} else {
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
329
|
+
bool will_freeze = uk->freeze;
|
330
|
+
if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
|
331
|
+
/* don't use zerocopy for hash keys but get a frozen string directly
|
332
|
+
* because rb_hash_aset freezes keys and it causes copying */
|
333
|
+
will_freeze = will_freeze || is_reading_map_key(uk);
|
334
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
335
|
+
ret = object_complete(uk, string);
|
336
|
+
} else {
|
337
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, false, false);
|
338
|
+
ret = object_complete_ext(uk, raw_type, string);
|
339
|
+
}
|
290
340
|
}
|
291
|
-
# endif
|
292
341
|
uk->reading_raw_remaining = 0;
|
293
342
|
return ret;
|
294
343
|
}
|
@@ -317,9 +366,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
317
366
|
|
318
367
|
SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
|
319
368
|
int count = b & 0x1f;
|
320
|
-
if(count == 0) {
|
321
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
322
|
-
}
|
323
369
|
/* read_raw_body_begin sets uk->reading_raw */
|
324
370
|
uk->reading_raw_remaining = count;
|
325
371
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -336,7 +382,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
336
382
|
if(count == 0) {
|
337
383
|
return object_complete(uk, rb_hash_new());
|
338
384
|
}
|
339
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
385
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
340
386
|
|
341
387
|
SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
|
342
388
|
switch(b) {
|
@@ -357,7 +403,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
357
403
|
uint8_t length = cb->u8;
|
358
404
|
int ext_type = (signed char) cb->buffer[1];
|
359
405
|
if(length == 0) {
|
360
|
-
return object_complete_ext(uk, ext_type,
|
406
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
361
407
|
}
|
362
408
|
uk->reading_raw_remaining = length;
|
363
409
|
return read_raw_body_begin(uk, ext_type);
|
@@ -369,7 +415,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
369
415
|
uint16_t length = _msgpack_be16(cb->u16);
|
370
416
|
int ext_type = (signed char) cb->buffer[2];
|
371
417
|
if(length == 0) {
|
372
|
-
return object_complete_ext(uk, ext_type,
|
418
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
373
419
|
}
|
374
420
|
uk->reading_raw_remaining = length;
|
375
421
|
return read_raw_body_begin(uk, ext_type);
|
@@ -381,7 +427,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
381
427
|
uint32_t length = _msgpack_be32(cb->u32);
|
382
428
|
int ext_type = (signed char) cb->buffer[4];
|
383
429
|
if(length == 0) {
|
384
|
-
return object_complete_ext(uk, ext_type,
|
430
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
385
431
|
}
|
386
432
|
uk->reading_raw_remaining = length;
|
387
433
|
return read_raw_body_begin(uk, ext_type);
|
@@ -419,7 +465,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
419
465
|
{
|
420
466
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
421
467
|
uint32_t u32 = _msgpack_be32(cb->u32);
|
422
|
-
return object_complete(uk, ULONG2NUM(
|
468
|
+
return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
|
423
469
|
}
|
424
470
|
|
425
471
|
case 0xcf: // unsigned int 64
|
@@ -447,7 +493,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
447
493
|
{
|
448
494
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
449
495
|
int32_t i32 = _msgpack_be32(cb->i32);
|
450
|
-
return object_complete(uk, LONG2NUM(
|
496
|
+
return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
|
451
497
|
}
|
452
498
|
|
453
499
|
case 0xd3: // signed int 64
|
@@ -502,9 +548,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
502
548
|
{
|
503
549
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
504
550
|
uint8_t count = cb->u8;
|
505
|
-
if(count == 0) {
|
506
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
507
|
-
}
|
508
551
|
/* read_raw_body_begin sets uk->reading_raw */
|
509
552
|
uk->reading_raw_remaining = count;
|
510
553
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -514,9 +557,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
514
557
|
{
|
515
558
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
516
559
|
uint16_t count = _msgpack_be16(cb->u16);
|
517
|
-
if(count == 0) {
|
518
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
519
|
-
}
|
520
560
|
/* read_raw_body_begin sets uk->reading_raw */
|
521
561
|
uk->reading_raw_remaining = count;
|
522
562
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -526,9 +566,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
526
566
|
{
|
527
567
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
528
568
|
uint32_t count = _msgpack_be32(cb->u32);
|
529
|
-
if(count == 0) {
|
530
|
-
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
531
|
-
}
|
532
569
|
/* read_raw_body_begin sets uk->reading_raw */
|
533
570
|
uk->reading_raw_remaining = count;
|
534
571
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -538,9 +575,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
538
575
|
{
|
539
576
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
540
577
|
uint8_t count = cb->u8;
|
541
|
-
if(count == 0) {
|
542
|
-
return object_complete(uk, rb_str_new_static("", 0));
|
543
|
-
}
|
544
578
|
/* read_raw_body_begin sets uk->reading_raw */
|
545
579
|
uk->reading_raw_remaining = count;
|
546
580
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -550,9 +584,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
550
584
|
{
|
551
585
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
552
586
|
uint16_t count = _msgpack_be16(cb->u16);
|
553
|
-
if(count == 0) {
|
554
|
-
return object_complete(uk, rb_str_new_static("", 0));
|
555
|
-
}
|
556
587
|
/* read_raw_body_begin sets uk->reading_raw */
|
557
588
|
uk->reading_raw_remaining = count;
|
558
589
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -562,9 +593,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
562
593
|
{
|
563
594
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
564
595
|
uint32_t count = _msgpack_be32(cb->u32);
|
565
|
-
if(count == 0) {
|
566
|
-
return object_complete(uk, rb_str_new_static("", 0));
|
567
|
-
}
|
568
596
|
/* read_raw_body_begin sets uk->reading_raw */
|
569
597
|
uk->reading_raw_remaining = count;
|
570
598
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -597,7 +625,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
597
625
|
if(count == 0) {
|
598
626
|
return object_complete(uk, rb_hash_new());
|
599
627
|
}
|
600
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
628
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
601
629
|
}
|
602
630
|
|
603
631
|
case 0xdf: // map 32
|
@@ -607,7 +635,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
607
635
|
if(count == 0) {
|
608
636
|
return object_complete(uk, rb_hash_new());
|
609
637
|
}
|
610
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
638
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
611
639
|
}
|
612
640
|
|
613
641
|
default:
|
@@ -694,7 +722,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
694
722
|
|
695
723
|
container_completed:
|
696
724
|
{
|
697
|
-
|
725
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
698
726
|
switch(top->type) {
|
699
727
|
case STACK_TYPE_ARRAY:
|
700
728
|
rb_ary_push(top->object, uk->last_object);
|
@@ -705,18 +733,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
705
733
|
break;
|
706
734
|
case STACK_TYPE_MAP_VALUE:
|
707
735
|
if(uk->symbolize_keys && rb_type(top->key) == T_STRING) {
|
708
|
-
/* here uses
|
709
|
-
#ifdef HAVE_RB_STR_INTERN
|
710
|
-
/* rb_str_intern is added since MRI 2.2.0 */
|
736
|
+
/* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
|
711
737
|
rb_hash_aset(top->object, rb_str_intern(top->key), uk->last_object);
|
712
|
-
#else
|
713
|
-
#ifndef HAVE_RB_INTERN_STR
|
714
|
-
/* MRI 1.8 doesn't have rb_intern_str or rb_intern2 */
|
715
|
-
rb_hash_aset(top->object, ID2SYM(rb_intern(RSTRING_PTR(top->key))), uk->last_object);
|
716
|
-
#else
|
717
|
-
rb_hash_aset(top->object, ID2SYM(rb_intern_str(top->key)), uk->last_object);
|
718
|
-
#endif
|
719
|
-
#endif
|
720
738
|
} else {
|
721
739
|
rb_hash_aset(top->object, top->key, uk->last_object);
|
722
740
|
}
|
@@ -754,7 +772,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
754
772
|
|
755
773
|
container_completed:
|
756
774
|
{
|
757
|
-
|
775
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
758
776
|
|
759
777
|
/* this section optimized out */
|
760
778
|
// TODO object_complete still creates objects which should be optimized out
|