msgpack 1.2.6 → 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yaml +56 -0
  3. data/.gitignore +3 -1
  4. data/.rubocop.yml +4 -1
  5. data/ChangeLog +59 -0
  6. data/Gemfile +3 -0
  7. data/README.md +242 -0
  8. data/Rakefile +3 -8
  9. data/doclib/msgpack/factory.rb +1 -0
  10. data/doclib/msgpack/packer.rb +20 -0
  11. data/doclib/msgpack/time.rb +22 -0
  12. data/doclib/msgpack/timestamp.rb +44 -0
  13. data/doclib/msgpack.rb +2 -2
  14. data/ext/java/org/msgpack/jruby/Buffer.java +21 -16
  15. data/ext/java/org/msgpack/jruby/Decoder.java +29 -10
  16. data/ext/java/org/msgpack/jruby/Encoder.java +38 -19
  17. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +9 -9
  18. data/ext/java/org/msgpack/jruby/ExtensionValue.java +5 -8
  19. data/ext/java/org/msgpack/jruby/Factory.java +8 -3
  20. data/ext/java/org/msgpack/jruby/Packer.java +31 -8
  21. data/ext/java/org/msgpack/jruby/Unpacker.java +40 -27
  22. data/ext/msgpack/buffer.c +4 -16
  23. data/ext/msgpack/buffer.h +60 -5
  24. data/ext/msgpack/compat.h +1 -12
  25. data/ext/msgpack/extconf.rb +39 -7
  26. data/ext/msgpack/factory_class.c +10 -5
  27. data/ext/msgpack/packer.c +18 -5
  28. data/ext/msgpack/packer.h +0 -16
  29. data/ext/msgpack/packer_class.c +21 -9
  30. data/ext/msgpack/packer_ext_registry.c +0 -22
  31. data/ext/msgpack/unpacker.c +41 -49
  32. data/ext/msgpack/unpacker.h +8 -0
  33. data/ext/msgpack/unpacker_class.c +23 -13
  34. data/lib/msgpack/symbol.rb +14 -4
  35. data/lib/msgpack/time.rb +29 -0
  36. data/lib/msgpack/timestamp.rb +76 -0
  37. data/lib/msgpack/version.rb +4 -7
  38. data/lib/msgpack.rb +8 -10
  39. data/msgpack.gemspec +3 -7
  40. data/spec/cruby/buffer_spec.rb +6 -1
  41. data/spec/factory_spec.rb +17 -0
  42. data/spec/msgpack_spec.rb +44 -1
  43. data/spec/packer_spec.rb +54 -0
  44. data/spec/spec_helper.rb +27 -0
  45. data/spec/timestamp_spec.rb +161 -0
  46. data/spec/unpacker_spec.rb +113 -1
  47. metadata +19 -51
  48. data/.travis.yml +0 -41
  49. 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(ctx.getRuntime().newSymbol("symbolize_keys"));
66
+ IRubyObject sk = options.fastARef(runtime.newSymbol("symbolize_keys"));
63
67
  if (sk != null) {
64
68
  symbolizeKeys = sk.isTrue();
65
69
  }
66
- IRubyObject au = options.fastARef(ctx.getRuntime().newSymbol("allow_unknown_ext"));
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] != ctx.getRuntime().getNil() && !(args[0] instanceof RubyHash)) {
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.getRuntime(), ctx.getRuntime().getModule("MessagePack").getClass("Unpacker"), extRegistry);
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.getRuntime().getTrue() : ctx.getRuntime().getFalse();
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.getRuntime().getTrue() : ctx.getRuntime().getFalse();
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.getRuntime();
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.getRuntime(), registry, byteList.unsafeBytes(), byteList.begin() + offset, limit, symbolizeKeys, allowUnknownExt);
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.getRuntime().newFixnum(decoder.offset());
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.getRuntime().getNil();
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.getRuntime().getFalse() : ctx.getRuntime().getTrue();
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.getRuntime(), registry, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, allowUnknownExt);
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.getRuntime().getNil();
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.getRuntime().getNil();
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.getRuntime().getNil();
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.getRuntime().newEOFError();
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.getRuntime().newEOFError();
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.getRuntime().newNotImplementedError("Not supported yet in JRuby implementation");
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.getRuntime().newNotImplementedError("Not supported yet in JRuby implementation");
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.getRuntime().newEOFError();
281
+ throw ctx.runtime.newEOFError();
269
282
  }
270
283
  }
271
284
  }
272
- return ctx.getRuntime().getNil();
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.getRuntime().newEOFError();
297
+ throw ctx.runtime.newEOFError();
285
298
  }
286
299
  }
287
300
  }
288
- return ctx.getRuntime().getNil();
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.getRuntime().getNil();
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.getRuntime().newTypeError(stream, "IO");
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.getRuntime(), registry, byteList.unsafeBytes(), byteList.begin(), byteList.length(), symbolizeKeys, allowUnknownExt);
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
- #endif
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
- #ifdef COMPAT_HAVE_ENCODING
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
- #endif
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 = rb_str_new(b->read_buffer, length);
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
@@ -2,13 +2,7 @@ require 'mkmf'
2
2
 
3
3
  have_header("ruby/st.h")
4
4
  have_header("st.h")
5
- have_func("rb_str_replace", ["ruby.h"])
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
@@ -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
- void msgpack_packer_write_other_value(msgpack_packer_t* pk, VALUE v)
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
- } else {
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
- msgpack_packer_write_string_value(pk, v);
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
- msgpack_packer_write_array_value(pk, v);
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
- msgpack_packer_write_hash_value(pk, v);
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);