msgpack 1.4.2 → 1.7.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|