msgpack 1.7.0 → 1.7.2
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/ChangeLog +11 -0
- data/ext/java/org/msgpack/jruby/Buffer.java +3 -3
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +7 -11
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +1 -1
- data/ext/java/org/msgpack/jruby/Factory.java +11 -50
- data/ext/java/org/msgpack/jruby/Packer.java +9 -27
- data/ext/java/org/msgpack/jruby/Unpacker.java +15 -35
- data/ext/msgpack/buffer.c +7 -5
- data/ext/msgpack/buffer.h +3 -1
- data/ext/msgpack/buffer_class.c +72 -1
- data/ext/msgpack/buffer_class.h +1 -0
- data/ext/msgpack/extconf.rb +16 -12
- data/ext/msgpack/factory_class.c +27 -61
- data/ext/msgpack/packer.c +12 -14
- data/ext/msgpack/packer.h +0 -4
- data/ext/msgpack/packer_class.c +12 -37
- data/ext/msgpack/packer_ext_registry.c +31 -28
- data/ext/msgpack/packer_ext_registry.h +10 -14
- data/ext/msgpack/unpacker.c +9 -10
- data/ext/msgpack/unpacker_class.c +5 -30
- data/ext/msgpack/unpacker_ext_registry.c +4 -16
- data/ext/msgpack/unpacker_ext_registry.h +3 -7
- data/lib/msgpack/factory.rb +49 -10
- data/lib/msgpack/packer.rb +6 -1
- data/lib/msgpack/unpacker.rb +10 -1
- data/lib/msgpack/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f5b1af6b3a51f5ccc6bcf67c94c1fc6193b02fe01b123e2cfb06a6df9607116
|
4
|
+
data.tar.gz: cc057f24e1ffa4cdc3e331499eb04de4c2383b0657dcf0baeba08300fd20862e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3eb06321a534ca9b16e321cc4a71458532578dafe7967314a662223b1fbf4aa93449c98177fa982aa532ce3732ddda4a6d497704df0e9c874da07f378c73595c
|
7
|
+
data.tar.gz: 8e540755e3db9e21d7dfa4354854e8b0486f5a1bbf82c3994c6095022205f7873153d364df9310d8072c481de38ca2b4c3e088e4221c3451ceb9438312489419
|
data/ChangeLog
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
2023-07-18 1.7.2:
|
2
|
+
|
3
|
+
* Fix a potential GC bug when packing data using recursive extensions and buffers containing over 512KkiB of data (See #341).
|
4
|
+
* Fix a regression where feeding an empty string to an Unpacker would be considered like the end of the buffer.
|
5
|
+
|
6
|
+
2023-05-19 1.7.1:
|
7
|
+
|
8
|
+
* Fix JRuby 9.4 compatibility.
|
9
|
+
* Fix compilation on older compilers (gcc 4.x).
|
10
|
+
* Fix an infinite recursion issue when registering a Symbol type with a `nil` packer.
|
11
|
+
|
1
12
|
2023-03-29 1.7.0:
|
2
13
|
|
3
14
|
* Fix a possible double-free issue when GC triggers inside `_msgpack_rmem_alloc2`.
|
@@ -22,10 +22,10 @@ import org.jcodings.Encoding;
|
|
22
22
|
@JRubyClass(name="MessagePack::Buffer")
|
23
23
|
public class Buffer extends RubyObject {
|
24
24
|
private static final long serialVersionUID = 8441244627425629412L;
|
25
|
-
private IRubyObject io;
|
26
|
-
private ByteBuffer buffer;
|
25
|
+
private transient IRubyObject io;
|
26
|
+
private transient ByteBuffer buffer;
|
27
27
|
private boolean writeMode;
|
28
|
-
private Encoding binaryEncoding;
|
28
|
+
private transient Encoding binaryEncoding;
|
29
29
|
|
30
30
|
private static final int CACHE_LINE_SIZE = 64;
|
31
31
|
private static final int ARRAY_HEADER_SIZE = 24;
|
@@ -54,8 +54,8 @@ public class ExtensionRegistry {
|
|
54
54
|
return hash;
|
55
55
|
}
|
56
56
|
|
57
|
-
public void put(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject
|
58
|
-
ExtensionEntry entry = new ExtensionEntry(mod, typeId, recursive, packerProc,
|
57
|
+
public void put(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject unpackerProc) {
|
58
|
+
ExtensionEntry entry = new ExtensionEntry(mod, typeId, recursive, packerProc, unpackerProc);
|
59
59
|
extensionsByModule.put(mod, entry);
|
60
60
|
extensionsByTypeId[typeId + 128] = entry;
|
61
61
|
extensionsByAncestor.clear();
|
@@ -114,18 +114,14 @@ public class ExtensionRegistry {
|
|
114
114
|
private final int typeId;
|
115
115
|
private final boolean recursive;
|
116
116
|
private final IRubyObject packerProc;
|
117
|
-
private final IRubyObject packerArg;
|
118
117
|
private final IRubyObject unpackerProc;
|
119
|
-
private final IRubyObject unpackerArg;
|
120
118
|
|
121
|
-
public ExtensionEntry(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject
|
119
|
+
public ExtensionEntry(RubyModule mod, int typeId, boolean recursive, IRubyObject packerProc, IRubyObject unpackerProc) {
|
122
120
|
this.mod = mod;
|
123
121
|
this.typeId = typeId;
|
124
122
|
this.recursive = recursive;
|
125
123
|
this.packerProc = packerProc;
|
126
|
-
this.packerArg = packerArg;
|
127
124
|
this.unpackerProc = unpackerProc;
|
128
|
-
this.unpackerArg = unpackerArg;
|
129
125
|
}
|
130
126
|
|
131
127
|
public RubyModule getExtensionModule() {
|
@@ -141,11 +137,11 @@ public class ExtensionRegistry {
|
|
141
137
|
}
|
142
138
|
|
143
139
|
public boolean hasPacker() {
|
144
|
-
return packerProc != null;
|
140
|
+
return packerProc != null && !packerProc.isNil();
|
145
141
|
}
|
146
142
|
|
147
143
|
public boolean hasUnpacker() {
|
148
|
-
return unpackerProc != null;
|
144
|
+
return unpackerProc != null && !unpackerProc.isNil();
|
149
145
|
}
|
150
146
|
|
151
147
|
public IRubyObject getPackerProc() {
|
@@ -157,11 +153,11 @@ public class ExtensionRegistry {
|
|
157
153
|
}
|
158
154
|
|
159
155
|
public RubyArray<?> toPackerTuple(ThreadContext ctx) {
|
160
|
-
return ctx.runtime.newArray(new IRubyObject[] {ctx.runtime.newFixnum(typeId), packerProc
|
156
|
+
return ctx.runtime.newArray(new IRubyObject[] {ctx.runtime.newFixnum(typeId), packerProc});
|
161
157
|
}
|
162
158
|
|
163
159
|
public RubyArray<?> toUnpackerTuple(ThreadContext ctx) {
|
164
|
-
return ctx.runtime.newArray(new IRubyObject[] {mod, unpackerProc
|
160
|
+
return ctx.runtime.newArray(new IRubyObject[] {mod, unpackerProc});
|
165
161
|
}
|
166
162
|
|
167
163
|
public IRubyObject[] toPackerProcTypeIdPair(ThreadContext ctx) {
|
@@ -26,7 +26,7 @@ import static org.msgpack.jruby.Types.*;
|
|
26
26
|
@JRubyClass(name="MessagePack::ExtensionValue")
|
27
27
|
public class ExtensionValue extends RubyObject {
|
28
28
|
private static final long serialVersionUID = 8451274621449322492L;
|
29
|
-
private final Encoding binaryEncoding;
|
29
|
+
private transient final Encoding binaryEncoding;
|
30
30
|
|
31
31
|
private RubyFixnum type;
|
32
32
|
private RubyString payload;
|
@@ -26,8 +26,8 @@ import static org.jruby.runtime.Visibility.PRIVATE;
|
|
26
26
|
@JRubyClass(name="MessagePack::Factory")
|
27
27
|
public class Factory extends RubyObject {
|
28
28
|
private static final long serialVersionUID = 8441284623445322492L;
|
29
|
-
private final Ruby runtime;
|
30
|
-
private ExtensionRegistry extensionRegistry;
|
29
|
+
private transient final Ruby runtime;
|
30
|
+
private transient ExtensionRegistry extensionRegistry;
|
31
31
|
private boolean hasSymbolExtType;
|
32
32
|
private boolean hasBigIntExtType;
|
33
33
|
|
@@ -80,39 +80,15 @@ public class Factory extends RubyObject {
|
|
80
80
|
});
|
81
81
|
}
|
82
82
|
|
83
|
-
@JRubyMethod(name = "
|
84
|
-
public IRubyObject
|
85
|
-
|
86
|
-
IRubyObject type = args[0];
|
87
|
-
IRubyObject mod = args[1];
|
88
|
-
|
89
|
-
IRubyObject packerArg;
|
90
|
-
IRubyObject unpackerArg;
|
91
|
-
|
92
|
-
RubyHash options = null;
|
83
|
+
@JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
|
84
|
+
public IRubyObject registerTypeInternal(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject opts) {
|
85
|
+
testFrozen("MessagePack::Factory");
|
93
86
|
|
94
|
-
|
95
|
-
|
96
|
-
}
|
87
|
+
Ruby runtime = ctx.runtime;
|
88
|
+
RubyHash options = (RubyHash) opts;
|
97
89
|
|
98
|
-
|
99
|
-
|
100
|
-
unpackerArg = runtime.newSymbol("from_msgpack_ext");
|
101
|
-
} else if (args.length == 3) {
|
102
|
-
if (args[args.length - 1] instanceof RubyHash) {
|
103
|
-
options = (RubyHash) args[args.length - 1];
|
104
|
-
packerArg = options.fastARef(runtime.newSymbol("packer"));
|
105
|
-
unpackerArg = options.fastARef(runtime.newSymbol("unpacker"));
|
106
|
-
IRubyObject optimizedSymbolsParsingArg = options.fastARef(runtime.newSymbol("optimized_symbols_parsing"));
|
107
|
-
if (optimizedSymbolsParsingArg != null && optimizedSymbolsParsingArg.isTrue()) {
|
108
|
-
throw runtime.newArgumentError("JRuby implementation does not support the optimized_symbols_parsing option");
|
109
|
-
}
|
110
|
-
} else {
|
111
|
-
throw runtime.newArgumentError(String.format("expected Hash but found %s.", args[args.length - 1].getType().getName()));
|
112
|
-
}
|
113
|
-
} else {
|
114
|
-
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
|
115
|
-
}
|
90
|
+
IRubyObject packerProc = options.fastARef(runtime.newSymbol("packer"));
|
91
|
+
IRubyObject unpackerProc = options.fastARef(runtime.newSymbol("unpacker"));
|
116
92
|
|
117
93
|
long typeId = ((RubyFixnum) type).getLongValue();
|
118
94
|
if (typeId < -128 || typeId > 127) {
|
@@ -124,21 +100,6 @@ public class Factory extends RubyObject {
|
|
124
100
|
}
|
125
101
|
RubyModule extModule = (RubyModule) mod;
|
126
102
|
|
127
|
-
IRubyObject packerProc = runtime.getNil();
|
128
|
-
IRubyObject unpackerProc = runtime.getNil();
|
129
|
-
if (packerArg != null) {
|
130
|
-
packerProc = packerArg.callMethod(ctx, "to_proc");
|
131
|
-
}
|
132
|
-
if (unpackerArg != null) {
|
133
|
-
if (unpackerArg instanceof RubyString || unpackerArg instanceof RubySymbol) {
|
134
|
-
unpackerProc = extModule.method(unpackerArg.callMethod(ctx, "to_sym"));
|
135
|
-
} else if (unpackerArg instanceof RubyProc || unpackerArg instanceof RubyMethod) {
|
136
|
-
unpackerProc = unpackerArg;
|
137
|
-
} else {
|
138
|
-
unpackerProc = unpackerArg.callMethod(ctx, "method", runtime.newSymbol("call"));
|
139
|
-
}
|
140
|
-
}
|
141
|
-
|
142
103
|
boolean recursive = false;
|
143
104
|
if (options != null) {
|
144
105
|
IRubyObject recursiveExtensionArg = options.fastARef(runtime.newSymbol("recursive"));
|
@@ -147,9 +108,9 @@ public class Factory extends RubyObject {
|
|
147
108
|
}
|
148
109
|
}
|
149
110
|
|
150
|
-
extensionRegistry.put(extModule, (int) typeId, recursive, packerProc,
|
111
|
+
extensionRegistry.put(extModule, (int) typeId, recursive, packerProc, unpackerProc);
|
151
112
|
|
152
|
-
if (extModule == runtime.getSymbol()) {
|
113
|
+
if (extModule == runtime.getSymbol() && !packerProc.isNil()) {
|
153
114
|
hasSymbolExtType = true;
|
154
115
|
}
|
155
116
|
|
@@ -28,12 +28,12 @@ import static org.jruby.runtime.Visibility.PRIVATE;
|
|
28
28
|
@JRubyClass(name="MessagePack::Packer")
|
29
29
|
public class Packer extends RubyObject {
|
30
30
|
private static final long serialVersionUID = 8451274621499362492L;
|
31
|
-
public ExtensionRegistry registry;
|
31
|
+
public transient ExtensionRegistry registry;
|
32
32
|
private Buffer buffer;
|
33
|
-
private Encoder encoder;
|
33
|
+
private transient Encoder encoder;
|
34
34
|
private boolean hasSymbolExtType;
|
35
35
|
private boolean hasBigintExtType;
|
36
|
-
private Encoding binaryEncoding;
|
36
|
+
private transient Encoding binaryEncoding;
|
37
37
|
|
38
38
|
public Packer(Ruby runtime, RubyClass type, ExtensionRegistry registry, boolean hasSymbolExtType, boolean hasBigintExtType) {
|
39
39
|
super(runtime, type);
|
@@ -93,29 +93,11 @@ public class Packer extends RubyObject {
|
|
93
93
|
return registry.toInternalPackerRegistry(ctx);
|
94
94
|
}
|
95
95
|
|
96
|
-
@JRubyMethod(name = "
|
97
|
-
public IRubyObject registerType(ThreadContext ctx, IRubyObject
|
96
|
+
@JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
|
97
|
+
public IRubyObject registerType(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject proc) {
|
98
|
+
testFrozen("MessagePack::Packer");
|
99
|
+
|
98
100
|
Ruby runtime = ctx.runtime;
|
99
|
-
if (isFrozen()) {
|
100
|
-
throw runtime.newFrozenError("MessagePack::Packer");
|
101
|
-
}
|
102
|
-
IRubyObject type = args[0];
|
103
|
-
IRubyObject mod = args[1];
|
104
|
-
|
105
|
-
IRubyObject arg;
|
106
|
-
IRubyObject proc;
|
107
|
-
if (args.length == 2) {
|
108
|
-
if (! block.isGiven()) {
|
109
|
-
throw runtime.newLocalJumpErrorNoBlock();
|
110
|
-
}
|
111
|
-
proc = block.getProcObject();
|
112
|
-
arg = proc;
|
113
|
-
} else if (args.length == 3) {
|
114
|
-
arg = args[2];
|
115
|
-
proc = arg.callMethod(ctx, "to_proc");
|
116
|
-
} else {
|
117
|
-
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 2..3)", 2 + args.length));
|
118
|
-
}
|
119
101
|
|
120
102
|
long typeId = ((RubyFixnum) type).getLongValue();
|
121
103
|
if (typeId < -128 || typeId > 127) {
|
@@ -127,9 +109,9 @@ public class Packer extends RubyObject {
|
|
127
109
|
}
|
128
110
|
RubyModule extModule = (RubyModule) mod;
|
129
111
|
|
130
|
-
registry.put(extModule, (int) typeId, false, proc,
|
112
|
+
registry.put(extModule, (int) typeId, false, proc, null);
|
131
113
|
|
132
|
-
if (extModule == runtime.getSymbol()) {
|
114
|
+
if (extModule == runtime.getSymbol() && !proc.isNil()) {
|
133
115
|
encoder.hasSymbolExtType = true;
|
134
116
|
}
|
135
117
|
|
@@ -21,18 +21,17 @@ import org.jruby.runtime.ThreadContext;
|
|
21
21
|
import org.jruby.anno.JRubyClass;
|
22
22
|
import org.jruby.anno.JRubyMethod;
|
23
23
|
import org.jruby.util.ByteList;
|
24
|
-
import org.jruby.ext.stringio.StringIO;
|
25
24
|
|
26
25
|
import static org.jruby.runtime.Visibility.PRIVATE;
|
27
26
|
|
28
27
|
@JRubyClass(name="MessagePack::Unpacker")
|
29
28
|
public class Unpacker extends RubyObject {
|
30
29
|
private static final long serialVersionUID = 8451264671199362492L;
|
31
|
-
private final ExtensionRegistry registry;
|
30
|
+
private transient final ExtensionRegistry registry;
|
32
31
|
|
33
|
-
private IRubyObject stream;
|
34
|
-
private IRubyObject data;
|
35
|
-
private Decoder decoder;
|
32
|
+
private transient IRubyObject stream;
|
33
|
+
private transient IRubyObject data;
|
34
|
+
private transient Decoder decoder;
|
36
35
|
private final RubyClass underflowErrorClass;
|
37
36
|
private boolean symbolizeKeys;
|
38
37
|
private boolean freeze;
|
@@ -127,40 +126,23 @@ public class Unpacker extends RubyObject {
|
|
127
126
|
return registry.toInternalUnpackerRegistry(ctx);
|
128
127
|
}
|
129
128
|
|
130
|
-
@JRubyMethod(name = "
|
131
|
-
public IRubyObject
|
129
|
+
@JRubyMethod(name = "register_type_internal", required = 3, visibility = PRIVATE)
|
130
|
+
public IRubyObject registerTypeInternal(ThreadContext ctx, IRubyObject type, IRubyObject mod, IRubyObject proc) {
|
131
|
+
testFrozen("MessagePack::Unpacker");
|
132
|
+
|
132
133
|
Ruby runtime = ctx.runtime;
|
133
|
-
if (isFrozen()) {
|
134
|
-
throw runtime.newFrozenError("MessagePack::Unpacker");
|
135
|
-
}
|
136
|
-
IRubyObject type = args[0];
|
137
|
-
|
138
|
-
RubyModule extModule;
|
139
|
-
IRubyObject arg;
|
140
|
-
IRubyObject proc;
|
141
|
-
if (args.length == 1) {
|
142
|
-
if (! block.isGiven()) {
|
143
|
-
throw runtime.newLocalJumpErrorNoBlock();
|
144
|
-
}
|
145
|
-
proc = RubyProc.newProc(runtime, block, block.type);
|
146
|
-
if (proc == null)
|
147
|
-
System.err.println("proc from Block is null");
|
148
|
-
arg = proc;
|
149
|
-
extModule = null;
|
150
|
-
} else if (args.length == 3) {
|
151
|
-
extModule = (RubyModule) args[1];
|
152
|
-
arg = args[2];
|
153
|
-
proc = extModule.method(arg);
|
154
|
-
} else {
|
155
|
-
throw runtime.newArgumentError(String.format("wrong number of arguments (%d for 1 or 3)", 2 + args.length));
|
156
|
-
}
|
157
134
|
|
158
135
|
long typeId = ((RubyFixnum) type).getLongValue();
|
159
136
|
if (typeId < -128 || typeId > 127) {
|
160
137
|
throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
|
161
138
|
}
|
162
139
|
|
163
|
-
|
140
|
+
RubyModule extModule = null;
|
141
|
+
if (mod != runtime.getNil()) {
|
142
|
+
extModule = (RubyModule)mod;
|
143
|
+
}
|
144
|
+
|
145
|
+
registry.put(extModule, (int) typeId, false, null, proc);
|
164
146
|
return runtime.getNil();
|
165
147
|
}
|
166
148
|
|
@@ -334,9 +316,7 @@ public class Unpacker extends RubyObject {
|
|
334
316
|
@JRubyMethod(name = "stream=", required = 1)
|
335
317
|
public IRubyObject setStream(ThreadContext ctx, IRubyObject stream) {
|
336
318
|
RubyString str;
|
337
|
-
if (stream instanceof
|
338
|
-
str = stream.callMethod(ctx, "string").asString();
|
339
|
-
} else if (stream instanceof RubyIO) {
|
319
|
+
if (stream instanceof RubyIO) {
|
340
320
|
str = stream.callMethod(ctx, "read").asString();
|
341
321
|
} else if (stream.respondsTo("read")) {
|
342
322
|
str = stream.callMethod(ctx, "read").asString();
|
data/ext/msgpack/buffer.c
CHANGED
@@ -251,12 +251,14 @@ bool _msgpack_buffer_read_all2(msgpack_buffer_t* b, char* buffer, size_t length)
|
|
251
251
|
|
252
252
|
static inline msgpack_buffer_chunk_t* _msgpack_buffer_alloc_new_chunk(msgpack_buffer_t* b)
|
253
253
|
{
|
254
|
-
msgpack_buffer_chunk_t*
|
255
|
-
if(
|
256
|
-
|
254
|
+
msgpack_buffer_chunk_t* chunk = b->free_list;
|
255
|
+
if (chunk) {
|
256
|
+
b->free_list = b->free_list->next;
|
257
|
+
} else {
|
258
|
+
chunk = xmalloc(sizeof(msgpack_buffer_chunk_t));
|
257
259
|
}
|
258
|
-
|
259
|
-
return
|
260
|
+
memset(chunk, 0, sizeof(msgpack_buffer_chunk_t));
|
261
|
+
return chunk;
|
260
262
|
}
|
261
263
|
|
262
264
|
static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
|
data/ext/msgpack/buffer.h
CHANGED
@@ -268,7 +268,9 @@ static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE str
|
|
268
268
|
static inline size_t msgpack_buffer_append_string_reference(msgpack_buffer_t* b, VALUE string)
|
269
269
|
{
|
270
270
|
size_t length = RSTRING_LEN(string);
|
271
|
-
|
271
|
+
if (length > 0) {
|
272
|
+
_msgpack_buffer_append_long_string(b, string);
|
273
|
+
}
|
272
274
|
return length;
|
273
275
|
}
|
274
276
|
|
data/ext/msgpack/buffer_class.c
CHANGED
@@ -21,7 +21,8 @@
|
|
21
21
|
#include "buffer.h"
|
22
22
|
#include "buffer_class.h"
|
23
23
|
|
24
|
-
VALUE cMessagePack_Buffer;
|
24
|
+
VALUE cMessagePack_Buffer = Qnil;
|
25
|
+
VALUE cMessagePack_HeldBuffer = Qnil;
|
25
26
|
|
26
27
|
static ID s_read;
|
27
28
|
static ID s_readpartial;
|
@@ -34,6 +35,73 @@ static VALUE sym_read_reference_threshold;
|
|
34
35
|
static VALUE sym_write_reference_threshold;
|
35
36
|
static VALUE sym_io_buffer_size;
|
36
37
|
|
38
|
+
typedef struct msgpack_held_buffer_t msgpack_held_buffer_t;
|
39
|
+
struct msgpack_held_buffer_t {
|
40
|
+
size_t size;
|
41
|
+
VALUE mapped_strings[];
|
42
|
+
};
|
43
|
+
|
44
|
+
static void HeldBuffer_mark(void *data)
|
45
|
+
{
|
46
|
+
msgpack_held_buffer_t* held_buffer = (msgpack_held_buffer_t*)data;
|
47
|
+
for (size_t index = 0; index < held_buffer->size; index++) {
|
48
|
+
rb_gc_mark(held_buffer->mapped_strings[index]);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
static size_t HeldBuffer_memsize(const void *data)
|
53
|
+
{
|
54
|
+
const msgpack_held_buffer_t* held_buffer = (msgpack_held_buffer_t*)data;
|
55
|
+
return sizeof(size_t) + sizeof(VALUE) * held_buffer->size;
|
56
|
+
}
|
57
|
+
|
58
|
+
static const rb_data_type_t held_buffer_data_type = {
|
59
|
+
.wrap_struct_name = "msgpack:held_buffer",
|
60
|
+
.function = {
|
61
|
+
.dmark = HeldBuffer_mark,
|
62
|
+
.dfree = RUBY_TYPED_DEFAULT_FREE,
|
63
|
+
.dsize = HeldBuffer_memsize,
|
64
|
+
},
|
65
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
66
|
+
};
|
67
|
+
|
68
|
+
VALUE MessagePack_Buffer_hold(msgpack_buffer_t* buffer)
|
69
|
+
{
|
70
|
+
size_t mapped_strings_count = 0;
|
71
|
+
msgpack_buffer_chunk_t* c = buffer->head;
|
72
|
+
while (c != &buffer->tail) {
|
73
|
+
if (c->mapped_string != NO_MAPPED_STRING) {
|
74
|
+
mapped_strings_count++;
|
75
|
+
}
|
76
|
+
c = c->next;
|
77
|
+
}
|
78
|
+
if (c->mapped_string != NO_MAPPED_STRING) {
|
79
|
+
mapped_strings_count++;
|
80
|
+
}
|
81
|
+
|
82
|
+
if (mapped_strings_count == 0) {
|
83
|
+
return Qnil;
|
84
|
+
}
|
85
|
+
|
86
|
+
msgpack_held_buffer_t* held_buffer = xmalloc(sizeof(msgpack_held_buffer_t) + mapped_strings_count * sizeof(VALUE));
|
87
|
+
|
88
|
+
c = buffer->head;
|
89
|
+
mapped_strings_count = 0;
|
90
|
+
while (c != &buffer->tail) {
|
91
|
+
if (c->mapped_string != NO_MAPPED_STRING) {
|
92
|
+
held_buffer->mapped_strings[mapped_strings_count] = c->mapped_string;
|
93
|
+
mapped_strings_count++;
|
94
|
+
}
|
95
|
+
c = c->next;
|
96
|
+
}
|
97
|
+
if (c->mapped_string != NO_MAPPED_STRING) {
|
98
|
+
held_buffer->mapped_strings[mapped_strings_count] = c->mapped_string;
|
99
|
+
mapped_strings_count++;
|
100
|
+
}
|
101
|
+
held_buffer->size = mapped_strings_count;
|
102
|
+
return TypedData_Wrap_Struct(cMessagePack_HeldBuffer, &held_buffer_data_type, held_buffer);
|
103
|
+
}
|
104
|
+
|
37
105
|
|
38
106
|
#define CHECK_STRING_TYPE(value) \
|
39
107
|
value = rb_check_string_type(value); \
|
@@ -520,6 +588,9 @@ void MessagePack_Buffer_module_init(VALUE mMessagePack)
|
|
520
588
|
|
521
589
|
msgpack_buffer_static_init();
|
522
590
|
|
591
|
+
cMessagePack_HeldBuffer = rb_define_class_under(mMessagePack, "HeldBuffer", rb_cBasicObject);
|
592
|
+
rb_undef_alloc_func(cMessagePack_HeldBuffer);
|
593
|
+
|
523
594
|
cMessagePack_Buffer = rb_define_class_under(mMessagePack, "Buffer", rb_cObject);
|
524
595
|
|
525
596
|
rb_define_alloc_func(cMessagePack_Buffer, Buffer_alloc);
|
data/ext/msgpack/buffer_class.h
CHANGED
@@ -25,6 +25,7 @@ extern VALUE cMessagePack_Buffer;
|
|
25
25
|
void MessagePack_Buffer_module_init(VALUE mMessagePack);
|
26
26
|
|
27
27
|
VALUE MessagePack_Buffer_wrap(msgpack_buffer_t* b, VALUE owner);
|
28
|
+
VALUE MessagePack_Buffer_hold(msgpack_buffer_t* b);
|
28
29
|
|
29
30
|
void MessagePack_Buffer_set_options(msgpack_buffer_t* b, VALUE io, VALUE options);
|
30
31
|
|
data/ext/msgpack/extconf.rb
CHANGED
@@ -1,19 +1,23 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
|
3
|
-
have_header("ruby/st.h")
|
4
|
-
have_header("st.h")
|
5
3
|
have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
|
6
4
|
have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
|
5
|
+
have_func("rb_proc_call_with_block", "ruby.h") # CRuby (TruffleRuby doesn't have it)
|
7
6
|
|
8
|
-
|
7
|
+
append_cflags([
|
8
|
+
"-fvisibility=hidden",
|
9
|
+
"-I..",
|
10
|
+
"-Wall",
|
11
|
+
"-O3",
|
12
|
+
"-std=gnu99"
|
13
|
+
])
|
14
|
+
append_cflags(RbConfig::CONFIG["debugflags"]) if RbConfig::CONFIG["debugflags"]
|
9
15
|
|
10
|
-
|
11
|
-
$CFLAGS << %[ -I.. -Wall -O3 #{RbConfig::CONFIG["debugflags"]} -std=gnu99]
|
12
|
-
end
|
16
|
+
append_cflags("-DRUBY_DEBUG=1") if ENV["MSGPACK_DEBUG"]
|
13
17
|
|
14
18
|
if RUBY_VERSION.start_with?('3.0.') && RUBY_VERSION <= '3.0.5'
|
15
19
|
# https://bugs.ruby-lang.org/issues/18772
|
16
|
-
|
20
|
+
append_cflags("-DRB_ENC_INTERNED_STR_NULL_CHECK=1")
|
17
21
|
end
|
18
22
|
|
19
23
|
# checking if Hash#[]= (rb_hash_aset) dedupes string keys (Ruby 2.6+)
|
@@ -23,21 +27,21 @@ r = rand.to_s
|
|
23
27
|
h[%W(#{r}).join('')] = :foo
|
24
28
|
x[%W(#{r}).join('')] = :foo
|
25
29
|
if x.keys[0].equal?(h.keys[0])
|
26
|
-
|
30
|
+
append_cflags("-DHASH_ASET_DEDUPE=1")
|
27
31
|
else
|
28
|
-
|
32
|
+
append_cflags("-DHASH_ASET_DEDUPE=0")
|
29
33
|
end
|
30
34
|
|
31
35
|
# checking if String#-@ (str_uminus) directly interns frozen strings... ' (Ruby 3.0+)
|
32
36
|
begin
|
33
37
|
s = rand.to_s.freeze
|
34
38
|
if (-s).equal?(s) && (-s.dup).equal?(s)
|
35
|
-
|
39
|
+
append_cflags("-DSTR_UMINUS_DEDUPE_FROZEN=1")
|
36
40
|
else
|
37
|
-
|
41
|
+
append_cflags("-DSTR_UMINUS_DEDUPE_FROZEN=0")
|
38
42
|
end
|
39
43
|
rescue NoMethodError
|
40
|
-
|
44
|
+
append_cflags("-DSTR_UMINUS_DEDUPE_FROZEN=0")
|
41
45
|
end
|
42
46
|
|
43
47
|
if warnflags = CONFIG['warnflags']
|