msgpack 1.2.9 → 1.4.4
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 +56 -0
- data/.gitignore +3 -1
- data/.rubocop.yml +4 -1
- data/ChangeLog +46 -0
- data/Gemfile +3 -0
- data/README.md +242 -0
- data/Rakefile +1 -9
- data/doclib/msgpack/factory.rb +1 -0
- data/doclib/msgpack/time.rb +22 -0
- data/doclib/msgpack/timestamp.rb +44 -0
- data/ext/java/org/msgpack/jruby/Buffer.java +17 -16
- data/ext/java/org/msgpack/jruby/Decoder.java +29 -10
- data/ext/java/org/msgpack/jruby/Encoder.java +22 -12
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +9 -9
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
- data/ext/java/org/msgpack/jruby/Factory.java +7 -2
- data/ext/java/org/msgpack/jruby/Packer.java +11 -9
- data/ext/java/org/msgpack/jruby/Unpacker.java +40 -27
- data/ext/msgpack/buffer.c +4 -16
- data/ext/msgpack/buffer.h +60 -5
- data/ext/msgpack/compat.h +1 -12
- data/ext/msgpack/extconf.rb +39 -7
- data/ext/msgpack/factory_class.c +10 -5
- data/ext/msgpack/packer.c +18 -5
- data/ext/msgpack/packer.h +0 -16
- data/ext/msgpack/packer_class.c +0 -9
- data/ext/msgpack/packer_ext_registry.c +0 -22
- data/ext/msgpack/unpacker.c +41 -49
- data/ext/msgpack/unpacker.h +8 -0
- data/ext/msgpack/unpacker_class.c +23 -13
- data/lib/msgpack/symbol.rb +14 -4
- data/lib/msgpack/time.rb +29 -0
- data/lib/msgpack/timestamp.rb +76 -0
- data/lib/msgpack/version.rb +4 -7
- data/lib/msgpack.rb +5 -8
- data/msgpack.gemspec +3 -7
- data/spec/factory_spec.rb +17 -0
- data/spec/msgpack_spec.rb +1 -1
- data/spec/packer_spec.rb +18 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/timestamp_spec.rb +161 -0
- data/spec/unpacker_spec.rb +113 -1
- metadata +19 -51
- data/.travis.yml +0 -41
- data/README.rdoc +0 -209
data/ext/msgpack/buffer.c
CHANGED
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
static ID s_replace;
|
|
24
24
|
#endif
|
|
25
25
|
|
|
26
|
-
#ifdef COMPAT_HAVE_ENCODING /* see compat.h*/
|
|
27
26
|
int msgpack_rb_encindex_utf8;
|
|
28
27
|
int msgpack_rb_encindex_usascii;
|
|
29
28
|
int msgpack_rb_encindex_ascii8bit;
|
|
30
|
-
|
|
29
|
+
|
|
30
|
+
ID s_uminus;
|
|
31
31
|
|
|
32
32
|
#ifndef DISABLE_RMEM
|
|
33
33
|
static msgpack_rmem_t s_rmem;
|
|
@@ -35,11 +35,11 @@ static msgpack_rmem_t s_rmem;
|
|
|
35
35
|
|
|
36
36
|
void msgpack_buffer_static_init()
|
|
37
37
|
{
|
|
38
|
-
|
|
38
|
+
s_uminus = rb_intern("-@");
|
|
39
|
+
|
|
39
40
|
msgpack_rb_encindex_utf8 = rb_utf8_encindex();
|
|
40
41
|
msgpack_rb_encindex_usascii = rb_usascii_encindex();
|
|
41
42
|
msgpack_rb_encindex_ascii8bit = rb_ascii8bit_encindex();
|
|
42
|
-
#endif
|
|
43
43
|
|
|
44
44
|
#ifndef DISABLE_RMEM
|
|
45
45
|
msgpack_rmem_init(&s_rmem);
|
|
@@ -164,12 +164,7 @@ size_t msgpack_buffer_read_to_string_nonblock(msgpack_buffer_t* b, VALUE string,
|
|
|
164
164
|
b->head->mapped_string != NO_MAPPED_STRING &&
|
|
165
165
|
length >= b->read_reference_threshold) {
|
|
166
166
|
VALUE s = _msgpack_buffer_refer_head_mapped_string(b, length);
|
|
167
|
-
#ifndef HAVE_RB_STR_REPLACE
|
|
168
|
-
/* TODO MRI 1.8 */
|
|
169
|
-
rb_funcall(string, s_replace, 1, s);
|
|
170
|
-
#else
|
|
171
167
|
rb_str_replace(string, s);
|
|
172
|
-
#endif
|
|
173
168
|
/* here doesn't have to call ENCODING_SET because
|
|
174
169
|
* encoding of s is always ASCII-8BIT */
|
|
175
170
|
_msgpack_buffer_consumed(b, length);
|
|
@@ -308,9 +303,7 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
|
|
|
308
303
|
static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE string)
|
|
309
304
|
{
|
|
310
305
|
VALUE mapped_string = rb_str_dup(string);
|
|
311
|
-
#ifdef COMPAT_HAVE_ENCODING
|
|
312
306
|
ENCODING_SET(mapped_string, msgpack_rb_encindex_ascii8bit);
|
|
313
|
-
#endif
|
|
314
307
|
|
|
315
308
|
_msgpack_buffer_add_new_chunk(b);
|
|
316
309
|
|
|
@@ -337,7 +330,6 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
|
|
|
337
330
|
|
|
338
331
|
if(b->io != Qnil) {
|
|
339
332
|
msgpack_buffer_flush(b);
|
|
340
|
-
#ifdef COMPAT_HAVE_ENCODING
|
|
341
333
|
if (ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit) {
|
|
342
334
|
rb_funcall(b->io, b->io_write_all_method, 1, string);
|
|
343
335
|
} else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
|
|
@@ -347,10 +339,6 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
|
|
|
347
339
|
} else {
|
|
348
340
|
msgpack_buffer_append(b, RSTRING_PTR(string), length);
|
|
349
341
|
}
|
|
350
|
-
#else
|
|
351
|
-
rb_funcall(b->io, b->io_write_all_method, 1, string);
|
|
352
|
-
#endif
|
|
353
|
-
|
|
354
342
|
} else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
|
|
355
343
|
_msgpack_buffer_append_reference(b, string);
|
|
356
344
|
|
data/ext/msgpack/buffer.h
CHANGED
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
|
|
50
50
|
#define NO_MAPPED_STRING ((VALUE)0)
|
|
51
51
|
|
|
52
|
-
#ifdef COMPAT_HAVE_ENCODING /* see compat.h*/
|
|
53
52
|
extern int msgpack_rb_encindex_utf8;
|
|
54
53
|
extern int msgpack_rb_encindex_usascii;
|
|
55
54
|
extern int msgpack_rb_encindex_ascii8bit;
|
|
56
|
-
|
|
55
|
+
|
|
56
|
+
extern ID s_uminus;
|
|
57
57
|
|
|
58
58
|
struct msgpack_buffer_chunk_t;
|
|
59
59
|
typedef struct msgpack_buffer_chunk_t msgpack_buffer_chunk_t;
|
|
@@ -262,6 +262,20 @@ static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE str
|
|
|
262
262
|
return length;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
+
static inline size_t msgpack_buffer_append_string_reference(msgpack_buffer_t* b, VALUE string)
|
|
266
|
+
{
|
|
267
|
+
size_t length = RSTRING_LEN(string);
|
|
268
|
+
|
|
269
|
+
if(length > MSGPACK_BUFFER_STRING_WRITE_REFERENCE_MINIMUM) {
|
|
270
|
+
_msgpack_buffer_append_long_string(b, string);
|
|
271
|
+
|
|
272
|
+
} else {
|
|
273
|
+
msgpack_buffer_append(b, RSTRING_PTR(string), length);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return length;
|
|
277
|
+
}
|
|
278
|
+
|
|
265
279
|
|
|
266
280
|
/*
|
|
267
281
|
* IO functions
|
|
@@ -424,7 +438,7 @@ static inline VALUE _msgpack_buffer_refer_head_mapped_string(msgpack_buffer_t* b
|
|
|
424
438
|
return rb_str_substr(b->head->mapped_string, offset, length);
|
|
425
439
|
}
|
|
426
440
|
|
|
427
|
-
static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen)
|
|
441
|
+
static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen, bool utf8)
|
|
428
442
|
{
|
|
429
443
|
#ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE
|
|
430
444
|
/* optimize */
|
|
@@ -432,16 +446,57 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
|
|
|
432
446
|
b->head->mapped_string != NO_MAPPED_STRING &&
|
|
433
447
|
length >= b->read_reference_threshold) {
|
|
434
448
|
VALUE result = _msgpack_buffer_refer_head_mapped_string(b, length);
|
|
449
|
+
if (utf8) ENCODING_SET(result, msgpack_rb_encindex_utf8);
|
|
435
450
|
_msgpack_buffer_consumed(b, length);
|
|
436
451
|
return result;
|
|
437
452
|
}
|
|
438
453
|
#endif
|
|
439
454
|
|
|
440
|
-
VALUE result
|
|
455
|
+
VALUE result;
|
|
456
|
+
|
|
457
|
+
#ifdef HAVE_RB_ENC_INTERNED_STR
|
|
458
|
+
if (will_be_frozen) {
|
|
459
|
+
result = rb_enc_interned_str(b->read_buffer, length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
|
|
460
|
+
} else {
|
|
461
|
+
if (utf8) {
|
|
462
|
+
result = rb_utf8_str_new(b->read_buffer, length);
|
|
463
|
+
} else {
|
|
464
|
+
result = rb_str_new(b->read_buffer, length);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
441
467
|
_msgpack_buffer_consumed(b, length);
|
|
442
468
|
return result;
|
|
469
|
+
|
|
470
|
+
#else
|
|
471
|
+
|
|
472
|
+
if (utf8) {
|
|
473
|
+
result = rb_utf8_str_new(b->read_buffer, length);
|
|
474
|
+
} else {
|
|
475
|
+
result = rb_str_new(b->read_buffer, length);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
#if STR_UMINUS_DEDUPE
|
|
479
|
+
if (will_be_frozen) {
|
|
480
|
+
#if STR_UMINUS_DEDUPE_FROZEN
|
|
481
|
+
// Starting from MRI 2.8 it is preferable to freeze the string
|
|
482
|
+
// before deduplication so that it can be interned directly
|
|
483
|
+
// otherwise it would be duplicated first which is wasteful.
|
|
484
|
+
rb_str_freeze(result);
|
|
485
|
+
#endif //STR_UMINUS_DEDUPE_FROZEN
|
|
486
|
+
// MRI 2.5 and older do not deduplicate strings that are already
|
|
487
|
+
// frozen.
|
|
488
|
+
result = rb_funcall(result, s_uminus, 0);
|
|
489
|
+
}
|
|
490
|
+
#endif // STR_UMINUS_DEDUPE
|
|
491
|
+
_msgpack_buffer_consumed(b, length);
|
|
492
|
+
return result;
|
|
493
|
+
|
|
494
|
+
#endif // HAVE_RB_ENC_INTERNED_STR
|
|
443
495
|
}
|
|
444
496
|
|
|
497
|
+
static inline VALUE msgpack_buffer_read_top_as_symbol(msgpack_buffer_t* b, size_t length)
|
|
498
|
+
{
|
|
499
|
+
return rb_str_intern(msgpack_buffer_read_top_as_string(b, length, true, false));
|
|
500
|
+
}
|
|
445
501
|
|
|
446
502
|
#endif
|
|
447
|
-
|
data/ext/msgpack/compat.h
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
#include <stdbool.h>
|
|
22
22
|
#include "ruby.h"
|
|
23
|
+
#include "ruby/encoding.h"
|
|
23
24
|
|
|
24
25
|
#if defined(HAVE_RUBY_ST_H)
|
|
25
26
|
# include "ruby/st.h" /* ruby hash on Ruby 1.9 */
|
|
@@ -38,18 +39,6 @@
|
|
|
38
39
|
# define ZALLOC_N(type,n) RB_ZALLOC_N(type,n)
|
|
39
40
|
#endif
|
|
40
41
|
|
|
41
|
-
/*
|
|
42
|
-
* COMPAT_HAVE_ENCODING
|
|
43
|
-
*/
|
|
44
|
-
#ifdef HAVE_RUBY_ENCODING_H
|
|
45
|
-
# include "ruby/encoding.h"
|
|
46
|
-
# define COMPAT_HAVE_ENCODING
|
|
47
|
-
#endif
|
|
48
|
-
|
|
49
|
-
#if defined(__MACRUBY__) /* MacRuby */
|
|
50
|
-
# undef COMPAT_HAVE_ENCODING
|
|
51
|
-
#endif
|
|
52
|
-
|
|
53
42
|
|
|
54
43
|
/*
|
|
55
44
|
* define STR_DUP_LIKELY_DOES_COPY
|
data/ext/msgpack/extconf.rb
CHANGED
|
@@ -2,13 +2,7 @@ require 'mkmf'
|
|
|
2
2
|
|
|
3
3
|
have_header("ruby/st.h")
|
|
4
4
|
have_header("st.h")
|
|
5
|
-
have_func("
|
|
6
|
-
have_func("rb_intern_str", ["ruby.h"])
|
|
7
|
-
have_func("rb_sym2str", ["ruby.h"])
|
|
8
|
-
have_func("rb_str_intern", ["ruby.h"])
|
|
9
|
-
have_func("rb_block_lambda", ["ruby.h"])
|
|
10
|
-
have_func("rb_hash_dup", ["ruby.h"])
|
|
11
|
-
have_func("rb_hash_clear", ["ruby.h"])
|
|
5
|
+
have_func("rb_enc_interned_str", "ruby.h")
|
|
12
6
|
|
|
13
7
|
unless RUBY_PLATFORM.include? 'mswin'
|
|
14
8
|
$CFLAGS << %[ -I.. -Wall -O3 -g -std=gnu99]
|
|
@@ -25,6 +19,44 @@ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
|
|
25
19
|
$CFLAGS << %[ -DDISABLE_RMEM]
|
|
26
20
|
end
|
|
27
21
|
|
|
22
|
+
# checking if Hash#[]= (rb_hash_aset) dedupes string keys
|
|
23
|
+
h = {}
|
|
24
|
+
x = {}
|
|
25
|
+
r = rand.to_s
|
|
26
|
+
h[%W(#{r}).join('')] = :foo
|
|
27
|
+
x[%W(#{r}).join('')] = :foo
|
|
28
|
+
if x.keys[0].equal?(h.keys[0])
|
|
29
|
+
$CFLAGS << ' -DHASH_ASET_DEDUPE=1 '
|
|
30
|
+
else
|
|
31
|
+
$CFLAGS << ' -DHASH_ASET_DEDUPE=0 '
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# checking if String#-@ (str_uminus) dedupes... '
|
|
36
|
+
begin
|
|
37
|
+
a = -(%w(t e s t).join)
|
|
38
|
+
b = -(%w(t e s t).join)
|
|
39
|
+
if a.equal?(b)
|
|
40
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE=1 '
|
|
41
|
+
else
|
|
42
|
+
$CFLAGS += ' -DSTR_UMINUS_DEDUPE=0 '
|
|
43
|
+
end
|
|
44
|
+
rescue NoMethodError
|
|
45
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# checking if String#-@ (str_uminus) directly interns frozen strings... '
|
|
49
|
+
begin
|
|
50
|
+
s = rand.to_s.freeze
|
|
51
|
+
if (-s).equal?(s) && (-s.dup).equal?(s)
|
|
52
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=1 '
|
|
53
|
+
else
|
|
54
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
|
|
55
|
+
end
|
|
56
|
+
rescue NoMethodError
|
|
57
|
+
$CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
|
|
58
|
+
end
|
|
59
|
+
|
|
28
60
|
if warnflags = CONFIG['warnflags']
|
|
29
61
|
warnflags.slice!(/ -Wdeclaration-after-statement/)
|
|
30
62
|
end
|
data/ext/msgpack/factory_class.c
CHANGED
|
@@ -32,6 +32,8 @@ struct msgpack_factory_t {
|
|
|
32
32
|
msgpack_packer_ext_registry_t pkrg;
|
|
33
33
|
msgpack_unpacker_ext_registry_t ukrg;
|
|
34
34
|
bool has_symbol_ext_type;
|
|
35
|
+
bool optimized_symbol_ext_type;
|
|
36
|
+
int symbol_ext_type;
|
|
35
37
|
};
|
|
36
38
|
|
|
37
39
|
#define FACTORY(from, name) \
|
|
@@ -114,6 +116,8 @@ VALUE MessagePack_Factory_unpacker(int argc, VALUE* argv, VALUE self)
|
|
|
114
116
|
|
|
115
117
|
msgpack_unpacker_ext_registry_destroy(&uk->ext_registry);
|
|
116
118
|
msgpack_unpacker_ext_registry_dup(&fc->ukrg, &uk->ext_registry);
|
|
119
|
+
uk->optimized_symbol_ext_type = fc->optimized_symbol_ext_type;
|
|
120
|
+
uk->symbol_ext_type = fc->symbol_ext_type;
|
|
117
121
|
|
|
118
122
|
return unpacker;
|
|
119
123
|
}
|
|
@@ -128,11 +132,7 @@ static VALUE Factory_registered_types_internal(VALUE self)
|
|
|
128
132
|
rb_hash_aset(uk_mapping, INT2FIX(i - 128), fc->ukrg.array[i]);
|
|
129
133
|
}
|
|
130
134
|
}
|
|
131
|
-
#ifdef HAVE_RB_HASH_DUP
|
|
132
135
|
return rb_ary_new3(2, rb_hash_dup(fc->pkrg.hash), uk_mapping);
|
|
133
|
-
#else
|
|
134
|
-
return rb_ary_new3(2, rb_funcall(fc->pkrg.hash, rb_intern("dup"), 0), uk_mapping);
|
|
135
|
-
#endif
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
@@ -141,7 +141,7 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
|
141
141
|
|
|
142
142
|
int ext_type;
|
|
143
143
|
VALUE ext_module;
|
|
144
|
-
VALUE options;
|
|
144
|
+
VALUE options = Qnil;
|
|
145
145
|
VALUE packer_arg, unpacker_arg;
|
|
146
146
|
VALUE packer_proc, unpacker_proc;
|
|
147
147
|
|
|
@@ -188,6 +188,8 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
|
188
188
|
if(unpacker_arg != Qnil) {
|
|
189
189
|
if(rb_type(unpacker_arg) == T_SYMBOL || rb_type(unpacker_arg) == T_STRING) {
|
|
190
190
|
unpacker_proc = rb_obj_method(ext_module, unpacker_arg);
|
|
191
|
+
} else if (rb_respond_to(unpacker_arg, rb_intern("call"))) {
|
|
192
|
+
unpacker_proc = unpacker_arg;
|
|
191
193
|
} else {
|
|
192
194
|
unpacker_proc = rb_funcall(unpacker_arg, rb_intern("method"), 1, ID2SYM(rb_intern("call")));
|
|
193
195
|
}
|
|
@@ -197,6 +199,9 @@ static VALUE Factory_register_type(int argc, VALUE* argv, VALUE self)
|
|
|
197
199
|
|
|
198
200
|
if (ext_module == rb_cSymbol) {
|
|
199
201
|
fc->has_symbol_ext_type = true;
|
|
202
|
+
if(RB_TEST(options) && RB_TEST(rb_hash_aref(options, ID2SYM(rb_intern("optimized_symbols_parsing"))))) {
|
|
203
|
+
fc->optimized_symbol_ext_type = true;
|
|
204
|
+
}
|
|
200
205
|
}
|
|
201
206
|
|
|
202
207
|
msgpack_unpacker_ext_registry_put(&fc->ukrg, ext_module, ext_type, unpacker_proc, unpacker_arg);
|
data/ext/msgpack/packer.c
CHANGED
|
@@ -121,7 +121,7 @@ void msgpack_packer_write_hash_value(msgpack_packer_t* pk, VALUE v)
|
|
|
121
121
|
#endif
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
bool msgpack_packer_try_write_with_ext_type_lookup(msgpack_packer_t* pk, VALUE v)
|
|
125
125
|
{
|
|
126
126
|
int ext_type;
|
|
127
127
|
|
|
@@ -131,7 +131,14 @@ void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
|
|
|
131
131
|
VALUE payload = rb_funcall(proc, s_call, 1, v);
|
|
132
132
|
StringValue(payload);
|
|
133
133
|
msgpack_packer_write_ext(pk, ext_type, payload);
|
|
134
|
-
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
|
|
140
|
+
{
|
|
141
|
+
if(!(msgpack_packer_try_write_with_ext_type_lookup(pk, v))) {
|
|
135
142
|
rb_funcall(v, pk->to_msgpack_method, 1, pk->to_msgpack_arg);
|
|
136
143
|
}
|
|
137
144
|
}
|
|
@@ -155,13 +162,19 @@ void msgpack_packer_write_value(msgpack_packer_t* pk, VALUE v)
|
|
|
155
162
|
msgpack_packer_write_symbol_value(pk, v);
|
|
156
163
|
break;
|
|
157
164
|
case T_STRING:
|
|
158
|
-
|
|
165
|
+
if(rb_class_of(v) == rb_cString || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
|
166
|
+
msgpack_packer_write_string_value(pk, v);
|
|
167
|
+
}
|
|
159
168
|
break;
|
|
160
169
|
case T_ARRAY:
|
|
161
|
-
|
|
170
|
+
if(rb_class_of(v) == rb_cArray || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
|
171
|
+
msgpack_packer_write_array_value(pk, v);
|
|
172
|
+
}
|
|
162
173
|
break;
|
|
163
174
|
case T_HASH:
|
|
164
|
-
|
|
175
|
+
if(rb_class_of(v) == rb_cHash || !msgpack_packer_try_write_with_ext_type_lookup(pk, v)) {
|
|
176
|
+
msgpack_packer_write_hash_value(pk, v);
|
|
177
|
+
}
|
|
165
178
|
break;
|
|
166
179
|
case T_BIGNUM:
|
|
167
180
|
msgpack_packer_write_bignum_value(pk, v);
|
data/ext/msgpack/packer.h
CHANGED
|
@@ -396,7 +396,6 @@ static inline void msgpack_packer_write_ext(msgpack_packer_t* pk, int ext_type,
|
|
|
396
396
|
msgpack_buffer_append_string(PACKER_BUFFER_(pk), payload);
|
|
397
397
|
}
|
|
398
398
|
|
|
399
|
-
#ifdef COMPAT_HAVE_ENCODING
|
|
400
399
|
static inline bool msgpack_packer_is_binary(VALUE v, int encindex)
|
|
401
400
|
{
|
|
402
401
|
return encindex == msgpack_rb_encindex_ascii8bit;
|
|
@@ -414,7 +413,6 @@ static inline bool msgpack_packer_is_utf8_compat_string(VALUE v, int encindex)
|
|
|
414
413
|
#endif
|
|
415
414
|
;
|
|
416
415
|
}
|
|
417
|
-
#endif
|
|
418
416
|
|
|
419
417
|
static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE v)
|
|
420
418
|
{
|
|
@@ -425,7 +423,6 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
|
425
423
|
rb_raise(rb_eArgError, "size of string is too long to pack: %lu bytes should be <= %lu", len, 0xffffffffUL);
|
|
426
424
|
}
|
|
427
425
|
|
|
428
|
-
#ifdef COMPAT_HAVE_ENCODING
|
|
429
426
|
int encindex = ENCODING_GET(v);
|
|
430
427
|
if(msgpack_packer_is_binary(v, encindex) && !pk->compatibility_mode) {
|
|
431
428
|
/* write ASCII-8BIT string using Binary type */
|
|
@@ -443,24 +440,11 @@ static inline void msgpack_packer_write_string_value(msgpack_packer_t* pk, VALUE
|
|
|
443
440
|
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
|
444
441
|
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
|
445
442
|
}
|
|
446
|
-
#else
|
|
447
|
-
msgpack_packer_write_raw_header(pk, (unsigned int)len);
|
|
448
|
-
msgpack_buffer_append_string(PACKER_BUFFER_(pk), v);
|
|
449
|
-
#endif
|
|
450
443
|
}
|
|
451
444
|
|
|
452
445
|
static inline void msgpack_packer_write_symbol_string_value(msgpack_packer_t* pk, VALUE v)
|
|
453
446
|
{
|
|
454
|
-
#ifdef HAVE_RB_SYM2STR
|
|
455
|
-
/* rb_sym2str is added since MRI 2.2.0 */
|
|
456
447
|
msgpack_packer_write_string_value(pk, rb_sym2str(v));
|
|
457
|
-
#else
|
|
458
|
-
VALUE str = rb_id2str(SYM2ID(v));
|
|
459
|
-
if (!str) {
|
|
460
|
-
rb_raise(rb_eRuntimeError, "could not convert a symbol to string");
|
|
461
|
-
}
|
|
462
|
-
msgpack_packer_write_string_value(pk, str);
|
|
463
|
-
#endif
|
|
464
448
|
}
|
|
465
449
|
|
|
466
450
|
void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v);
|
data/ext/msgpack/packer_class.c
CHANGED
|
@@ -339,11 +339,7 @@ static VALUE Packer_write_to(VALUE self, VALUE io)
|
|
|
339
339
|
static VALUE Packer_registered_types_internal(VALUE self)
|
|
340
340
|
{
|
|
341
341
|
PACKER(self, pk);
|
|
342
|
-
#ifdef HAVE_RB_HASH_DUP
|
|
343
342
|
return rb_hash_dup(pk->ext_registry.hash);
|
|
344
|
-
#else
|
|
345
|
-
return rb_funcall(pk->ext_registry.hash, rb_intern("dup"), 0);
|
|
346
|
-
#endif
|
|
347
343
|
}
|
|
348
344
|
|
|
349
345
|
static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
|
@@ -359,12 +355,7 @@ static VALUE Packer_register_type(int argc, VALUE* argv, VALUE self)
|
|
|
359
355
|
case 2:
|
|
360
356
|
/* register_type(0x7f, Time) {|obj| block... } */
|
|
361
357
|
rb_need_block();
|
|
362
|
-
#ifdef HAVE_RB_BLOCK_LAMBDA
|
|
363
358
|
proc = rb_block_lambda();
|
|
364
|
-
#else
|
|
365
|
-
/* MRI 1.8 */
|
|
366
|
-
proc = rb_block_proc();
|
|
367
|
-
#endif
|
|
368
359
|
arg = proc;
|
|
369
360
|
break;
|
|
370
361
|
case 3:
|
|
@@ -43,37 +43,15 @@ void msgpack_packer_ext_registry_mark(msgpack_packer_ext_registry_t* pkrg)
|
|
|
43
43
|
void msgpack_packer_ext_registry_dup(msgpack_packer_ext_registry_t* src,
|
|
44
44
|
msgpack_packer_ext_registry_t* dst)
|
|
45
45
|
{
|
|
46
|
-
#ifdef HAVE_RB_HASH_DUP
|
|
47
46
|
dst->hash = rb_hash_dup(src->hash);
|
|
48
47
|
dst->cache = rb_hash_dup(src->cache);
|
|
49
|
-
#else
|
|
50
|
-
dst->hash = rb_funcall(src->hash, rb_intern("dup"), 0);
|
|
51
|
-
dst->cache = rb_funcall(src->cache, rb_intern("dup"), 0);
|
|
52
|
-
#endif
|
|
53
48
|
}
|
|
54
49
|
|
|
55
|
-
#ifndef HAVE_RB_HASH_CLEAR
|
|
56
|
-
|
|
57
|
-
static int
|
|
58
|
-
__rb_hash_clear_clear_i(key, value, dummy)
|
|
59
|
-
VALUE key, value, dummy;
|
|
60
|
-
{
|
|
61
|
-
return ST_DELETE;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
#endif
|
|
65
|
-
|
|
66
50
|
VALUE msgpack_packer_ext_registry_put(msgpack_packer_ext_registry_t* pkrg,
|
|
67
51
|
VALUE ext_module, int ext_type, VALUE proc, VALUE arg)
|
|
68
52
|
{
|
|
69
53
|
VALUE e = rb_ary_new3(3, INT2FIX(ext_type), proc, arg);
|
|
70
54
|
/* clear lookup cache not to miss added type */
|
|
71
|
-
#ifdef HAVE_RB_HASH_CLEAR
|
|
72
55
|
rb_hash_clear(pkrg->cache);
|
|
73
|
-
#else
|
|
74
|
-
if(FIX2INT(rb_funcall(pkrg->cache, rb_intern("size"), 0)) > 0) {
|
|
75
|
-
rb_hash_foreach(pkrg->cache, __rb_hash_clear_clear_i, 0);
|
|
76
|
-
}
|
|
77
|
-
#endif
|
|
78
56
|
return rb_hash_aset(pkrg->hash, ext_module, e);
|
|
79
57
|
}
|
data/ext/msgpack/unpacker.c
CHANGED
|
@@ -142,32 +142,27 @@ static inline void reset_head_byte(msgpack_unpacker_t* uk)
|
|
|
142
142
|
|
|
143
143
|
static inline int object_complete(msgpack_unpacker_t* uk, VALUE object)
|
|
144
144
|
{
|
|
145
|
+
if(uk->freeze) {
|
|
146
|
+
rb_obj_freeze(object);
|
|
147
|
+
}
|
|
148
|
+
|
|
145
149
|
uk->last_object = object;
|
|
146
150
|
reset_head_byte(uk);
|
|
147
151
|
return PRIMITIVE_OBJECT_COMPLETE;
|
|
148
152
|
}
|
|
149
153
|
|
|
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)
|
|
154
|
+
static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
|
|
159
155
|
{
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
return object_complete(uk, str);
|
|
156
|
+
uk->last_object = object;
|
|
157
|
+
reset_head_byte(uk);
|
|
158
|
+
return PRIMITIVE_OBJECT_COMPLETE;
|
|
164
159
|
}
|
|
165
160
|
|
|
166
161
|
static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
|
|
167
162
|
{
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
163
|
+
if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
|
|
164
|
+
return object_complete_symbol(uk, rb_str_intern(str));
|
|
165
|
+
}
|
|
171
166
|
|
|
172
167
|
VALUE proc = msgpack_unpacker_ext_registry_lookup(&uk->ext_registry, ext_type);
|
|
173
168
|
if(proc != Qnil) {
|
|
@@ -271,9 +266,10 @@ static int read_raw_body_cont(msgpack_unpacker_t* uk)
|
|
|
271
266
|
|
|
272
267
|
int ret;
|
|
273
268
|
if(uk->reading_raw_type == RAW_TYPE_STRING) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
269
|
+
ENCODING_SET(uk->reading_raw, msgpack_rb_encindex_utf8);
|
|
270
|
+
ret = object_complete(uk, uk->reading_raw);
|
|
271
|
+
} else if (uk->reading_raw_type == RAW_TYPE_BINARY) {
|
|
272
|
+
ret = object_complete(uk, uk->reading_raw);
|
|
277
273
|
} else {
|
|
278
274
|
ret = object_complete_ext(uk, uk->reading_raw_type, uk->reading_raw);
|
|
279
275
|
}
|
|
@@ -288,20 +284,26 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
|
|
|
288
284
|
/* try optimized read */
|
|
289
285
|
size_t length = uk->reading_raw_remaining;
|
|
290
286
|
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
287
|
int ret;
|
|
296
|
-
if(
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
ret = object_complete_binary(uk, string);
|
|
288
|
+
if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
|
|
289
|
+
VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length);
|
|
290
|
+
ret = object_complete_symbol(uk, symbol);
|
|
300
291
|
} else {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
292
|
+
/* don't use zerocopy for hash keys but get a frozen string directly
|
|
293
|
+
* because rb_hash_aset freezes keys and it causes copying */
|
|
294
|
+
bool will_freeze = uk->freeze || is_reading_map_key(uk);
|
|
295
|
+
VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
|
|
296
|
+
if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
|
|
297
|
+
ret = object_complete(uk, string);
|
|
298
|
+
} else {
|
|
299
|
+
ret = object_complete_ext(uk, raw_type, string);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
# if !HASH_ASET_DEDUPE
|
|
303
|
+
if(will_freeze) {
|
|
304
|
+
rb_obj_freeze(string);
|
|
305
|
+
}
|
|
306
|
+
# endif
|
|
305
307
|
}
|
|
306
308
|
uk->reading_raw_remaining = 0;
|
|
307
309
|
return ret;
|
|
@@ -332,7 +334,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
|
332
334
|
SWITCH_RANGE(b, 0xa0, 0xbf) // FixRaw / fixstr
|
|
333
335
|
int count = b & 0x1f;
|
|
334
336
|
if(count == 0) {
|
|
335
|
-
return
|
|
337
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
|
336
338
|
}
|
|
337
339
|
/* read_raw_body_begin sets uk->reading_raw */
|
|
338
340
|
uk->reading_raw_remaining = count;
|
|
@@ -517,7 +519,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
|
517
519
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
|
518
520
|
uint8_t count = cb->u8;
|
|
519
521
|
if(count == 0) {
|
|
520
|
-
return
|
|
522
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
|
521
523
|
}
|
|
522
524
|
/* read_raw_body_begin sets uk->reading_raw */
|
|
523
525
|
uk->reading_raw_remaining = count;
|
|
@@ -529,7 +531,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
|
529
531
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
|
530
532
|
uint16_t count = _msgpack_be16(cb->u16);
|
|
531
533
|
if(count == 0) {
|
|
532
|
-
return
|
|
534
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
|
533
535
|
}
|
|
534
536
|
/* read_raw_body_begin sets uk->reading_raw */
|
|
535
537
|
uk->reading_raw_remaining = count;
|
|
@@ -541,7 +543,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
|
541
543
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
|
542
544
|
uint32_t count = _msgpack_be32(cb->u32);
|
|
543
545
|
if(count == 0) {
|
|
544
|
-
return
|
|
546
|
+
return object_complete(uk, rb_utf8_str_new_static("", 0));
|
|
545
547
|
}
|
|
546
548
|
/* read_raw_body_begin sets uk->reading_raw */
|
|
547
549
|
uk->reading_raw_remaining = count;
|
|
@@ -553,7 +555,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
|
553
555
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
|
|
554
556
|
uint8_t count = cb->u8;
|
|
555
557
|
if(count == 0) {
|
|
556
|
-
return
|
|
558
|
+
return object_complete(uk, rb_str_new_static("", 0));
|
|
557
559
|
}
|
|
558
560
|
/* read_raw_body_begin sets uk->reading_raw */
|
|
559
561
|
uk->reading_raw_remaining = count;
|
|
@@ -565,7 +567,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
|
565
567
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
|
|
566
568
|
uint16_t count = _msgpack_be16(cb->u16);
|
|
567
569
|
if(count == 0) {
|
|
568
|
-
return
|
|
570
|
+
return object_complete(uk, rb_str_new_static("", 0));
|
|
569
571
|
}
|
|
570
572
|
/* read_raw_body_begin sets uk->reading_raw */
|
|
571
573
|
uk->reading_raw_remaining = count;
|
|
@@ -577,7 +579,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
|
|
|
577
579
|
READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
|
|
578
580
|
uint32_t count = _msgpack_be32(cb->u32);
|
|
579
581
|
if(count == 0) {
|
|
580
|
-
return
|
|
582
|
+
return object_complete(uk, rb_str_new_static("", 0));
|
|
581
583
|
}
|
|
582
584
|
/* read_raw_body_begin sets uk->reading_raw */
|
|
583
585
|
uk->reading_raw_remaining = count;
|
|
@@ -719,18 +721,8 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
|
|
|
719
721
|
break;
|
|
720
722
|
case STACK_TYPE_MAP_VALUE:
|
|
721
723
|
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 */
|
|
724
|
+
/* here uses rb_str_intern instead of rb_intern so that Ruby VM can GC unused symbols */
|
|
725
725
|
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
726
|
} else {
|
|
735
727
|
rb_hash_aset(top->object, top->key, uk->last_object);
|
|
736
728
|
}
|
data/ext/msgpack/unpacker.h
CHANGED
|
@@ -64,7 +64,10 @@ struct msgpack_unpacker_t {
|
|
|
64
64
|
|
|
65
65
|
/* options */
|
|
66
66
|
bool symbolize_keys;
|
|
67
|
+
bool freeze;
|
|
67
68
|
bool allow_unknown_ext;
|
|
69
|
+
bool optimized_symbol_ext_type;
|
|
70
|
+
int symbol_ext_type;
|
|
68
71
|
};
|
|
69
72
|
|
|
70
73
|
#define UNPACKER_BUFFER_(uk) (&(uk)->buffer)
|
|
@@ -96,6 +99,11 @@ static inline void msgpack_unpacker_set_symbolized_keys(msgpack_unpacker_t* uk,
|
|
|
96
99
|
uk->symbolize_keys = enable;
|
|
97
100
|
}
|
|
98
101
|
|
|
102
|
+
static inline void msgpack_unpacker_set_freeze(msgpack_unpacker_t* uk, bool enable)
|
|
103
|
+
{
|
|
104
|
+
uk->freeze = enable;
|
|
105
|
+
}
|
|
106
|
+
|
|
99
107
|
static inline void msgpack_unpacker_set_allow_unknown_ext(msgpack_unpacker_t* uk, bool enable)
|
|
100
108
|
{
|
|
101
109
|
uk->allow_unknown_ext = enable;
|