msgpack 1.3.3 → 1.6.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/.github/workflows/ci.yaml +57 -0
- data/.rubocop.yml +2 -2
- data/ChangeLog +74 -0
- data/Gemfile +1 -1
- data/README.md +266 -0
- data/Rakefile +1 -9
- data/bench/bench.rb +78 -0
- data/bin/console +8 -0
- data/doclib/msgpack/factory.rb +47 -3
- data/doclib/msgpack/packer.rb +5 -4
- data/doclib/msgpack/unpacker.rb +2 -2
- data/ext/java/org/msgpack/jruby/Buffer.java +23 -16
- data/ext/java/org/msgpack/jruby/Decoder.java +46 -23
- data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +37 -49
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
- data/ext/java/org/msgpack/jruby/Factory.java +47 -7
- data/ext/java/org/msgpack/jruby/Packer.java +29 -17
- data/ext/java/org/msgpack/jruby/Unpacker.java +72 -37
- data/ext/msgpack/buffer.c +42 -68
- data/ext/msgpack/buffer.h +59 -14
- data/ext/msgpack/buffer_class.c +90 -52
- data/ext/msgpack/compat.h +1 -111
- data/ext/msgpack/extconf.rb +45 -19
- data/ext/msgpack/factory_class.c +133 -43
- data/ext/msgpack/packer.c +60 -36
- data/ext/msgpack/packer.h +27 -25
- data/ext/msgpack/packer_class.c +84 -77
- data/ext/msgpack/packer_class.h +11 -0
- data/ext/msgpack/packer_ext_registry.c +24 -32
- data/ext/msgpack/packer_ext_registry.h +40 -33
- data/ext/msgpack/sysdep.h +5 -2
- data/ext/msgpack/unpacker.c +132 -115
- data/ext/msgpack/unpacker.h +23 -10
- data/ext/msgpack/unpacker_class.c +83 -78
- data/ext/msgpack/unpacker_class.h +11 -0
- data/ext/msgpack/unpacker_ext_registry.c +42 -18
- data/ext/msgpack/unpacker_ext_registry.h +23 -16
- data/lib/msgpack/bigint.rb +69 -0
- data/lib/msgpack/factory.rb +103 -0
- data/lib/msgpack/symbol.rb +21 -4
- data/lib/msgpack/time.rb +1 -1
- data/lib/msgpack/version.rb +4 -8
- data/lib/msgpack.rb +6 -12
- data/msgpack.gemspec +4 -6
- data/spec/bigint_spec.rb +26 -0
- data/spec/cruby/buffer_spec.rb +17 -0
- data/spec/factory_spec.rb +351 -12
- data/spec/msgpack_spec.rb +1 -1
- data/spec/packer_spec.rb +18 -0
- data/spec/spec_helper.rb +37 -3
- data/spec/timestamp_spec.rb +38 -0
- data/spec/unpacker_spec.rb +157 -4
- metadata +31 -61
- data/.travis.yml +0 -43
- data/README.rdoc +0 -225
- 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/ext/msgpack/unpacker.c
CHANGED
@@ -20,7 +20,7 @@
|
|
20
20
|
#include "rmem.h"
|
21
21
|
#include "extension_value_class.h"
|
22
22
|
|
23
|
-
#if !defined(
|
23
|
+
#if !defined(DISABLE_UNPACKER_STACK_RMEM) && \
|
24
24
|
MSGPACK_UNPACKER_STACK_CAPACITY * MSGPACK_UNPACKER_STACK_SIZE <= MSGPACK_RMEM_PAGE_SIZE
|
25
25
|
#define UNPACKER_STACK_RMEM
|
26
26
|
#endif
|
@@ -34,7 +34,14 @@ static ID s_call;
|
|
34
34
|
static msgpack_rmem_t s_stack_rmem;
|
35
35
|
#endif
|
36
36
|
|
37
|
-
|
37
|
+
#if !defined(HAVE_RB_HASH_NEW_CAPA)
|
38
|
+
static inline VALUE rb_hash_new_capa(long capa)
|
39
|
+
{
|
40
|
+
return rb_hash_new();
|
41
|
+
}
|
42
|
+
#endif
|
43
|
+
|
44
|
+
void msgpack_unpacker_static_init(void)
|
38
45
|
{
|
39
46
|
#ifdef UNPACKER_STACK_RMEM
|
40
47
|
msgpack_rmem_init(&s_stack_rmem);
|
@@ -43,7 +50,7 @@ void msgpack_unpacker_static_init()
|
|
43
50
|
s_call = rb_intern("call");
|
44
51
|
}
|
45
52
|
|
46
|
-
void msgpack_unpacker_static_destroy()
|
53
|
+
void msgpack_unpacker_static_destroy(void)
|
47
54
|
{
|
48
55
|
#ifdef UNPACKER_STACK_RMEM
|
49
56
|
msgpack_rmem_destroy(&s_stack_rmem);
|
@@ -52,10 +59,21 @@ void msgpack_unpacker_static_destroy()
|
|
52
59
|
|
53
60
|
#define HEAD_BYTE_REQUIRED 0xc1
|
54
61
|
|
62
|
+
static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
|
63
|
+
msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
|
64
|
+
stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
|
65
|
+
#ifdef UNPACKER_STACK_RMEM
|
66
|
+
stack->data = msgpack_rmem_alloc(&s_stack_rmem);
|
67
|
+
/*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
|
68
|
+
#else
|
69
|
+
/*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_entry_t));*/
|
70
|
+
stack->data = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_entry_t));
|
71
|
+
#endif
|
72
|
+
return stack;
|
73
|
+
}
|
74
|
+
|
55
75
|
void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
56
76
|
{
|
57
|
-
memset(uk, 0, sizeof(msgpack_unpacker_t));
|
58
|
-
|
59
77
|
msgpack_buffer_init(UNPACKER_BUFFER_(uk));
|
60
78
|
|
61
79
|
uk->head_byte = HEAD_BYTE_REQUIRED;
|
@@ -63,39 +81,42 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
|
|
63
81
|
uk->last_object = Qnil;
|
64
82
|
uk->reading_raw = Qnil;
|
65
83
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
#
|
73
|
-
|
84
|
+
uk->stack = _msgpack_unpacker_new_stack();
|
85
|
+
}
|
86
|
+
|
87
|
+
static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
|
88
|
+
#ifdef UNPACKER_STACK_RMEM
|
89
|
+
msgpack_rmem_free(&s_stack_rmem, stack->data);
|
90
|
+
#else
|
91
|
+
xfree(stack->data);
|
92
|
+
#endif
|
93
|
+
xfree(stack);
|
74
94
|
}
|
75
95
|
|
76
96
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
|
77
97
|
{
|
78
|
-
|
79
|
-
msgpack_rmem_free(&s_stack_rmem, uk->stack);
|
80
|
-
#else
|
81
|
-
xfree(uk->stack);
|
82
|
-
#endif
|
83
|
-
|
98
|
+
_msgpack_unpacker_free_stack(uk->stack);
|
84
99
|
msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
|
85
100
|
}
|
86
101
|
|
102
|
+
void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
|
103
|
+
{
|
104
|
+
while (stack) {
|
105
|
+
msgpack_unpacker_stack_entry_t* s = stack->data;
|
106
|
+
msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
|
107
|
+
for(; s < send; s++) {
|
108
|
+
rb_gc_mark(s->object);
|
109
|
+
rb_gc_mark(s->key);
|
110
|
+
}
|
111
|
+
stack = stack->parent;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
87
115
|
void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
|
88
116
|
{
|
89
117
|
rb_gc_mark(uk->last_object);
|
90
118
|
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
|
-
|
119
|
+
msgpack_unpacker_mark_stack(uk->stack);
|
99
120
|
/* See MessagePack_Buffer_wrap */
|
100
121
|
/* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
|
101
122
|
rb_gc_mark(uk->buffer_ref);
|
@@ -107,9 +128,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
|
|
107
128
|
|
108
129
|
uk->head_byte = HEAD_BYTE_REQUIRED;
|
109
130
|
|
110
|
-
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->
|
111
|
-
uk->
|
112
|
-
|
131
|
+
/*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
|
132
|
+
uk->stack->depth = 0;
|
113
133
|
uk->last_object = Qnil;
|
114
134
|
uk->reading_raw = Qnil;
|
115
135
|
uk->reading_raw_remaining = 0;
|
@@ -142,41 +162,42 @@ static inline void reset_head_byte(msgpack_unpacker_t* uk)
|
|
142
162
|
|
143
163
|
static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
|
144
164
|
{
|
165
|
+
if(uk->freeze) {
|
166
|
+
rb_obj_freeze(object);
|
167
|
+
}
|
168
|
+
|
145
169
|
uk->last_object = object;
|
146
170
|
reset_head_byte(uk);
|
147
171
|
return PRIMITIVE_OBJECT_COMPLETE;
|
148
172
|
}
|
149
173
|
|
150
|
-
static inline int
|
151
|
-
{
|
152
|
-
#ifdef COMPAT_HAVE_ENCODING
|
153
|
-
ENCODING_SET(str, msgpack_rb_encindex_utf8);
|
154
|
-
#endif
|
155
|
-
return object_complete(uk, str);
|
156
|
-
}
|
157
|
-
|
158
|
-
static inline int object_complete_binary(msgpack_unpacker_t* uk, VALUE str)
|
174
|
+
static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
|
159
175
|
{
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
return object_complete(uk, str);
|
176
|
+
uk->last_object = object;
|
177
|
+
reset_head_byte(uk);
|
178
|
+
return PRIMITIVE_OBJECT_COMPLETE;
|
164
179
|
}
|
165
180
|
|
166
181
|
static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
|
167
182
|
{
|
168
|
-
|
169
|
-
|
170
|
-
|
183
|
+
if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
|
184
|
+
if (RB_UNLIKELY(NIL_P(str))) { // empty extension is returned as Qnil
|
185
|
+
return object_complete_symbol(uk, ID2SYM(rb_intern3("", 0, rb_utf8_encoding())));
|
186
|
+
}
|
187
|
+
return object_complete_symbol(uk, rb_str_intern(str));
|
188
|
+
}
|
189
|
+
|
190
|
+
int ext_flags;
|
191
|
+
VALUE proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, ext_type, &ext_flags);
|
171
192
|
|
172
|
-
VALUE proc = msgpack_unpacker_ext_registry_lookup(&uk->ext_registry, ext_type);
|
173
193
|
if(proc != Qnil) {
|
174
|
-
VALUE obj
|
194
|
+
VALUE obj;
|
195
|
+
obj = rb_funcall(proc, s_call, 1, str == Qnil ? rb_str_buf_new(0) : str);
|
175
196
|
return object_complete(uk, obj);
|
176
197
|
}
|
177
198
|
|
178
199
|
if(uk->allow_unknown_ext) {
|
179
|
-
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str);
|
200
|
+
VALUE obj = MessagePack_ExtensionValue_new(ext_type, str == Qnil ? rb_str_buf_new(0) : str);
|
180
201
|
return object_complete(uk, obj);
|
181
202
|
}
|
182
203
|
|
@@ -184,37 +205,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
|
|
184
205
|
}
|
185
206
|
|
186
207
|
/* stack funcs */
|
187
|
-
static inline
|
208
|
+
static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
|
188
209
|
{
|
189
|
-
return &uk->stack[uk->
|
210
|
+
return &uk->stack->data[uk->stack->depth-1];
|
190
211
|
}
|
191
212
|
|
192
213
|
static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
|
193
214
|
{
|
194
215
|
reset_head_byte(uk);
|
195
216
|
|
196
|
-
if(uk->
|
217
|
+
if(uk->stack->capacity - uk->stack->depth <= 0) {
|
197
218
|
return PRIMITIVE_STACK_TOO_DEEP;
|
198
219
|
}
|
199
220
|
|
200
|
-
|
221
|
+
msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
|
201
222
|
next->count = count;
|
202
223
|
next->type = type;
|
203
224
|
next->object = object;
|
204
225
|
next->key = Qnil;
|
205
226
|
|
206
|
-
uk->
|
227
|
+
uk->stack->depth++;
|
207
228
|
return PRIMITIVE_CONTAINER_START;
|
208
229
|
}
|
209
230
|
|
210
231
|
static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
|
211
232
|
{
|
212
|
-
return --uk->
|
233
|
+
return --uk->stack->depth;
|
213
234
|
}
|
214
235
|
|
215
236
|
static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
|
216
237
|
{
|
217
|
-
return uk->
|
238
|
+
return uk->stack->depth == 0;
|
218
239
|
}
|
219
240
|
|
220
241
|
#ifdef USE_CASE_RANGE
|
@@ -242,8 +263,8 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
|
|
242
263
|
|
243
264
|
static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
|
244
265
|
{
|
245
|
-
if(uk->
|
246
|
-
|
266
|
+
if(uk->stack->depth > 0) {
|
267
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
247
268
|
if(top->type == STACK_TYPE_MAP_KEY) {
|
248
269
|
return true;
|
249
270
|
}
|
@@ -271,9 +292,10 @@ static int read_raw_body_cont(msgpack_unpacker_t* uk)
|
|
271
292
|
|
272
293
|
int ret;
|
273
294
|
if(uk->reading_raw_type == RAW_TYPE_STRING) {
|
274
|
-
|
275
|
-
|
276
|
-
|
295
|
+
ENCODING_SET(uk->reading_raw, msgpack_rb_encindex_utf8);
|
296
|
+
ret = object_complete(uk, uk->reading_raw);
|
297
|
+
} else if (uk->reading_raw_type == RAW_TYPE_BINARY) {
|
298
|
+
ret = object_complete(uk, uk->reading_raw);
|
277
299
|
} else {
|
278
300
|
ret = object_complete_ext(uk, uk->reading_raw_type, uk->reading_raw);
|
279
301
|
}
|
@@ -285,23 +307,49 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
285
307
|
{
|
286
308
|
/* assuming uk->reading_raw == Qnil */
|
287
309
|
|
310
|
+
int ext_flags;
|
311
|
+
VALUE proc;
|
312
|
+
|
313
|
+
if(!(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY)) {
|
314
|
+
proc = msgpack_unpacker_ext_registry_lookup(uk->ext_registry, raw_type, &ext_flags);
|
315
|
+
if(proc != Qnil && ext_flags & MSGPACK_EXT_RECURSIVE) {
|
316
|
+
VALUE obj;
|
317
|
+
uk->last_object = Qnil;
|
318
|
+
reset_head_byte(uk);
|
319
|
+
uk->reading_raw_remaining = 0;
|
320
|
+
|
321
|
+
msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
|
322
|
+
child_stack->parent = uk->stack;
|
323
|
+
uk->stack = child_stack;
|
324
|
+
|
325
|
+
obj = rb_funcall(proc, s_call, 1, uk->self);
|
326
|
+
|
327
|
+
uk->stack = child_stack->parent;
|
328
|
+
_msgpack_unpacker_free_stack(child_stack);
|
329
|
+
|
330
|
+
return object_complete(uk, obj);
|
331
|
+
}
|
332
|
+
}
|
333
|
+
|
288
334
|
/* try optimized read */
|
289
335
|
size_t length = uk->reading_raw_remaining;
|
290
336
|
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
|
291
|
-
/* don't use zerocopy for hash keys but get a frozen string directly
|
292
|
-
* because rb_hash_aset freezes keys and it causes copying */
|
293
|
-
bool will_freeze = is_reading_map_key(uk);
|
294
|
-
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze);
|
295
337
|
int ret;
|
296
|
-
if(
|
297
|
-
|
298
|
-
|
299
|
-
ret = object_complete_binary(uk, string);
|
338
|
+
if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
|
339
|
+
VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
|
340
|
+
ret = object_complete_symbol(uk, symbol);
|
300
341
|
} else {
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
342
|
+
bool will_freeze = uk->freeze;
|
343
|
+
if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
|
344
|
+
/* don't use zerocopy for hash keys but get a frozen string directly
|
345
|
+
* because rb_hash_aset freezes keys and it causes copying */
|
346
|
+
will_freeze = will_freeze || is_reading_map_key(uk);
|
347
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
348
|
+
ret = object_complete(uk, string);
|
349
|
+
} else {
|
350
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, false, false);
|
351
|
+
ret = object_complete_ext(uk, raw_type, string);
|
352
|
+
}
|
305
353
|
}
|
306
354
|
uk->reading_raw_remaining = 0;
|
307
355
|
return ret;
|
@@ -331,9 +379,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
331
379
|
|
332
380
|
SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
|
333
381
|
int count = b & 0x1f;
|
334
|
-
if(count == 0) {
|
335
|
-
return object_complete_string(uk, rb_str_buf_new(0));
|
336
|
-
}
|
337
382
|
/* read_raw_body_begin sets uk->reading_raw */
|
338
383
|
uk->reading_raw_remaining = count;
|
339
384
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -350,7 +395,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
350
395
|
if(count == 0) {
|
351
396
|
return object_complete(uk, rb_hash_new());
|
352
397
|
}
|
353
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
398
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
354
399
|
|
355
400
|
SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
|
356
401
|
switch(b) {
|
@@ -371,7 +416,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
371
416
|
uint8_t length = cb->u8;
|
372
417
|
int ext_type = (signed char) cb->buffer[1];
|
373
418
|
if(length == 0) {
|
374
|
-
return object_complete_ext(uk, ext_type,
|
419
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
375
420
|
}
|
376
421
|
uk->reading_raw_remaining = length;
|
377
422
|
return read_raw_body_begin(uk, ext_type);
|
@@ -383,7 +428,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
383
428
|
uint16_t length = _msgpack_be16(cb->u16);
|
384
429
|
int ext_type = (signed char) cb->buffer[2];
|
385
430
|
if(length == 0) {
|
386
|
-
return object_complete_ext(uk, ext_type,
|
431
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
387
432
|
}
|
388
433
|
uk->reading_raw_remaining = length;
|
389
434
|
return read_raw_body_begin(uk, ext_type);
|
@@ -395,7 +440,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
395
440
|
uint32_t length = _msgpack_be32(cb->u32);
|
396
441
|
int ext_type = (signed char) cb->buffer[4];
|
397
442
|
if(length == 0) {
|
398
|
-
return object_complete_ext(uk, ext_type,
|
443
|
+
return object_complete_ext(uk, ext_type, Qnil);
|
399
444
|
}
|
400
445
|
uk->reading_raw_remaining = length;
|
401
446
|
return read_raw_body_begin(uk, ext_type);
|
@@ -433,7 +478,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
433
478
|
{
|
434
479
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
435
480
|
uint32_t u32 = _msgpack_be32(cb->u32);
|
436
|
-
return object_complete(uk, ULONG2NUM(
|
481
|
+
return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
|
437
482
|
}
|
438
483
|
|
439
484
|
case 0xcf: // unsigned int 64
|
@@ -461,7 +506,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
461
506
|
{
|
462
507
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
463
508
|
int32_t i32 = _msgpack_be32(cb->i32);
|
464
|
-
return object_complete(uk, LONG2NUM(
|
509
|
+
return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
|
465
510
|
}
|
466
511
|
|
467
512
|
case 0xd3: // signed int 64
|
@@ -516,9 +561,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
516
561
|
{
|
517
562
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
518
563
|
uint8_t count = cb->u8;
|
519
|
-
if(count == 0) {
|
520
|
-
return object_complete_string(uk, rb_str_buf_new(0));
|
521
|
-
}
|
522
564
|
/* read_raw_body_begin sets uk->reading_raw */
|
523
565
|
uk->reading_raw_remaining = count;
|
524
566
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -528,9 +570,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
528
570
|
{
|
529
571
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
530
572
|
uint16_t count = _msgpack_be16(cb->u16);
|
531
|
-
if(count == 0) {
|
532
|
-
return object_complete_string(uk, rb_str_buf_new(0));
|
533
|
-
}
|
534
573
|
/* read_raw_body_begin sets uk->reading_raw */
|
535
574
|
uk->reading_raw_remaining = count;
|
536
575
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -540,9 +579,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
540
579
|
{
|
541
580
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
542
581
|
uint32_t count = _msgpack_be32(cb->u32);
|
543
|
-
if(count == 0) {
|
544
|
-
return object_complete_string(uk, rb_str_buf_new(0));
|
545
|
-
}
|
546
582
|
/* read_raw_body_begin sets uk->reading_raw */
|
547
583
|
uk->reading_raw_remaining = count;
|
548
584
|
return read_raw_body_begin(uk, RAW_TYPE_STRING);
|
@@ -552,9 +588,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
552
588
|
{
|
553
589
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
554
590
|
uint8_t count = cb->u8;
|
555
|
-
if(count == 0) {
|
556
|
-
return object_complete_binary(uk, rb_str_buf_new(0));
|
557
|
-
}
|
558
591
|
/* read_raw_body_begin sets uk->reading_raw */
|
559
592
|
uk->reading_raw_remaining = count;
|
560
593
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -564,9 +597,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
564
597
|
{
|
565
598
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
566
599
|
uint16_t count = _msgpack_be16(cb->u16);
|
567
|
-
if(count == 0) {
|
568
|
-
return object_complete_binary(uk, rb_str_buf_new(0));
|
569
|
-
}
|
570
600
|
/* read_raw_body_begin sets uk->reading_raw */
|
571
601
|
uk->reading_raw_remaining = count;
|
572
602
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -576,9 +606,6 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
576
606
|
{
|
577
607
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
578
608
|
uint32_t count = _msgpack_be32(cb->u32);
|
579
|
-
if(count == 0) {
|
580
|
-
return object_complete_binary(uk, rb_str_buf_new(0));
|
581
|
-
}
|
582
609
|
/* read_raw_body_begin sets uk->reading_raw */
|
583
610
|
uk->reading_raw_remaining = count;
|
584
611
|
return read_raw_body_begin(uk, RAW_TYPE_BINARY);
|
@@ -611,7 +638,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
611
638
|
if(count == 0) {
|
612
639
|
return object_complete(uk, rb_hash_new());
|
613
640
|
}
|
614
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
641
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
615
642
|
}
|
616
643
|
|
617
644
|
case 0xdf: // map 32
|
@@ -621,7 +648,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
621
648
|
if(count == 0) {
|
622
649
|
return object_complete(uk, rb_hash_new());
|
623
650
|
}
|
624
|
-
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2,
|
651
|
+
return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
|
625
652
|
}
|
626
653
|
|
627
654
|
default:
|
@@ -708,7 +735,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
708
735
|
|
709
736
|
container_completed:
|
710
737
|
{
|
711
|
-
|
738
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
712
739
|
switch(top->type) {
|
713
740
|
case STACK_TYPE_ARRAY:
|
714
741
|
rb_ary_push(top->object, uk->last_object);
|
@@ -719,18 +746,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
719
746
|
break;
|
720
747
|
case STACK_TYPE_MAP_VALUE:
|
721
748
|
if(uk->symbolize_keys && rb_type(top->key) == T_STRING) {
|
722
|
-
/* here uses
|
723
|
-
#ifdef HAVE_RB_STR_INTERN
|
724
|
-
/* rb_str_intern is added since MRI 2.2.0 */
|
749
|
+
/* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
|
725
750
|
rb_hash_aset(top->object, rb_str_intern(top->key), uk->last_object);
|
726
|
-
#else
|
727
|
-
#ifndef HAVE_RB_INTERN_STR
|
728
|
-
/* MRI 1.8 doesn't have rb_intern_str or rb_intern2 */
|
729
|
-
rb_hash_aset(top->object, ID2SYM(rb_intern(RSTRING_PTR(top->key))), uk->last_object);
|
730
|
-
#else
|
731
|
-
rb_hash_aset(top->object, ID2SYM(rb_intern_str(top->key)), uk->last_object);
|
732
|
-
#endif
|
733
|
-
#endif
|
734
751
|
} else {
|
735
752
|
rb_hash_aset(top->object, top->key, uk->last_object);
|
736
753
|
}
|
@@ -768,7 +785,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
768
785
|
|
769
786
|
container_completed:
|
770
787
|
{
|
771
|
-
|
788
|
+
msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
|
772
789
|
|
773
790
|
/* this section optimized out */
|
774
791
|
// TODO object_complete still creates objects which should be optimized out
|
data/ext/msgpack/unpacker.h
CHANGED
@@ -27,6 +27,7 @@
|
|
27
27
|
|
28
28
|
struct msgpack_unpacker_t;
|
29
29
|
typedef struct msgpack_unpacker_t msgpack_unpacker_t;
|
30
|
+
typedef struct msgpack_unpacker_stack_t msgpack_unpacker_stack_t;
|
30
31
|
|
31
32
|
enum stack_type_t {
|
32
33
|
STACK_TYPE_ARRAY,
|
@@ -39,19 +40,23 @@ typedef struct {
|
|
39
40
|
enum stack_type_t type;
|
40
41
|
VALUE object;
|
41
42
|
VALUE key;
|
42
|
-
}
|
43
|
+
} msgpack_unpacker_stack_entry_t;
|
44
|
+
|
45
|
+
struct msgpack_unpacker_stack_t {
|
46
|
+
size_t depth;
|
47
|
+
size_t capacity;
|
48
|
+
msgpack_unpacker_stack_entry_t *data;
|
49
|
+
msgpack_unpacker_stack_t *parent;
|
50
|
+
};
|
43
51
|
|
44
52
|
#define MSGPACK_UNPACKER_STACK_SIZE (8+4+8+8) /* assumes size_t <= 64bit, enum <= 32bit, VALUE <= 64bit */
|
45
53
|
|
46
54
|
struct msgpack_unpacker_t {
|
47
55
|
msgpack_buffer_t buffer;
|
48
|
-
|
56
|
+
msgpack_unpacker_stack_t *stack;
|
49
57
|
unsigned int head_byte;
|
50
58
|
|
51
|
-
|
52
|
-
size_t stack_depth;
|
53
|
-
size_t stack_capacity;
|
54
|
-
|
59
|
+
VALUE self;
|
55
60
|
VALUE last_object;
|
56
61
|
|
57
62
|
VALUE reading_raw;
|
@@ -60,11 +65,14 @@ struct msgpack_unpacker_t {
|
|
60
65
|
|
61
66
|
VALUE buffer_ref;
|
62
67
|
|
63
|
-
msgpack_unpacker_ext_registry_t ext_registry;
|
68
|
+
msgpack_unpacker_ext_registry_t *ext_registry;
|
64
69
|
|
65
70
|
/* options */
|
66
71
|
bool symbolize_keys;
|
72
|
+
bool freeze;
|
67
73
|
bool allow_unknown_ext;
|
74
|
+
bool optimized_symbol_ext_type;
|
75
|
+
int symbol_ext_type;
|
68
76
|
};
|
69
77
|
|
70
78
|
#define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
|
@@ -79,11 +87,11 @@ enum msgpack_unpacker_object_type {
|
|
79
87
|
TYPE_MAP,
|
80
88
|
};
|
81
89
|
|
82
|
-
void msgpack_unpacker_static_init();
|
90
|
+
void msgpack_unpacker_static_init(void);
|
83
91
|
|
84
|
-
void msgpack_unpacker_static_destroy();
|
92
|
+
void msgpack_unpacker_static_destroy(void);
|
85
93
|
|
86
|
-
void _msgpack_unpacker_init(msgpack_unpacker_t*
|
94
|
+
void _msgpack_unpacker_init(msgpack_unpacker_t*);
|
87
95
|
|
88
96
|
void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk);
|
89
97
|
|
@@ -96,6 +104,11 @@ static inline void msgpack_unpacker_set_symbolized_keys(msgpack_unpacker_t* uk,
|
|
96
104
|
uk->symbolize_keys = enable;
|
97
105
|
}
|
98
106
|
|
107
|
+
static inline void msgpack_unpacker_set_freeze(msgpack_unpacker_t* uk, bool enable)
|
108
|
+
{
|
109
|
+
uk->freeze = enable;
|
110
|
+
}
|
111
|
+
|
99
112
|
static inline void msgpack_unpacker_set_allow_unknown_ext(msgpack_unpacker_t* uk, bool enable)
|
100
113
|
{
|
101
114
|
uk->allow_unknown_ext = enable;
|