msgpack 1.2.6 → 1.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +56 -0
- data/.gitignore +3 -1
- data/.rubocop.yml +4 -1
- data/ChangeLog +59 -0
- data/Gemfile +3 -0
- data/README.md +242 -0
- data/Rakefile +3 -8
- data/doclib/msgpack/factory.rb +1 -0
- data/doclib/msgpack/packer.rb +20 -0
- data/doclib/msgpack/time.rb +22 -0
- data/doclib/msgpack/timestamp.rb +44 -0
- data/doclib/msgpack.rb +2 -2
- data/ext/java/org/msgpack/jruby/Buffer.java +21 -16
- data/ext/java/org/msgpack/jruby/Decoder.java +29 -10
- data/ext/java/org/msgpack/jruby/Encoder.java +38 -19
- 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 +8 -3
- data/ext/java/org/msgpack/jruby/Packer.java +31 -8
- 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 +21 -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 +8 -10
- data/msgpack.gemspec +3 -7
- data/spec/cruby/buffer_spec.rb +6 -1
- data/spec/factory_spec.rb +17 -0
- data/spec/msgpack_spec.rb +44 -1
- data/spec/packer_spec.rb +54 -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 -201
@@ -27,6 +27,7 @@ import static org.jruby.runtime.Visibility.PRIVATE;
|
|
27
27
|
|
28
28
|
@JRubyClass(name="MessagePack::Unpacker")
|
29
29
|
public class Unpacker extends RubyObject {
|
30
|
+
private static final long serialVersionUID = 8451264671199362492L;
|
30
31
|
private final ExtensionRegistry registry;
|
31
32
|
|
32
33
|
private IRubyObject stream;
|
@@ -34,6 +35,7 @@ public class Unpacker extends RubyObject {
|
|
34
35
|
private Decoder decoder;
|
35
36
|
private final RubyClass underflowErrorClass;
|
36
37
|
private boolean symbolizeKeys;
|
38
|
+
private boolean freeze;
|
37
39
|
private boolean allowUnknownExt;
|
38
40
|
|
39
41
|
public Unpacker(Ruby runtime, RubyClass type) {
|
@@ -56,19 +58,25 @@ public class Unpacker extends RubyObject {
|
|
56
58
|
public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
|
57
59
|
symbolizeKeys = false;
|
58
60
|
allowUnknownExt = false;
|
61
|
+
freeze = false;
|
59
62
|
if (args.length > 0) {
|
63
|
+
Ruby runtime = ctx.runtime;
|
60
64
|
if (args[args.length - 1] instanceof RubyHash) {
|
61
65
|
RubyHash options = (RubyHash) args[args.length - 1];
|
62
|
-
IRubyObject sk = options.fastARef(
|
66
|
+
IRubyObject sk = options.fastARef(runtime.newSymbol("symbolize_keys"));
|
63
67
|
if (sk != null) {
|
64
68
|
symbolizeKeys = sk.isTrue();
|
65
69
|
}
|
66
|
-
IRubyObject
|
70
|
+
IRubyObject f = options.fastARef(runtime.newSymbol("freeze"));
|
71
|
+
if (f != null) {
|
72
|
+
freeze = f.isTrue();
|
73
|
+
}
|
74
|
+
IRubyObject au = options.fastARef(runtime.newSymbol("allow_unknown_ext"));
|
67
75
|
if (au != null) {
|
68
76
|
allowUnknownExt = au.isTrue();
|
69
77
|
}
|
70
78
|
}
|
71
|
-
if (args[0] !=
|
79
|
+
if (args[0] != runtime.getNil() && !(args[0] instanceof RubyHash)) {
|
72
80
|
setStream(ctx, args[0]);
|
73
81
|
}
|
74
82
|
}
|
@@ -76,19 +84,24 @@ public class Unpacker extends RubyObject {
|
|
76
84
|
}
|
77
85
|
|
78
86
|
public static Unpacker newUnpacker(ThreadContext ctx, ExtensionRegistry extRegistry, IRubyObject[] args) {
|
79
|
-
Unpacker unpacker = new Unpacker(ctx.
|
87
|
+
Unpacker unpacker = new Unpacker(ctx.runtime, ctx.runtime.getModule("MessagePack").getClass("Unpacker"), extRegistry);
|
80
88
|
unpacker.initialize(ctx, args);
|
81
89
|
return unpacker;
|
82
90
|
}
|
83
91
|
|
84
92
|
@JRubyMethod(name = "symbolize_keys?")
|
85
93
|
public IRubyObject isSymbolizeKeys(ThreadContext ctx) {
|
86
|
-
return symbolizeKeys ? ctx.
|
94
|
+
return symbolizeKeys ? ctx.runtime.getTrue() : ctx.runtime.getFalse();
|
95
|
+
}
|
96
|
+
|
97
|
+
@JRubyMethod(name = "freeze?")
|
98
|
+
public IRubyObject isFreeze(ThreadContext ctx) {
|
99
|
+
return freeze ? ctx.runtime.getTrue() : ctx.runtime.getFalse();
|
87
100
|
}
|
88
101
|
|
89
102
|
@JRubyMethod(name = "allow_unknown_ext?")
|
90
103
|
public IRubyObject isAllowUnknownExt(ThreadContext ctx) {
|
91
|
-
return allowUnknownExt ? ctx.
|
104
|
+
return allowUnknownExt ? ctx.runtime.getTrue() : ctx.runtime.getFalse();
|
92
105
|
}
|
93
106
|
|
94
107
|
@JRubyMethod(name = "registered_types_internal", visibility = PRIVATE)
|
@@ -98,7 +111,7 @@ public class Unpacker extends RubyObject {
|
|
98
111
|
|
99
112
|
@JRubyMethod(name = "register_type", required = 1, optional = 2)
|
100
113
|
public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
|
101
|
-
Ruby runtime = ctx.
|
114
|
+
Ruby runtime = ctx.runtime;
|
102
115
|
IRubyObject type = args[0];
|
103
116
|
|
104
117
|
RubyModule extModule;
|
@@ -144,7 +157,7 @@ public class Unpacker extends RubyObject {
|
|
144
157
|
if (limit == -1) {
|
145
158
|
limit = byteList.length() - offset;
|
146
159
|
}
|
147
|
-
Decoder decoder = new Decoder(ctx.
|
160
|
+
Decoder decoder = new Decoder(ctx.runtime, registry, byteList.unsafeBytes(), byteList.begin() + offset, limit, symbolizeKeys, freeze, allowUnknownExt);
|
148
161
|
try {
|
149
162
|
data = null;
|
150
163
|
data = decoder.next();
|
@@ -153,13 +166,13 @@ public class Unpacker extends RubyObject {
|
|
153
166
|
throw re;
|
154
167
|
}
|
155
168
|
}
|
156
|
-
return ctx.
|
169
|
+
return ctx.runtime.newFixnum(decoder.offset());
|
157
170
|
}
|
158
171
|
|
159
172
|
@JRubyMethod(name = "data")
|
160
173
|
public IRubyObject getData(ThreadContext ctx) {
|
161
174
|
if (data == null) {
|
162
|
-
return ctx.
|
175
|
+
return ctx.runtime.getNil();
|
163
176
|
} else {
|
164
177
|
return data;
|
165
178
|
}
|
@@ -167,14 +180,14 @@ public class Unpacker extends RubyObject {
|
|
167
180
|
|
168
181
|
@JRubyMethod(name = "finished?")
|
169
182
|
public IRubyObject finished_p(ThreadContext ctx) {
|
170
|
-
return data == null ? ctx.
|
183
|
+
return data == null ? ctx.runtime.getFalse() : ctx.runtime.getTrue();
|
171
184
|
}
|
172
185
|
|
173
|
-
@JRubyMethod(required = 1)
|
186
|
+
@JRubyMethod(required = 1, name = "feed", alias = { "feed_reference" })
|
174
187
|
public IRubyObject feed(ThreadContext ctx, IRubyObject data) {
|
175
188
|
ByteList byteList = data.asString().getByteList();
|
176
189
|
if (decoder == null) {
|
177
|
-
decoder = new Decoder(ctx.
|
190
|
+
decoder = new Decoder(ctx.runtime, registry, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
|
178
191
|
} else {
|
179
192
|
decoder.feed(byteList.unsafeBytes(), byteList.begin(), byteList.length());
|
180
193
|
}
|
@@ -191,7 +204,7 @@ public class Unpacker extends RubyObject {
|
|
191
204
|
feed(ctx, data);
|
192
205
|
if (block.isGiven()) {
|
193
206
|
each(ctx, block);
|
194
|
-
return ctx.
|
207
|
+
return ctx.runtime.getNil();
|
195
208
|
} else {
|
196
209
|
return callMethod(ctx, "to_enum");
|
197
210
|
}
|
@@ -219,7 +232,7 @@ public class Unpacker extends RubyObject {
|
|
219
232
|
|
220
233
|
@JRubyMethod
|
221
234
|
public IRubyObject fill(ThreadContext ctx) {
|
222
|
-
return ctx.
|
235
|
+
return ctx.runtime.getNil();
|
223
236
|
}
|
224
237
|
|
225
238
|
@JRubyMethod
|
@@ -227,13 +240,13 @@ public class Unpacker extends RubyObject {
|
|
227
240
|
if (decoder != null) {
|
228
241
|
decoder.reset();
|
229
242
|
}
|
230
|
-
return ctx.
|
243
|
+
return ctx.runtime.getNil();
|
231
244
|
}
|
232
245
|
|
233
246
|
@JRubyMethod(name = "read", alias = { "unpack" })
|
234
247
|
public IRubyObject read(ThreadContext ctx) {
|
235
248
|
if (decoder == null) {
|
236
|
-
throw ctx.
|
249
|
+
throw ctx.runtime.newEOFError();
|
237
250
|
}
|
238
251
|
try {
|
239
252
|
return decoder.next();
|
@@ -241,19 +254,19 @@ public class Unpacker extends RubyObject {
|
|
241
254
|
if (re.getException().getType() != underflowErrorClass) {
|
242
255
|
throw re;
|
243
256
|
} else {
|
244
|
-
throw ctx.
|
257
|
+
throw ctx.runtime.newEOFError();
|
245
258
|
}
|
246
259
|
}
|
247
260
|
}
|
248
261
|
|
249
262
|
@JRubyMethod(name = "skip")
|
250
263
|
public IRubyObject skip(ThreadContext ctx) {
|
251
|
-
throw ctx.
|
264
|
+
throw ctx.runtime.newNotImplementedError("Not supported yet in JRuby implementation");
|
252
265
|
}
|
253
266
|
|
254
267
|
@JRubyMethod(name = "skip_nil")
|
255
268
|
public IRubyObject skipNil(ThreadContext ctx) {
|
256
|
-
throw ctx.
|
269
|
+
throw ctx.runtime.newNotImplementedError("Not supported yet in JRuby implementation");
|
257
270
|
}
|
258
271
|
|
259
272
|
@JRubyMethod
|
@@ -265,11 +278,11 @@ public class Unpacker extends RubyObject {
|
|
265
278
|
if (re.getException().getType() != underflowErrorClass) {
|
266
279
|
throw re;
|
267
280
|
} else {
|
268
|
-
throw ctx.
|
281
|
+
throw ctx.runtime.newEOFError();
|
269
282
|
}
|
270
283
|
}
|
271
284
|
}
|
272
|
-
return ctx.
|
285
|
+
return ctx.runtime.getNil();
|
273
286
|
}
|
274
287
|
|
275
288
|
@JRubyMethod
|
@@ -281,17 +294,17 @@ public class Unpacker extends RubyObject {
|
|
281
294
|
if (re.getException().getType() != underflowErrorClass) {
|
282
295
|
throw re;
|
283
296
|
} else {
|
284
|
-
throw ctx.
|
297
|
+
throw ctx.runtime.newEOFError();
|
285
298
|
}
|
286
299
|
}
|
287
300
|
}
|
288
|
-
return ctx.
|
301
|
+
return ctx.runtime.getNil();
|
289
302
|
}
|
290
303
|
|
291
304
|
@JRubyMethod(name = "stream")
|
292
305
|
public IRubyObject getStream(ThreadContext ctx) {
|
293
306
|
if (stream == null) {
|
294
|
-
return ctx.
|
307
|
+
return ctx.runtime.getNil();
|
295
308
|
} else {
|
296
309
|
return stream;
|
297
310
|
}
|
@@ -307,12 +320,12 @@ public class Unpacker extends RubyObject {
|
|
307
320
|
} else if (stream.respondsTo("read")) {
|
308
321
|
str = stream.callMethod(ctx, "read").asString();
|
309
322
|
} else {
|
310
|
-
throw ctx.
|
323
|
+
throw ctx.runtime.newTypeError(stream, "IO");
|
311
324
|
}
|
312
325
|
ByteList byteList = str.getByteList();
|
313
326
|
this.stream = stream;
|
314
327
|
this.decoder = null;
|
315
|
-
this.decoder = new Decoder(ctx.
|
328
|
+
this.decoder = new Decoder(ctx.runtime, registry, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
|
316
329
|
return getStream(ctx);
|
317
330
|
}
|
318
331
|
}
|
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);
|