msgpack 1.4.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +57 -0
  3. data/ChangeLog +60 -0
  4. data/README.md +25 -1
  5. data/Rakefile +1 -2
  6. data/bench/bench.rb +78 -0
  7. data/bin/console +8 -0
  8. data/doclib/msgpack/factory.rb +47 -3
  9. data/doclib/msgpack/packer.rb +5 -4
  10. data/doclib/msgpack/unpacker.rb +2 -2
  11. data/ext/java/org/msgpack/jruby/Buffer.java +23 -16
  12. data/ext/java/org/msgpack/jruby/Decoder.java +29 -21
  13. data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
  14. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +37 -49
  15. data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
  16. data/ext/java/org/msgpack/jruby/Factory.java +47 -7
  17. data/ext/java/org/msgpack/jruby/Packer.java +29 -17
  18. data/ext/java/org/msgpack/jruby/Unpacker.java +66 -42
  19. data/ext/msgpack/buffer.c +38 -57
  20. data/ext/msgpack/buffer.h +19 -10
  21. data/ext/msgpack/buffer_class.c +90 -52
  22. data/ext/msgpack/compat.h +0 -99
  23. data/ext/msgpack/extconf.rb +9 -22
  24. data/ext/msgpack/factory_class.c +133 -43
  25. data/ext/msgpack/packer.c +60 -36
  26. data/ext/msgpack/packer.h +27 -18
  27. data/ext/msgpack/packer_class.c +84 -77
  28. data/ext/msgpack/packer_class.h +11 -0
  29. data/ext/msgpack/packer_ext_registry.c +24 -32
  30. data/ext/msgpack/packer_ext_registry.h +40 -33
  31. data/ext/msgpack/sysdep.h +5 -2
  32. data/ext/msgpack/unpacker.c +128 -97
  33. data/ext/msgpack/unpacker.h +17 -10
  34. data/ext/msgpack/unpacker_class.c +75 -80
  35. data/ext/msgpack/unpacker_class.h +11 -0
  36. data/ext/msgpack/unpacker_ext_registry.c +42 -18
  37. data/ext/msgpack/unpacker_ext_registry.h +23 -16
  38. data/lib/msgpack/bigint.rb +69 -0
  39. data/lib/msgpack/factory.rb +103 -0
  40. data/lib/msgpack/symbol.rb +21 -4
  41. data/lib/msgpack/time.rb +1 -1
  42. data/lib/msgpack/version.rb +1 -1
  43. data/lib/msgpack.rb +5 -7
  44. data/msgpack.gemspec +2 -2
  45. data/spec/bigint_spec.rb +26 -0
  46. data/spec/cruby/buffer_spec.rb +17 -0
  47. data/spec/factory_spec.rb +351 -12
  48. data/spec/msgpack_spec.rb +1 -1
  49. data/spec/packer_spec.rb +18 -0
  50. data/spec/spec_helper.rb +20 -3
  51. data/spec/timestamp_spec.rb +38 -0
  52. data/spec/unpacker_spec.rb +54 -4
  53. metadata +25 -41
  54. data/.travis.yml +0 -39
  55. data/bench/pack.rb +0 -23
  56. data/bench/pack_log.rb +0 -33
  57. data/bench/pack_log_long.rb +0 -65
  58. data/bench/pack_symbols.rb +0 -28
  59. data/bench/run.sh +0 -14
  60. data/bench/run_long.sh +0 -35
  61. data/bench/run_symbols.sh +0 -26
  62. data/bench/unpack.rb +0 -21
  63. data/bench/unpack_log.rb +0 -34
  64. data/bench/unpack_log_long.rb +0 -67
@@ -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;
@@ -55,51 +56,70 @@ public class Unpacker extends RubyObject {
55
56
 
56
57
  @JRubyMethod(name = "initialize", optional = 2, visibility = PRIVATE)
57
58
  public IRubyObject initialize(ThreadContext ctx, IRubyObject[] args) {
59
+ Ruby runtime = ctx.runtime;
60
+
58
61
  symbolizeKeys = false;
59
62
  allowUnknownExt = false;
60
63
  freeze = false;
61
- if (args.length > 0) {
62
- if (args[args.length - 1] instanceof RubyHash) {
63
- RubyHash options = (RubyHash) args[args.length - 1];
64
- IRubyObject sk = options.fastARef(ctx.getRuntime().newSymbol("symbolize_keys"));
65
- if (sk != null) {
66
- symbolizeKeys = sk.isTrue();
67
- }
68
- IRubyObject f = options.fastARef(ctx.getRuntime().newSymbol("freeze"));
69
- if (f != null) {
70
- freeze = f.isTrue();
71
- }
72
- IRubyObject au = options.fastARef(ctx.getRuntime().newSymbol("allow_unknown_ext"));
73
- if (au != null) {
74
- allowUnknownExt = au.isTrue();
75
- }
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();
85
+ }
86
+ IRubyObject f = options.fastARef(runtime.newSymbol("freeze"));
87
+ if (f != null) {
88
+ freeze = f.isTrue();
76
89
  }
77
- if (args[0] != ctx.getRuntime().getNil() && !(args[0] instanceof RubyHash)) {
78
- setStream(ctx, args[0]);
90
+ IRubyObject au = options.fastARef(runtime.newSymbol("allow_unknown_ext"));
91
+ if (au != null) {
92
+ allowUnknownExt = au.isTrue();
79
93
  }
94
+
80
95
  }
96
+
97
+ if (io != null && io != runtime.getNil()) {
98
+ setStream(ctx, io);
99
+ }
100
+
81
101
  return this;
82
102
  }
83
103
 
84
104
  public static Unpacker newUnpacker(ThreadContext ctx, ExtensionRegistry extRegistry, IRubyObject[] args) {
85
- Unpacker unpacker = new Unpacker(ctx.getRuntime(), ctx.getRuntime().getModule("MessagePack").getClass("Unpacker"), extRegistry);
105
+ Unpacker unpacker = new Unpacker(ctx.runtime, ctx.runtime.getModule("MessagePack").getClass("Unpacker"), extRegistry);
86
106
  unpacker.initialize(ctx, args);
87
107
  return unpacker;
88
108
  }
89
109
 
90
110
  @JRubyMethod(name = "symbolize_keys?")
91
111
  public IRubyObject isSymbolizeKeys(ThreadContext ctx) {
92
- return symbolizeKeys ? ctx.getRuntime().getTrue() : ctx.getRuntime().getFalse();
112
+ return symbolizeKeys ? ctx.runtime.getTrue() : ctx.runtime.getFalse();
93
113
  }
94
114
 
95
115
  @JRubyMethod(name = "freeze?")
96
116
  public IRubyObject isFreeze(ThreadContext ctx) {
97
- return freeze ? ctx.getRuntime().getTrue() : ctx.getRuntime().getFalse();
117
+ return freeze ? ctx.runtime.getTrue() : ctx.runtime.getFalse();
98
118
  }
99
119
 
100
120
  @JRubyMethod(name = "allow_unknown_ext?")
101
121
  public IRubyObject isAllowUnknownExt(ThreadContext ctx) {
102
- return allowUnknownExt ? ctx.getRuntime().getTrue() : ctx.getRuntime().getFalse();
122
+ return allowUnknownExt ? ctx.runtime.getTrue() : ctx.runtime.getFalse();
103
123
  }
104
124
 
105
125
  @JRubyMethod(name = "registered_types_internal", visibility = PRIVATE)
@@ -109,7 +129,7 @@ public class Unpacker extends RubyObject {
109
129
 
110
130
  @JRubyMethod(name = "register_type", required = 1, optional = 2)
111
131
  public IRubyObject registerType(ThreadContext ctx, IRubyObject[] args, final Block block) {
112
- Ruby runtime = ctx.getRuntime();
132
+ Ruby runtime = ctx.runtime;
113
133
  IRubyObject type = args[0];
114
134
 
115
135
  RubyModule extModule;
@@ -137,7 +157,7 @@ public class Unpacker extends RubyObject {
137
157
  throw runtime.newRangeError(String.format("integer %d too big to convert to `signed char'", typeId));
138
158
  }
139
159
 
140
- registry.put(extModule, (int) typeId, null, null, proc, arg);
160
+ registry.put(extModule, (int) typeId, false, null, null, proc, arg);
141
161
  return runtime.getNil();
142
162
  }
143
163
 
@@ -155,7 +175,7 @@ public class Unpacker extends RubyObject {
155
175
  if (limit == -1) {
156
176
  limit = byteList.length() - offset;
157
177
  }
158
- Decoder decoder = new Decoder(ctx.getRuntime(), registry, byteList.unsafeBytes(), byteList.begin() + offset, limit, symbolizeKeys, freeze, allowUnknownExt);
178
+ Decoder decoder = new Decoder(ctx.runtime, this, byteList.unsafeBytes(), byteList.begin() + offset, limit, symbolizeKeys, freeze, allowUnknownExt);
159
179
  try {
160
180
  data = null;
161
181
  data = decoder.next();
@@ -164,13 +184,13 @@ public class Unpacker extends RubyObject {
164
184
  throw re;
165
185
  }
166
186
  }
167
- return ctx.getRuntime().newFixnum(decoder.offset());
187
+ return ctx.runtime.newFixnum(decoder.offset());
168
188
  }
169
189
 
170
190
  @JRubyMethod(name = "data")
171
191
  public IRubyObject getData(ThreadContext ctx) {
172
192
  if (data == null) {
173
- return ctx.getRuntime().getNil();
193
+ return ctx.runtime.getNil();
174
194
  } else {
175
195
  return data;
176
196
  }
@@ -178,14 +198,14 @@ public class Unpacker extends RubyObject {
178
198
 
179
199
  @JRubyMethod(name = "finished?")
180
200
  public IRubyObject finished_p(ThreadContext ctx) {
181
- return data == null ? ctx.getRuntime().getFalse() : ctx.getRuntime().getTrue();
201
+ return data == null ? ctx.runtime.getFalse() : ctx.runtime.getTrue();
182
202
  }
183
203
 
184
204
  @JRubyMethod(required = 1, name = "feed", alias = { "feed_reference" })
185
205
  public IRubyObject feed(ThreadContext ctx, IRubyObject data) {
186
206
  ByteList byteList = data.asString().getByteList();
187
207
  if (decoder == null) {
188
- decoder = new Decoder(ctx.getRuntime(), registry, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
208
+ decoder = new Decoder(ctx.runtime, this, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
189
209
  } else {
190
210
  decoder.feed(byteList.unsafeBytes(), byteList.begin(), byteList.length());
191
211
  }
@@ -202,7 +222,7 @@ public class Unpacker extends RubyObject {
202
222
  feed(ctx, data);
203
223
  if (block.isGiven()) {
204
224
  each(ctx, block);
205
- return ctx.getRuntime().getNil();
225
+ return ctx.runtime.getNil();
206
226
  } else {
207
227
  return callMethod(ctx, "to_enum");
208
228
  }
@@ -230,7 +250,7 @@ public class Unpacker extends RubyObject {
230
250
 
231
251
  @JRubyMethod
232
252
  public IRubyObject fill(ThreadContext ctx) {
233
- return ctx.getRuntime().getNil();
253
+ return ctx.runtime.getNil();
234
254
  }
235
255
 
236
256
  @JRubyMethod
@@ -238,13 +258,13 @@ public class Unpacker extends RubyObject {
238
258
  if (decoder != null) {
239
259
  decoder.reset();
240
260
  }
241
- return ctx.getRuntime().getNil();
261
+ return ctx.runtime.getNil();
242
262
  }
243
263
 
244
264
  @JRubyMethod(name = "read", alias = { "unpack" })
245
265
  public IRubyObject read(ThreadContext ctx) {
246
266
  if (decoder == null) {
247
- throw ctx.getRuntime().newEOFError();
267
+ throw ctx.runtime.newEOFError();
248
268
  }
249
269
  try {
250
270
  return decoder.next();
@@ -252,19 +272,19 @@ public class Unpacker extends RubyObject {
252
272
  if (re.getException().getType() != underflowErrorClass) {
253
273
  throw re;
254
274
  } else {
255
- throw ctx.getRuntime().newEOFError();
275
+ throw ctx.runtime.newEOFError();
256
276
  }
257
277
  }
258
278
  }
259
279
 
260
280
  @JRubyMethod(name = "skip")
261
281
  public IRubyObject skip(ThreadContext ctx) {
262
- throw ctx.getRuntime().newNotImplementedError("Not supported yet in JRuby implementation");
282
+ throw ctx.runtime.newNotImplementedError("Not supported yet in JRuby implementation");
263
283
  }
264
284
 
265
285
  @JRubyMethod(name = "skip_nil")
266
286
  public IRubyObject skipNil(ThreadContext ctx) {
267
- throw ctx.getRuntime().newNotImplementedError("Not supported yet in JRuby implementation");
287
+ throw ctx.runtime.newNotImplementedError("Not supported yet in JRuby implementation");
268
288
  }
269
289
 
270
290
  @JRubyMethod
@@ -276,11 +296,11 @@ public class Unpacker extends RubyObject {
276
296
  if (re.getException().getType() != underflowErrorClass) {
277
297
  throw re;
278
298
  } else {
279
- throw ctx.getRuntime().newEOFError();
299
+ throw ctx.runtime.newEOFError();
280
300
  }
281
301
  }
282
302
  }
283
- return ctx.getRuntime().getNil();
303
+ return ctx.runtime.getNil();
284
304
  }
285
305
 
286
306
  @JRubyMethod
@@ -292,17 +312,17 @@ public class Unpacker extends RubyObject {
292
312
  if (re.getException().getType() != underflowErrorClass) {
293
313
  throw re;
294
314
  } else {
295
- throw ctx.getRuntime().newEOFError();
315
+ throw ctx.runtime.newEOFError();
296
316
  }
297
317
  }
298
318
  }
299
- return ctx.getRuntime().getNil();
319
+ return ctx.runtime.getNil();
300
320
  }
301
321
 
302
322
  @JRubyMethod(name = "stream")
303
323
  public IRubyObject getStream(ThreadContext ctx) {
304
324
  if (stream == null) {
305
- return ctx.getRuntime().getNil();
325
+ return ctx.runtime.getNil();
306
326
  } else {
307
327
  return stream;
308
328
  }
@@ -318,12 +338,16 @@ public class Unpacker extends RubyObject {
318
338
  } else if (stream.respondsTo("read")) {
319
339
  str = stream.callMethod(ctx, "read").asString();
320
340
  } else {
321
- throw ctx.getRuntime().newTypeError(stream, "IO");
341
+ throw ctx.runtime.newTypeError(stream, "IO");
322
342
  }
323
343
  ByteList byteList = str.getByteList();
324
344
  this.stream = stream;
325
345
  this.decoder = null;
326
- this.decoder = new Decoder(ctx.getRuntime(), registry, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
346
+ this.decoder = new Decoder(ctx.runtime, this, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, freeze, allowUnknownExt);
327
347
  return getStream(ctx);
328
348
  }
349
+
350
+ public ExtensionRegistry.ExtensionEntry lookupExtensionByTypeId(int typeId) {
351
+ return registry.lookupExtensionByTypeId(typeId);
352
+ }
329
353
  }
data/ext/msgpack/buffer.c CHANGED
@@ -29,11 +29,9 @@ int msgpack_rb_encindex_ascii8bit;
29
29
 
30
30
  ID s_uminus;
31
31
 
32
- #ifndef DISABLE_RMEM
33
32
  static msgpack_rmem_t s_rmem;
34
- #endif
35
33
 
36
- void msgpack_buffer_static_init()
34
+ void msgpack_buffer_static_init(void)
37
35
  {
38
36
  s_uminus = rb_intern("-@");
39
37
 
@@ -41,20 +39,16 @@ void msgpack_buffer_static_init()
41
39
  msgpack_rb_encindex_usascii = rb_usascii_encindex();
42
40
  msgpack_rb_encindex_ascii8bit = rb_ascii8bit_encindex();
43
41
 
44
- #ifndef DISABLE_RMEM
45
42
  msgpack_rmem_init(&s_rmem);
46
- #endif
47
43
 
48
44
  #ifndef HAVE_RB_STR_REPLACE
49
45
  s_replace = rb_intern("replace");
50
46
  #endif
51
47
  }
52
48
 
53
- void msgpack_buffer_static_destroy()
49
+ void msgpack_buffer_static_destroy(void)
54
50
  {
55
- #ifndef DISABLE_RMEM
56
51
  msgpack_rmem_destroy(&s_rmem);
57
- #endif
58
52
  }
59
53
 
60
54
  void msgpack_buffer_init(msgpack_buffer_t* b)
@@ -72,16 +66,12 @@ void msgpack_buffer_init(msgpack_buffer_t* b)
72
66
  static void _msgpack_buffer_chunk_destroy(msgpack_buffer_chunk_t* c)
73
67
  {
74
68
  if(c->mem != NULL) {
75
- #ifndef DISABLE_RMEM
76
69
  if(!msgpack_rmem_free(&s_rmem, c->mem)) {
77
70
  xfree(c->mem);
78
71
  }
79
72
  /* no needs to update rmem_owner because chunks will not be
80
73
  * free()ed (left in free_list) and thus *rmem_owner is
81
74
  * always valid. */
82
- #else
83
- xfree(c->mem);
84
- #endif
85
75
  }
86
76
  c->first = NULL;
87
77
  c->last = NULL;
@@ -108,8 +98,25 @@ void msgpack_buffer_destroy(msgpack_buffer_t* b)
108
98
  }
109
99
  }
110
100
 
111
- void msgpack_buffer_mark(msgpack_buffer_t* b)
101
+ size_t msgpack_buffer_memsize(const msgpack_buffer_t* b)
112
102
  {
103
+ size_t memsize = 0;
104
+ msgpack_buffer_chunk_t* c = b->head;
105
+
106
+ while(c) {
107
+ memsize += sizeof(msgpack_buffer_chunk_t);
108
+ if(c->mapped_string != NO_MAPPED_STRING) {
109
+ memsize += (c->last - c->first);
110
+ }
111
+ c = c->next;
112
+ }
113
+
114
+ return memsize;
115
+ }
116
+
117
+ void msgpack_buffer_mark(void *ptr)
118
+ {
119
+ msgpack_buffer_t* b = ptr;
113
120
  /* head is always available */
114
121
  msgpack_buffer_chunk_t* c = b->head;
115
122
  while(c != &b->tail) {
@@ -120,8 +127,6 @@ void msgpack_buffer_mark(msgpack_buffer_t* b)
120
127
 
121
128
  rb_gc_mark(b->io);
122
129
  rb_gc_mark(b->io_buffer);
123
-
124
- rb_gc_mark(b->owner);
125
130
  }
126
131
 
127
132
  bool _msgpack_buffer_shift_chunk(msgpack_buffer_t* b)
@@ -158,24 +163,17 @@ size_t msgpack_buffer_read_to_string_nonblock(msgpack_buffer_t* b, VALUE string,
158
163
  {
159
164
  size_t avail = msgpack_buffer_top_readable_size(b);
160
165
 
161
- #ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE
162
166
  /* optimize */
163
167
  if(length <= avail && RSTRING_LEN(string) == 0 &&
164
168
  b->head->mapped_string != NO_MAPPED_STRING &&
165
169
  length >= b->read_reference_threshold) {
166
170
  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
171
  rb_str_replace(string, s);
172
- #endif
173
172
  /* here doesn't have to call ENCODING_SET because
174
173
  * encoding of s is always ASCII-8BIT */
175
174
  _msgpack_buffer_consumed(b, length);
176
175
  return length;
177
176
  }
178
- #endif
179
177
 
180
178
  size_t const length_orig = length;
181
179
 
@@ -288,15 +286,11 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
288
286
 
289
287
  msgpack_buffer_chunk_t* nc = _msgpack_buffer_alloc_new_chunk(b);
290
288
 
291
- #ifndef DISABLE_RMEM
292
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
293
289
  if(b->rmem_last == b->tail_buffer_end) {
294
290
  /* reuse unused rmem space */
295
291
  size_t unused = b->tail_buffer_end - b->tail.last;
296
292
  b->rmem_last -= unused;
297
293
  }
298
- #endif
299
- #endif
300
294
 
301
295
  /* rebuild tail */
302
296
  *nc = b->tail;
@@ -307,8 +301,13 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
307
301
 
308
302
  static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE string)
309
303
  {
310
- VALUE mapped_string = rb_str_dup(string);
311
- ENCODING_SET(mapped_string, msgpack_rb_encindex_ascii8bit);
304
+ VALUE mapped_string;
305
+ if(ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit && RTEST(rb_obj_frozen_p(string))) {
306
+ mapped_string = string;
307
+ } else {
308
+ mapped_string = rb_str_dup(string);
309
+ ENCODING_SET(mapped_string, msgpack_rb_encindex_ascii8bit);
310
+ }
312
311
 
313
312
  _msgpack_buffer_add_new_chunk(b);
314
313
 
@@ -337,18 +336,11 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
337
336
  msgpack_buffer_flush(b);
338
337
  if (ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit) {
339
338
  rb_funcall(b->io, b->io_write_all_method, 1, string);
340
- } else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
341
- VALUE s = rb_str_dup(string);
342
- ENCODING_SET(s, msgpack_rb_encindex_ascii8bit);
343
- rb_funcall(b->io, b->io_write_all_method, 1, s);
344
339
  } else {
345
340
  msgpack_buffer_append(b, RSTRING_PTR(string), length);
346
341
  }
347
- } else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
348
- _msgpack_buffer_append_reference(b, string);
349
-
350
342
  } else {
351
- msgpack_buffer_append(b, RSTRING_PTR(string), length);
343
+ _msgpack_buffer_append_reference(b, string);
352
344
  }
353
345
  }
354
346
 
@@ -356,11 +348,8 @@ static inline void* _msgpack_buffer_chunk_malloc(
356
348
  msgpack_buffer_t* b, msgpack_buffer_chunk_t* c,
357
349
  size_t required_size, size_t* allocated_size)
358
350
  {
359
- #ifndef DISABLE_RMEM
360
351
  if(required_size <= MSGPACK_RMEM_PAGE_SIZE) {
361
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
362
352
  if((size_t)(b->rmem_end - b->rmem_last) < required_size) {
363
- #endif
364
353
  /* alloc new rmem page */
365
354
  *allocated_size = MSGPACK_RMEM_PAGE_SIZE;
366
355
  char* buffer = msgpack_rmem_alloc(&s_rmem);
@@ -371,8 +360,6 @@ static inline void* _msgpack_buffer_chunk_malloc(
371
360
  b->rmem_last = b->rmem_end = buffer + MSGPACK_RMEM_PAGE_SIZE;
372
361
 
373
362
  return buffer;
374
-
375
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
376
363
  } else {
377
364
  /* reuse unused rmem */
378
365
  *allocated_size = (size_t)(b->rmem_end - b->rmem_last);
@@ -386,13 +373,7 @@ static inline void* _msgpack_buffer_chunk_malloc(
386
373
 
387
374
  return buffer;
388
375
  }
389
- #endif
390
376
  }
391
- #else
392
- if(required_size < 72) {
393
- required_size = 72;
394
- }
395
- #endif
396
377
 
397
378
  // TODO alignment?
398
379
  *allocated_size = required_size;
@@ -447,11 +428,7 @@ void _msgpack_buffer_expand(msgpack_buffer_t* b, const char* data, size_t length
447
428
  size_t capacity = b->tail.last - b->tail.first;
448
429
 
449
430
  /* can't realloc mapped chunk or rmem page */
450
- if(b->tail.mapped_string != NO_MAPPED_STRING
451
- #ifndef DISABLE_RMEM
452
- || capacity <= MSGPACK_RMEM_PAGE_SIZE
453
- #endif
454
- ) {
431
+ if(b->tail.mapped_string != NO_MAPPED_STRING || capacity <= MSGPACK_RMEM_PAGE_SIZE) {
455
432
  /* allocate new chunk */
456
433
  _msgpack_buffer_add_new_chunk(b);
457
434
 
@@ -624,13 +601,13 @@ size_t msgpack_buffer_flush_to_io(msgpack_buffer_t* b, VALUE io, ID write_method
624
601
  size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
625
602
  {
626
603
  if(b->io_buffer == Qnil) {
627
- b->io_buffer = rb_funcall(b->io, b->io_partial_read_method, 1, LONG2NUM(b->io_buffer_size));
604
+ b->io_buffer = rb_funcall(b->io, b->io_partial_read_method, 1, SIZET2NUM(b->io_buffer_size));
628
605
  if(b->io_buffer == Qnil) {
629
606
  rb_raise(rb_eEOFError, "IO reached end of file");
630
607
  }
631
608
  StringValue(b->io_buffer);
632
609
  } else {
633
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(b->io_buffer_size), b->io_buffer);
610
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(b->io_buffer_size), b->io_buffer);
634
611
  if(ret == Qnil) {
635
612
  rb_raise(rb_eEOFError, "IO reached end of file");
636
613
  }
@@ -649,9 +626,11 @@ size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
649
626
 
650
627
  size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string, size_t length)
651
628
  {
629
+ #define MIN(x, y) (((x) < (y)) ? (x) : (y))
630
+
652
631
  if(RSTRING_LEN(string) == 0) {
653
632
  /* direct read */
654
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(length), string);
633
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(MIN(b->io_buffer_size, length)), string);
655
634
  if(ret == Qnil) {
656
635
  return 0;
657
636
  }
@@ -663,7 +642,7 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
663
642
  b->io_buffer = rb_str_buf_new(0);
664
643
  }
665
644
 
666
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(length), b->io_buffer);
645
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(MIN(b->io_buffer_size, length)), b->io_buffer);
667
646
  if(ret == Qnil) {
668
647
  return 0;
669
648
  }
@@ -671,6 +650,8 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
671
650
 
672
651
  rb_str_buf_cat(string, (const void*)RSTRING_PTR(b->io_buffer), rl);
673
652
  return rl;
653
+
654
+ #undef MIN
674
655
  }
675
656
 
676
657
  size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
@@ -679,7 +660,7 @@ size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
679
660
  b->io_buffer = rb_str_buf_new(0);
680
661
  }
681
662
 
682
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(length), b->io_buffer);
663
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(length), b->io_buffer);
683
664
  if(ret == Qnil) {
684
665
  return 0;
685
666
  }
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;
@@ -98,11 +102,9 @@ struct msgpack_buffer_t {
98
102
  msgpack_buffer_chunk_t* head;
99
103
  msgpack_buffer_chunk_t* free_list;
100
104
 
101
- #ifndef DISABLE_RMEM
102
105
  char* rmem_last;
103
106
  char* rmem_end;
104
107
  void** rmem_owner;
105
- #endif
106
108
 
107
109
  union msgpack_buffer_cast_block_t cast_block;
108
110
 
@@ -114,25 +116,25 @@ struct msgpack_buffer_t {
114
116
  size_t write_reference_threshold;
115
117
  size_t read_reference_threshold;
116
118
  size_t io_buffer_size;
117
-
118
- VALUE owner;
119
119
  };
120
120
 
121
121
  /*
122
122
  * initialization functions
123
123
  */
124
- void msgpack_buffer_static_init();
124
+ void msgpack_buffer_static_init(void);
125
125
 
126
- void msgpack_buffer_static_destroy();
126
+ void msgpack_buffer_static_destroy(void);
127
127
 
128
128
  void msgpack_buffer_init(msgpack_buffer_t* b);
129
129
 
130
130
  void msgpack_buffer_destroy(msgpack_buffer_t* b);
131
131
 
132
- void msgpack_buffer_mark(msgpack_buffer_t* b);
132
+ void msgpack_buffer_mark(void* b);
133
133
 
134
134
  void msgpack_buffer_clear(msgpack_buffer_t* b);
135
135
 
136
+ size_t msgpack_buffer_memsize(const msgpack_buffer_t* b);
137
+
136
138
  static inline void msgpack_buffer_set_write_reference_threshold(msgpack_buffer_t* b, size_t length)
137
139
  {
138
140
  if(length < MSGPACK_BUFFER_STRING_WRITE_REFERENCE_MINIMUM) {
@@ -440,7 +442,6 @@ static inline VALUE _msgpack_buffer_refer_head_mapped_string(msgpack_buffer_t* b
440
442
 
441
443
  static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen, bool utf8)
442
444
  {
443
- #ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE
444
445
  /* optimize */
445
446
  if(!will_be_frozen &&
446
447
  b->head->mapped_string != NO_MAPPED_STRING &&
@@ -450,13 +451,16 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
450
451
  _msgpack_buffer_consumed(b, length);
451
452
  return result;
452
453
  }
453
- #endif
454
454
 
455
455
  VALUE result;
456
456
 
457
457
  #ifdef HAVE_RB_ENC_INTERNED_STR
458
458
  if (will_be_frozen) {
459
- result = rb_enc_interned_str(b->read_buffer, length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
459
+ if (RB_ENC_INTERNED_STR_NULL_CHECK && length == 0) {
460
+ result = rb_enc_interned_str("", length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
461
+ } else {
462
+ result = rb_enc_interned_str(b->read_buffer, length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
463
+ }
460
464
  } else {
461
465
  if (utf8) {
462
466
  result = rb_utf8_str_new(b->read_buffer, length);
@@ -494,4 +498,9 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
494
498
  #endif // HAVE_RB_ENC_INTERNED_STR
495
499
  }
496
500
 
501
+ static inline VALUE msgpack_buffer_read_top_as_symbol(msgpack_buffer_t* b, size_t length, bool utf8)
502
+ {
503
+ return rb_str_intern(msgpack_buffer_read_top_as_string(b, length, true, utf8));
504
+ }
505
+
497
506
  #endif