msgpack 1.4.5 → 1.5.6
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 +5 -5
- data/ChangeLog +32 -0
- data/README.md +25 -1
- data/bench/bench.rb +78 -0
- data/doclib/msgpack/factory.rb +45 -2
- data/ext/java/org/msgpack/jruby/Buffer.java +6 -0
- data/ext/java/org/msgpack/jruby/Decoder.java +23 -19
- data/ext/java/org/msgpack/jruby/Encoder.java +46 -18
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +24 -31
- data/ext/java/org/msgpack/jruby/Factory.java +40 -5
- data/ext/java/org/msgpack/jruby/Packer.java +21 -11
- data/ext/java/org/msgpack/jruby/Unpacker.java +44 -22
- data/ext/msgpack/buffer.c +9 -36
- data/ext/msgpack/buffer.h +9 -1
- data/ext/msgpack/buffer_class.c +18 -9
- data/ext/msgpack/compat.h +0 -99
- data/ext/msgpack/extconf.rb +9 -11
- data/ext/msgpack/factory_class.c +62 -5
- data/ext/msgpack/packer.c +42 -29
- data/ext/msgpack/packer.h +25 -7
- data/ext/msgpack/packer_class.c +23 -20
- data/ext/msgpack/packer_ext_registry.c +13 -4
- data/ext/msgpack/packer_ext_registry.h +10 -5
- data/ext/msgpack/unpacker.c +99 -68
- data/ext/msgpack/unpacker.h +10 -6
- data/ext/msgpack/unpacker_class.c +16 -8
- data/ext/msgpack/unpacker_ext_registry.c +3 -2
- data/ext/msgpack/unpacker_ext_registry.h +5 -2
- data/lib/msgpack/bigint.rb +69 -0
- data/lib/msgpack/factory.rb +103 -0
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +4 -5
- data/msgpack.gemspec +1 -0
- data/spec/bigint_spec.rb +26 -0
- data/spec/factory_spec.rb +248 -0
- data/spec/spec_helper.rb +9 -1
- data/spec/timestamp_spec.rb +2 -2
- data/spec/unpacker_spec.rb +12 -0
- metadata +20 -13
- 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
@@ -12,6 +12,8 @@ import org.jruby.RubyInteger;
|
|
12
12
|
import org.jruby.RubyFixnum;
|
13
13
|
import org.jruby.RubyString;
|
14
14
|
import org.jruby.RubySymbol;
|
15
|
+
import org.jruby.RubyProc;
|
16
|
+
import org.jruby.RubyMethod;
|
15
17
|
import org.jruby.runtime.builtin.IRubyObject;
|
16
18
|
import org.jruby.anno.JRubyClass;
|
17
19
|
import org.jruby.anno.JRubyMethod;
|
@@ -25,14 +27,16 @@ import static org.jruby.runtime.Visibility.PRIVATE;
|
|
25
27
|
public class Factory extends RubyObject {
|
26
28
|
private static final long serialVersionUID = 8441284623445322492L;
|
27
29
|
private final Ruby runtime;
|
28
|
-
private
|
30
|
+
private ExtensionRegistry extensionRegistry;
|
29
31
|
private boolean hasSymbolExtType;
|
32
|
+
private boolean hasBigIntExtType;
|
30
33
|
|
31
34
|
public Factory(Ruby runtime, RubyClass type) {
|
32
35
|
super(runtime, type);
|
33
36
|
this.runtime = runtime;
|
34
37
|
this.extensionRegistry = new ExtensionRegistry();
|
35
38
|
this.hasSymbolExtType = false;
|
39
|
+
this.hasBigIntExtType = false;
|
36
40
|
}
|
37
41
|
|
38
42
|
static class FactoryAllocator implements ObjectAllocator {
|
@@ -50,9 +54,17 @@ public class Factory extends RubyObject {
|
|
50
54
|
return this;
|
51
55
|
}
|
52
56
|
|
53
|
-
@JRubyMethod(name = "
|
57
|
+
@JRubyMethod(name = "dup")
|
58
|
+
public IRubyObject dup() {
|
59
|
+
Factory clone = (Factory)super.dup();
|
60
|
+
clone.extensionRegistry = extensionRegistry();
|
61
|
+
clone.hasSymbolExtType = hasSymbolExtType;
|
62
|
+
return clone;
|
63
|
+
}
|
64
|
+
|
65
|
+
@JRubyMethod(name = "packer", optional = 2)
|
54
66
|
public Packer packer(ThreadContext ctx, IRubyObject[] args) {
|
55
|
-
return Packer.newPacker(ctx, extensionRegistry(), hasSymbolExtType, args);
|
67
|
+
return Packer.newPacker(ctx, extensionRegistry(), hasSymbolExtType, hasBigIntExtType, args);
|
56
68
|
}
|
57
69
|
|
58
70
|
@JRubyMethod(name = "unpacker", optional = 2)
|
@@ -77,6 +89,8 @@ public class Factory extends RubyObject {
|
|
77
89
|
IRubyObject packerArg;
|
78
90
|
IRubyObject unpackerArg;
|
79
91
|
|
92
|
+
RubyHash options = null;
|
93
|
+
|
80
94
|
if (isFrozen()) {
|
81
95
|
throw runtime.newRuntimeError("can't modify frozen Factory");
|
82
96
|
}
|
@@ -86,7 +100,7 @@ public class Factory extends RubyObject {
|
|
86
100
|
unpackerArg = runtime.newSymbol("from_msgpack_ext");
|
87
101
|
} else if (args.length == 3) {
|
88
102
|
if (args[args.length - 1] instanceof RubyHash) {
|
89
|
-
|
103
|
+
options = (RubyHash) args[args.length - 1];
|
90
104
|
packerArg = options.fastARef(runtime.newSymbol("packer"));
|
91
105
|
unpackerArg = options.fastARef(runtime.newSymbol("unpacker"));
|
92
106
|
IRubyObject optimizedSymbolsParsingArg = options.fastARef(runtime.newSymbol("optimized_symbols_parsing"));
|
@@ -118,17 +132,38 @@ public class Factory extends RubyObject {
|
|
118
132
|
if (unpackerArg != null) {
|
119
133
|
if (unpackerArg instanceof RubyString || unpackerArg instanceof RubySymbol) {
|
120
134
|
unpackerProc = extModule.method(unpackerArg.callMethod(ctx, "to_sym"));
|
135
|
+
} else if (unpackerArg instanceof RubyProc || unpackerArg instanceof RubyMethod) {
|
136
|
+
unpackerProc = unpackerArg;
|
121
137
|
} else {
|
122
138
|
unpackerProc = unpackerArg.callMethod(ctx, "method", runtime.newSymbol("call"));
|
123
139
|
}
|
124
140
|
}
|
125
141
|
|
126
|
-
|
142
|
+
boolean recursive = false;
|
143
|
+
if (options != null) {
|
144
|
+
IRubyObject recursiveExtensionArg = options.fastARef(runtime.newSymbol("recursive"));
|
145
|
+
if (recursiveExtensionArg != null && recursiveExtensionArg.isTrue()) {
|
146
|
+
recursive = true;
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
extensionRegistry.put(extModule, (int) typeId, recursive, packerProc, packerArg, unpackerProc, unpackerArg);
|
127
151
|
|
128
152
|
if (extModule == runtime.getSymbol()) {
|
129
153
|
hasSymbolExtType = true;
|
130
154
|
}
|
131
155
|
|
156
|
+
if (options != null) {
|
157
|
+
IRubyObject oversizedIntegerExtensionArg = options.fastARef(runtime.newSymbol("oversized_integer_extension"));
|
158
|
+
if (oversizedIntegerExtensionArg != null && oversizedIntegerExtensionArg.isTrue()) {
|
159
|
+
if (extModule == runtime.getModule("Integer")) {
|
160
|
+
hasBigIntExtType = true;
|
161
|
+
} else {
|
162
|
+
throw runtime.newArgumentError("oversized_integer_extension: true is only for Integer class");
|
163
|
+
}
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
132
167
|
return runtime.getNil();
|
133
168
|
}
|
134
169
|
}
|
@@ -32,17 +32,19 @@ public class Packer extends RubyObject {
|
|
32
32
|
private Buffer buffer;
|
33
33
|
private Encoder encoder;
|
34
34
|
private boolean hasSymbolExtType;
|
35
|
+
private boolean hasBigintExtType;
|
35
36
|
private Encoding binaryEncoding;
|
36
37
|
|
37
|
-
public Packer(Ruby runtime, RubyClass type, ExtensionRegistry registry, boolean hasSymbolExtType) {
|
38
|
+
public Packer(Ruby runtime, RubyClass type, ExtensionRegistry registry, boolean hasSymbolExtType, boolean hasBigintExtType) {
|
38
39
|
super(runtime, type);
|
39
40
|
this.registry = registry;
|
40
41
|
this.hasSymbolExtType = hasSymbolExtType;
|
42
|
+
this.hasBigintExtType = hasBigintExtType;
|
41
43
|
}
|
42
44
|
|
43
45
|
static class PackerAllocator implements ObjectAllocator {
|
44
46
|
public IRubyObject allocate(Ruby runtime, RubyClass type) {
|
45
|
-
return new Packer(runtime, type, null, false);
|
47
|
+
return new Packer(runtime, type, null, false, false);
|
46
48
|
}
|
47
49
|
}
|
48
50
|
|
@@ -50,25 +52,33 @@ public class Packer extends RubyObject {
|
|
50
52
|
public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
|
51
53
|
boolean compatibilityMode = false;
|
52
54
|
Ruby runtime = ctx.runtime;
|
53
|
-
if (args.length > 0
|
54
|
-
RubyHash options =
|
55
|
-
|
56
|
-
|
55
|
+
if (args.length > 0) {
|
56
|
+
RubyHash options = null;
|
57
|
+
if (args[args.length - 1] instanceof RubyHash) {
|
58
|
+
options = (RubyHash) args[args.length - 1];
|
59
|
+
} else if (args.length > 1 && args[args.length - 2] instanceof RubyHash) {
|
60
|
+
options = (RubyHash) args[args.length - 2];
|
61
|
+
}
|
62
|
+
|
63
|
+
if (options != null) {
|
64
|
+
IRubyObject mode = options.fastARef(runtime.newSymbol("compatibility_mode"));
|
65
|
+
compatibilityMode = (mode != null) && mode.isTrue();
|
66
|
+
}
|
57
67
|
}
|
58
68
|
if (registry == null) {
|
59
69
|
// registry is null when allocate -> initialize
|
60
70
|
// registry is already initialized (and somthing might be registered) when newPacker from Factory
|
61
71
|
this.registry = new ExtensionRegistry();
|
62
72
|
}
|
63
|
-
this.encoder = new Encoder(runtime, compatibilityMode, registry, hasSymbolExtType);
|
73
|
+
this.encoder = new Encoder(runtime, this, compatibilityMode, registry, hasSymbolExtType, hasBigintExtType);
|
64
74
|
this.buffer = new Buffer(runtime, runtime.getModule("MessagePack").getClass("Buffer"));
|
65
75
|
this.buffer.initialize(ctx, args);
|
66
76
|
this.binaryEncoding = runtime.getEncodingService().getAscii8bitEncoding();
|
67
77
|
return this;
|
68
78
|
}
|
69
79
|
|
70
|
-
public static Packer newPacker(ThreadContext ctx, ExtensionRegistry extRegistry, boolean hasSymbolExtType, IRubyObject[] args) {
|
71
|
-
Packer packer = new Packer(ctx.runtime, ctx.runtime.getModule("MessagePack").getClass("Packer"), extRegistry, hasSymbolExtType);
|
80
|
+
public static Packer newPacker(ThreadContext ctx, ExtensionRegistry extRegistry, boolean hasSymbolExtType, boolean hasBigintExtType, IRubyObject[] args) {
|
81
|
+
Packer packer = new Packer(ctx.runtime, ctx.runtime.getModule("MessagePack").getClass("Packer"), extRegistry, hasSymbolExtType, hasBigintExtType);
|
72
82
|
packer.initialize(ctx, args);
|
73
83
|
return packer;
|
74
84
|
}
|
@@ -114,7 +124,7 @@ public class Packer extends RubyObject {
|
|
114
124
|
}
|
115
125
|
RubyModule extModule = (RubyModule) mod;
|
116
126
|
|
117
|
-
registry.put(extModule, (int) typeId, proc, arg, null, null);
|
127
|
+
registry.put(extModule, (int) typeId, false, proc, arg, null, null);
|
118
128
|
|
119
129
|
if (extModule == runtime.getSymbol()) {
|
120
130
|
encoder.hasSymbolExtType = true;
|
@@ -257,7 +267,7 @@ public class Packer extends RubyObject {
|
|
257
267
|
return buffer.size(ctx);
|
258
268
|
}
|
259
269
|
|
260
|
-
@JRubyMethod(name = "clear")
|
270
|
+
@JRubyMethod(name = "clear", alias = { "reset" })
|
261
271
|
public IRubyObject clear(ThreadContext ctx) {
|
262
272
|
return buffer.clear(ctx);
|
263
273
|
}
|
@@ -56,30 +56,48 @@ public class Unpacker extends RubyObject {
|
|
56
56
|
|
57
57
|
@JRubyMethod(name = "initialize", optional = 2, visibility = PRIVATE)
|
58
58
|
public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
|
59
|
+
Ruby runtime = ctx.runtime;
|
60
|
+
|
59
61
|
symbolizeKeys = false;
|
60
62
|
allowUnknownExt = false;
|
61
63
|
freeze = false;
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
64
|
+
|
65
|
+
IRubyObject io = null;
|
66
|
+
RubyHash options = null;
|
67
|
+
|
68
|
+
if (args.length >= 1) {
|
69
|
+
io = args[0];
|
70
|
+
}
|
71
|
+
|
72
|
+
if (args.length >= 2 && args[1] != runtime.getNil()) {
|
73
|
+
options = (RubyHash)args[1];
|
74
|
+
}
|
75
|
+
|
76
|
+
if (options == null && io != null && io instanceof RubyHash) {
|
77
|
+
options = (RubyHash)io;
|
78
|
+
io = null;
|
79
|
+
}
|
80
|
+
|
81
|
+
if (options != null) {
|
82
|
+
IRubyObject sk = options.fastARef(runtime.newSymbol("symbolize_keys"));
|
83
|
+
if (sk != null) {
|
84
|
+
symbolizeKeys = sk.isTrue();
|
78
85
|
}
|
79
|
-
|
80
|
-
|
86
|
+
IRubyObject f = options.fastARef(runtime.newSymbol("freeze"));
|
87
|
+
if (f != null) {
|
88
|
+
freeze = f.isTrue();
|
81
89
|
}
|
90
|
+
IRubyObject au = options.fastARef(runtime.newSymbol("allow_unknown_ext"));
|
91
|
+
if (au != null) {
|
92
|
+
allowUnknownExt = au.isTrue();
|
93
|
+
}
|
94
|
+
|
82
95
|
}
|
96
|
+
|
97
|
+
if (io != null && io != runtime.getNil()) {
|
98
|
+
setStream(ctx, io);
|
99
|
+
}
|
100
|
+
|
83
101
|
return this;
|
84
102
|
}
|
85
103
|
|
@@ -139,7 +157,7 @@ public class Unpacker extends RubyObject {
|
|
139
157
|
throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
|
140
158
|
}
|
141
159
|
|
142
|
-
registry.put(extModule, (int) typeId, null, null, proc, arg);
|
160
|
+
registry.put(extModule, (int) typeId, false, null, null, proc, arg);
|
143
161
|
return runtime.getNil();
|
144
162
|
}
|
145
163
|
|
@@ -157,7 +175,7 @@ public class Unpacker extends RubyObject {
|
|
157
175
|
if (limit == -1) {
|
158
176
|
limit = byteList.length() - offset;
|
159
177
|
}
|
160
|
-
Decoder decoder = new Decoder(ctx.runtime,
|
178
|
+
Decoder decoder = new Decoder(ctx.runtime, this, byteList.unsafeBytes(), byteList.begin() + offset, limit, symbolizeKeys, freeze, allowUnknownExt);
|
161
179
|
try {
|
162
180
|
data = null;
|
163
181
|
data = decoder.next();
|
@@ -187,7 +205,7 @@ public class Unpacker extends RubyObject {
|
|
187
205
|
public IRubyObject feed(ThreadContext ctx, IRubyObject data) {
|
188
206
|
ByteList byteList = data.asString().getByteList();
|
189
207
|
if (decoder == null) {
|
190
|
-
decoder = new Decoder(ctx.runtime,
|
208
|
+
decoder = new Decoder(ctx.runtime, this, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
|
191
209
|
} else {
|
192
210
|
decoder.feed(byteList.unsafeBytes(), byteList.begin(), byteList.length());
|
193
211
|
}
|
@@ -325,7 +343,11 @@ public class Unpacker extends RubyObject {
|
|
325
343
|
ByteList byteList = str.getByteList();
|
326
344
|
this.stream = stream;
|
327
345
|
this.decoder = null;
|
328
|
-
this.decoder = new Decoder(ctx.runtime,
|
346
|
+
this.decoder = new Decoder(ctx.runtime, this, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
|
329
347
|
return getStream(ctx);
|
330
348
|
}
|
349
|
+
|
350
|
+
public ExtensionRegistry.ExtensionEntry lookupExtensionByTypeId(int typeId) {
|
351
|
+
return registry.lookupExtensionByTypeId(typeId);
|
352
|
+
}
|
331
353
|
}
|
data/ext/msgpack/buffer.c
CHANGED
@@ -300,30 +300,6 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
|
|
300
300
|
}
|
301
301
|
}
|
302
302
|
|
303
|
-
static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE string)
|
304
|
-
{
|
305
|
-
VALUE mapped_string = rb_str_dup(string);
|
306
|
-
ENCODING_SET(mapped_string, msgpack_rb_encindex_ascii8bit);
|
307
|
-
|
308
|
-
_msgpack_buffer_add_new_chunk(b);
|
309
|
-
|
310
|
-
char* data = RSTRING_PTR(mapped_string);
|
311
|
-
size_t length = RSTRING_LEN(mapped_string);
|
312
|
-
|
313
|
-
b->tail.first = (char*) data;
|
314
|
-
b->tail.last = (char*) data + length;
|
315
|
-
b->tail.mapped_string = mapped_string;
|
316
|
-
b->tail.mem = NULL;
|
317
|
-
|
318
|
-
/* msgpack_buffer_writable_size should return 0 for mapped chunk */
|
319
|
-
b->tail_buffer_end = b->tail.last;
|
320
|
-
|
321
|
-
/* consider read_buffer */
|
322
|
-
if(b->head == &b->tail) {
|
323
|
-
b->read_buffer = b->tail.first;
|
324
|
-
}
|
325
|
-
}
|
326
|
-
|
327
303
|
void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
|
328
304
|
{
|
329
305
|
size_t length = RSTRING_LEN(string);
|
@@ -332,16 +308,9 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
|
|
332
308
|
msgpack_buffer_flush(b);
|
333
309
|
if (ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit) {
|
334
310
|
rb_funcall(b->io, b->io_write_all_method, 1, string);
|
335
|
-
} else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
|
336
|
-
VALUE s = rb_str_dup(string);
|
337
|
-
ENCODING_SET(s, msgpack_rb_encindex_ascii8bit);
|
338
|
-
rb_funcall(b->io, b->io_write_all_method, 1, s);
|
339
311
|
} else {
|
340
312
|
msgpack_buffer_append(b, RSTRING_PTR(string), length);
|
341
313
|
}
|
342
|
-
} else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
|
343
|
-
_msgpack_buffer_append_reference(b, string);
|
344
|
-
|
345
314
|
} else {
|
346
315
|
msgpack_buffer_append(b, RSTRING_PTR(string), length);
|
347
316
|
}
|
@@ -619,13 +588,13 @@ size_t msgpack_buffer_flush_to_io(msgpack_buffer_t* b, VALUE io, ID write_method
|
|
619
588
|
size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
|
620
589
|
{
|
621
590
|
if(b->io_buffer == Qnil) {
|
622
|
-
b->io_buffer = rb_funcall(b->io, b->io_partial_read_method, 1,
|
591
|
+
b->io_buffer = rb_funcall(b->io, b->io_partial_read_method, 1, SIZET2NUM(b->io_buffer_size));
|
623
592
|
if(b->io_buffer == Qnil) {
|
624
593
|
rb_raise(rb_eEOFError, "IO reached end of file");
|
625
594
|
}
|
626
595
|
StringValue(b->io_buffer);
|
627
596
|
} else {
|
628
|
-
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2,
|
597
|
+
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(b->io_buffer_size), b->io_buffer);
|
629
598
|
if(ret == Qnil) {
|
630
599
|
rb_raise(rb_eEOFError, "IO reached end of file");
|
631
600
|
}
|
@@ -644,9 +613,11 @@ size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
|
|
644
613
|
|
645
614
|
size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string, size_t length)
|
646
615
|
{
|
616
|
+
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
617
|
+
|
647
618
|
if(RSTRING_LEN(string) == 0) {
|
648
619
|
/* direct read */
|
649
|
-
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2,
|
620
|
+
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(MIN(b->io_buffer_size, length)), string);
|
650
621
|
if(ret == Qnil) {
|
651
622
|
return 0;
|
652
623
|
}
|
@@ -658,7 +629,7 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
|
|
658
629
|
b->io_buffer = rb_str_buf_new(0);
|
659
630
|
}
|
660
631
|
|
661
|
-
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2,
|
632
|
+
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(MIN(b->io_buffer_size, length)), b->io_buffer);
|
662
633
|
if(ret == Qnil) {
|
663
634
|
return 0;
|
664
635
|
}
|
@@ -666,6 +637,8 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
|
|
666
637
|
|
667
638
|
rb_str_buf_cat(string, (const void*)RSTRING_PTR(b->io_buffer), rl);
|
668
639
|
return rl;
|
640
|
+
|
641
|
+
#undef MIN
|
669
642
|
}
|
670
643
|
|
671
644
|
size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
|
@@ -674,7 +647,7 @@ size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
|
|
674
647
|
b->io_buffer = rb_str_buf_new(0);
|
675
648
|
}
|
676
649
|
|
677
|
-
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2,
|
650
|
+
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(length), b->io_buffer);
|
678
651
|
if(ret == Qnil) {
|
679
652
|
return 0;
|
680
653
|
}
|
data/ext/msgpack/buffer.h
CHANGED
@@ -49,6 +49,10 @@
|
|
49
49
|
|
50
50
|
#define NO_MAPPED_STRING ((VALUE)0)
|
51
51
|
|
52
|
+
#ifndef RB_ENC_INTERNED_STR_NULL_CHECK
|
53
|
+
#define RB_ENC_INTERNED_STR_NULL_CHECK 0
|
54
|
+
#endif
|
55
|
+
|
52
56
|
extern int msgpack_rb_encindex_utf8;
|
53
57
|
extern int msgpack_rb_encindex_usascii;
|
54
58
|
extern int msgpack_rb_encindex_ascii8bit;
|
@@ -456,7 +460,11 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
|
|
456
460
|
|
457
461
|
#ifdef HAVE_RB_ENC_INTERNED_STR
|
458
462
|
if (will_be_frozen) {
|
459
|
-
|
463
|
+
if (RB_ENC_INTERNED_STR_NULL_CHECK && length == 0) {
|
464
|
+
result = rb_enc_interned_str("", length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
|
465
|
+
} else {
|
466
|
+
result = rb_enc_interned_str(b->read_buffer, length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
|
467
|
+
}
|
460
468
|
} else {
|
461
469
|
if (utf8) {
|
462
470
|
result = rb_utf8_str_new(b->read_buffer, length);
|
data/ext/msgpack/buffer_class.c
CHANGED
@@ -29,6 +29,11 @@ static ID s_write;
|
|
29
29
|
static ID s_append;
|
30
30
|
static ID s_close;
|
31
31
|
|
32
|
+
static VALUE sym_read_reference_threshold;
|
33
|
+
static VALUE sym_write_reference_threshold;
|
34
|
+
static VALUE sym_io_buffer_size;
|
35
|
+
|
36
|
+
|
32
37
|
#define BUFFER(from, name) \
|
33
38
|
msgpack_buffer_t *name = NULL; \
|
34
39
|
Data_Get_Struct(from, msgpack_buffer_t, name); \
|
@@ -89,19 +94,19 @@ void MessagePack_Buffer_set_options(msgpack_buffer_t* b, VALUE io, VALUE options
|
|
89
94
|
if(options != Qnil) {
|
90
95
|
VALUE v;
|
91
96
|
|
92
|
-
v = rb_hash_aref(options,
|
97
|
+
v = rb_hash_aref(options, sym_read_reference_threshold);
|
93
98
|
if(v != Qnil) {
|
94
|
-
msgpack_buffer_set_read_reference_threshold(b,
|
99
|
+
msgpack_buffer_set_read_reference_threshold(b, NUM2SIZET(v));
|
95
100
|
}
|
96
101
|
|
97
|
-
v = rb_hash_aref(options,
|
102
|
+
v = rb_hash_aref(options, sym_write_reference_threshold);
|
98
103
|
if(v != Qnil) {
|
99
|
-
msgpack_buffer_set_write_reference_threshold(b,
|
104
|
+
msgpack_buffer_set_write_reference_threshold(b, NUM2SIZET(v));
|
100
105
|
}
|
101
106
|
|
102
|
-
v = rb_hash_aref(options,
|
107
|
+
v = rb_hash_aref(options, sym_io_buffer_size);
|
103
108
|
if(v != Qnil) {
|
104
|
-
msgpack_buffer_set_io_buffer_size(b,
|
109
|
+
msgpack_buffer_set_io_buffer_size(b, NUM2SIZET(v));
|
105
110
|
}
|
106
111
|
}
|
107
112
|
}
|
@@ -296,11 +301,11 @@ static VALUE Buffer_skip(VALUE self, VALUE sn)
|
|
296
301
|
|
297
302
|
/* do nothing */
|
298
303
|
if(n == 0) {
|
299
|
-
return
|
304
|
+
return INT2NUM(0);
|
300
305
|
}
|
301
306
|
|
302
307
|
size_t sz = read_until_eof(b, Qnil, n);
|
303
|
-
return
|
308
|
+
return SIZET2NUM(sz);
|
304
309
|
}
|
305
310
|
|
306
311
|
static VALUE Buffer_skip_all(VALUE self, VALUE sn)
|
@@ -468,7 +473,7 @@ static VALUE Buffer_write_to(VALUE self, VALUE io)
|
|
468
473
|
{
|
469
474
|
BUFFER(self, b);
|
470
475
|
size_t sz = msgpack_buffer_flush_to_io(b, io, s_write, true);
|
471
|
-
return
|
476
|
+
return SIZET2NUM(sz);
|
472
477
|
}
|
473
478
|
|
474
479
|
void MessagePack_Buffer_module_init(VALUE mMessagePack)
|
@@ -479,6 +484,10 @@ void MessagePack_Buffer_module_init(VALUE mMessagePack)
|
|
479
484
|
s_append = rb_intern("<<");
|
480
485
|
s_close = rb_intern("close");
|
481
486
|
|
487
|
+
sym_read_reference_threshold = ID2SYM(rb_intern("read_reference_threshold"));
|
488
|
+
sym_write_reference_threshold = ID2SYM(rb_intern("write_reference_threshold"));
|
489
|
+
sym_io_buffer_size = ID2SYM(rb_intern("io_buffer_size"));
|
490
|
+
|
482
491
|
msgpack_buffer_static_init();
|
483
492
|
|
484
493
|
cMessagePack_Buffer = rb_define_class_under(mMessagePack, "Buffer", rb_cObject);
|
data/ext/msgpack/compat.h
CHANGED
@@ -22,104 +22,5 @@
|
|
22
22
|
#include "ruby.h"
|
23
23
|
#include "ruby/encoding.h"
|
24
24
|
|
25
|
-
#if defined(HAVE_RUBY_ST_H)
|
26
|
-
# include "ruby/st.h" /* ruby hash on Ruby 1.9 */
|
27
|
-
#elif defined(HAVE_ST_H)
|
28
|
-
# include "st.h" /* ruby hash on Ruby 1.8 */
|
29
|
-
#endif
|
30
|
-
|
31
|
-
|
32
|
-
/*
|
33
|
-
* ZALLOC_N (ruby 2.2 or later)
|
34
|
-
*/
|
35
|
-
#ifndef RB_ZALLOC_N
|
36
|
-
# define RB_ZALLOC_N(type,n) ((type*)ruby_xcalloc((size_t)(n),sizeof(type)))
|
37
|
-
#endif
|
38
|
-
#ifndef ZALLOC_N
|
39
|
-
# define ZALLOC_N(type,n) RB_ZALLOC_N(type,n)
|
40
|
-
#endif
|
41
|
-
|
42
|
-
|
43
|
-
/*
|
44
|
-
* define STR_DUP_LIKELY_DOES_COPY
|
45
|
-
* check rb_str_dup actually copies the string or not
|
46
|
-
*/
|
47
|
-
#if defined(RUBY_VM) && defined(FL_ALL) && defined(FL_USER1) && defined(FL_USER3) /* MRI 1.9 */
|
48
|
-
# define STR_DUP_LIKELY_DOES_COPY(str) FL_ALL(str, FL_USER1|FL_USER3) /* same as STR_ASSOC_P(str) */
|
49
|
-
|
50
|
-
#elif defined(FL_TEST) && defined(ELTS_SHARED) /* MRI 1.8 */
|
51
|
-
# define STR_DUP_LIKELY_DOES_COPY(str) (!FL_TEST(str, ELTS_SHARED))
|
52
|
-
|
53
|
-
//#elif defined(RUBINIUS) || defined(JRUBY) /* Rubinius and JRuby */
|
54
|
-
#else
|
55
|
-
# define STR_DUP_LIKELY_DOES_COPY(str) (1)
|
56
|
-
|
57
|
-
#endif
|
58
|
-
|
59
|
-
|
60
|
-
/*
|
61
|
-
* SIZET2NUM
|
62
|
-
*/
|
63
|
-
#ifndef SIZET2NUM /* MRI 1.8 */
|
64
|
-
# define SIZET2NUM(v) ULL2NUM(v)
|
65
|
-
#endif
|
66
|
-
|
67
|
-
|
68
|
-
/*
|
69
|
-
* rb_errinfo()
|
70
|
-
*/
|
71
|
-
#if defined(RUBY_VM) /* MRI 1.9 */
|
72
|
-
# define COMPAT_RERAISE rb_exc_raise(rb_errinfo())
|
73
|
-
|
74
|
-
#elif defined(JRUBY) /* JRuby */
|
75
|
-
# define COMPAT_RERAISE rb_exc_raise(rb_gv_get("$!"))
|
76
|
-
|
77
|
-
#else /* MRI 1.8 and Rubinius */
|
78
|
-
# define COMPAT_RERAISE rb_exc_raise(ruby_errinfo)
|
79
|
-
#endif
|
80
|
-
|
81
|
-
|
82
|
-
/*
|
83
|
-
* RBIGNUM_POSITIVE_P
|
84
|
-
*/
|
85
|
-
#ifndef RBIGNUM_POSITIVE_P
|
86
|
-
# if defined(RUBINIUS) /* Rubinius <= v1.2.3 */
|
87
|
-
# define RBIGNUM_POSITIVE_P(b) (rb_funcall(b, rb_intern(">="), 1, INT2FIX(0)) == Qtrue)
|
88
|
-
|
89
|
-
# elif defined(JRUBY) /* JRuby */
|
90
|
-
# define RBIGNUM_POSITIVE_P(b) (rb_funcall(b, rb_intern(">="), 1, INT2FIX(0)) == Qtrue)
|
91
|
-
# define rb_big2ull(b) rb_num2ull(b)
|
92
|
-
/*#define rb_big2ll(b) rb_num2ll(b)*/
|
93
|
-
|
94
|
-
# else /* MRI 1.8 */
|
95
|
-
# define RBIGNUM_POSITIVE_P(b) (RBIGNUM(b)->sign)
|
96
|
-
# endif
|
97
|
-
#endif
|
98
|
-
|
99
|
-
|
100
|
-
/*
|
101
|
-
* RSTRING_PTR, RSTRING_LEN
|
102
|
-
*/
|
103
|
-
#ifndef RSTRING_PTR /* MRI 1.8.5 */
|
104
|
-
# define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
105
|
-
#endif
|
106
|
-
|
107
|
-
#ifndef RSTRING_LEN /* MRI 1.8.5 */
|
108
|
-
# define RSTRING_LEN(s) (RSTRING(s)->len)
|
109
|
-
#endif
|
110
|
-
|
111
|
-
|
112
|
-
/*
|
113
|
-
* RSTRUCT_GET
|
114
|
-
*/
|
115
|
-
#ifndef RSTRUCT_GET
|
116
|
-
# ifdef RSTRUCT_PTR /* MRI <= 2.0.0 */
|
117
|
-
# define RSTRUCT_GET(st, idx) (RSTRUCT_PTR(st)[idx])
|
118
|
-
# else /* Rubinius */
|
119
|
-
# define RSTRUCT_GET(st, idx) (rb_struct_aref(st, INT2FIX(idx)))
|
120
|
-
# endif
|
121
|
-
#endif
|
122
|
-
|
123
|
-
|
124
25
|
#endif
|
125
26
|
|
data/ext/msgpack/extconf.rb
CHANGED
@@ -2,24 +2,23 @@ require 'mkmf'
|
|
2
2
|
|
3
3
|
have_header("ruby/st.h")
|
4
4
|
have_header("st.h")
|
5
|
-
have_func("rb_enc_interned_str", "ruby.h")
|
5
|
+
have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
|
6
|
+
have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
|
6
7
|
|
7
8
|
unless RUBY_PLATFORM.include? 'mswin'
|
8
|
-
$CFLAGS << %[ -I.. -Wall -O3
|
9
|
+
$CFLAGS << %[ -I.. -Wall -O3 #{RbConfig::CONFIG["debugflags"]} -std=gnu99]
|
9
10
|
end
|
10
11
|
#$CFLAGS << %[ -DDISABLE_RMEM]
|
11
12
|
#$CFLAGS << %[ -DDISABLE_RMEM_REUSE_INTERNAL_FRAGMENT]
|
12
13
|
#$CFLAGS << %[ -DDISABLE_BUFFER_READ_REFERENCE_OPTIMIZE]
|
13
14
|
#$CFLAGS << %[ -DDISABLE_BUFFER_READ_TO_S_OPTIMIZE]
|
14
15
|
|
15
|
-
if
|
16
|
-
#
|
17
|
-
$CFLAGS <<
|
18
|
-
# Rubinius C extensions don't grab GVL while rmem is not thread safe
|
19
|
-
$CFLAGS << %[ -DDISABLE_RMEM]
|
16
|
+
if RUBY_VERSION.start_with?('3.0.')
|
17
|
+
# https://bugs.ruby-lang.org/issues/18772
|
18
|
+
$CFLAGS << ' -DRB_ENC_INTERNED_STR_NULL_CHECK=1 '
|
20
19
|
end
|
21
20
|
|
22
|
-
# checking if Hash#[]= (rb_hash_aset) dedupes string keys
|
21
|
+
# checking if Hash#[]= (rb_hash_aset) dedupes string keys (Ruby 2.6+)
|
23
22
|
h = {}
|
24
23
|
x = {}
|
25
24
|
r = rand.to_s
|
@@ -32,7 +31,7 @@ else
|
|
32
31
|
end
|
33
32
|
|
34
33
|
|
35
|
-
# checking if String#-@ (str_uminus) dedupes... '
|
34
|
+
# checking if String#-@ (str_uminus) dedupes... ' (Ruby 2.5+)
|
36
35
|
begin
|
37
36
|
a = -(%w(t e s t).join)
|
38
37
|
b = -(%w(t e s t).join)
|
@@ -45,7 +44,7 @@ rescue NoMethodError
|
|
45
44
|
$CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
|
46
45
|
end
|
47
46
|
|
48
|
-
# checking if String#-@ (str_uminus) directly interns frozen strings... '
|
47
|
+
# checking if String#-@ (str_uminus) directly interns frozen strings... ' (Ruby 3.0+)
|
49
48
|
begin
|
50
49
|
s = rand.to_s.freeze
|
51
50
|
if (-s).equal?(s) && (-s.dup).equal?(s)
|
@@ -62,4 +61,3 @@ if warnflags = CONFIG['warnflags']
|
|
62
61
|
end
|
63
62
|
|
64
63
|
create_makefile('msgpack/msgpack')
|
65
|
-
|