msgpack 1.3.3 → 1.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +99 -0
  3. data/README.md +293 -0
  4. data/ext/java/org/msgpack/jruby/Buffer.java +26 -19
  5. data/ext/java/org/msgpack/jruby/Decoder.java +46 -23
  6. data/ext/java/org/msgpack/jruby/Encoder.java +68 -30
  7. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +43 -64
  8. data/ext/java/org/msgpack/jruby/ExtensionValue.java +6 -9
  9. data/ext/java/org/msgpack/jruby/Factory.java +43 -42
  10. data/ext/java/org/msgpack/jruby/Packer.java +37 -40
  11. data/ext/java/org/msgpack/jruby/Unpacker.java +86 -68
  12. data/ext/msgpack/buffer.c +58 -85
  13. data/ext/msgpack/buffer.h +59 -20
  14. data/ext/msgpack/buffer_class.c +161 -52
  15. data/ext/msgpack/buffer_class.h +1 -0
  16. data/ext/msgpack/compat.h +1 -111
  17. data/ext/msgpack/extconf.rb +41 -23
  18. data/ext/msgpack/factory_class.c +143 -87
  19. data/ext/msgpack/packer.c +66 -43
  20. data/ext/msgpack/packer.h +25 -27
  21. data/ext/msgpack/packer_class.c +102 -130
  22. data/ext/msgpack/packer_class.h +11 -0
  23. data/ext/msgpack/packer_ext_registry.c +35 -40
  24. data/ext/msgpack/packer_ext_registry.h +41 -38
  25. data/ext/msgpack/rbinit.c +1 -1
  26. data/ext/msgpack/rmem.c +3 -4
  27. data/ext/msgpack/sysdep.h +5 -2
  28. data/ext/msgpack/unpacker.c +130 -126
  29. data/ext/msgpack/unpacker.h +22 -13
  30. data/ext/msgpack/unpacker_class.c +94 -124
  31. data/ext/msgpack/unpacker_class.h +11 -0
  32. data/ext/msgpack/unpacker_ext_registry.c +40 -28
  33. data/ext/msgpack/unpacker_ext_registry.h +21 -18
  34. data/lib/msgpack/bigint.rb +69 -0
  35. data/lib/msgpack/buffer.rb +9 -0
  36. data/lib/msgpack/factory.rb +140 -10
  37. data/lib/msgpack/packer.rb +10 -1
  38. data/lib/msgpack/symbol.rb +21 -4
  39. data/lib/msgpack/time.rb +1 -1
  40. data/lib/msgpack/unpacker.rb +14 -1
  41. data/lib/msgpack/version.rb +4 -8
  42. data/lib/msgpack.rb +7 -12
  43. data/msgpack.gemspec +9 -8
  44. metadata +37 -96
  45. data/.gitignore +0 -23
  46. data/.rubocop.yml +0 -36
  47. data/.travis.yml +0 -43
  48. data/Gemfile +0 -9
  49. data/README.rdoc +0 -225
  50. data/Rakefile +0 -78
  51. data/appveyor.yml +0 -18
  52. data/bench/pack.rb +0 -23
  53. data/bench/pack_log.rb +0 -33
  54. data/bench/pack_log_long.rb +0 -65
  55. data/bench/pack_symbols.rb +0 -28
  56. data/bench/run.sh +0 -14
  57. data/bench/run_long.sh +0 -35
  58. data/bench/run_symbols.sh +0 -26
  59. data/bench/unpack.rb +0 -21
  60. data/bench/unpack_log.rb +0 -34
  61. data/bench/unpack_log_long.rb +0 -67
  62. data/doclib/msgpack/buffer.rb +0 -193
  63. data/doclib/msgpack/core_ext.rb +0 -101
  64. data/doclib/msgpack/error.rb +0 -19
  65. data/doclib/msgpack/extension_value.rb +0 -9
  66. data/doclib/msgpack/factory.rb +0 -101
  67. data/doclib/msgpack/packer.rb +0 -208
  68. data/doclib/msgpack/time.rb +0 -22
  69. data/doclib/msgpack/timestamp.rb +0 -44
  70. data/doclib/msgpack/unpacker.rb +0 -183
  71. data/doclib/msgpack.rb +0 -87
  72. data/msgpack.org.md +0 -46
  73. data/spec/cases.json +0 -1
  74. data/spec/cases.msg +0 -0
  75. data/spec/cases_compact.msg +0 -0
  76. data/spec/cases_spec.rb +0 -39
  77. data/spec/cruby/buffer_io_spec.rb +0 -255
  78. data/spec/cruby/buffer_packer.rb +0 -29
  79. data/spec/cruby/buffer_spec.rb +0 -575
  80. data/spec/cruby/buffer_unpacker.rb +0 -19
  81. data/spec/cruby/unpacker_spec.rb +0 -70
  82. data/spec/ext_value_spec.rb +0 -99
  83. data/spec/exttypes.rb +0 -51
  84. data/spec/factory_spec.rb +0 -367
  85. data/spec/format_spec.rb +0 -301
  86. data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
  87. data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
  88. data/spec/jruby/unpacker_spec.rb +0 -186
  89. data/spec/msgpack_spec.rb +0 -214
  90. data/spec/pack_spec.rb +0 -61
  91. data/spec/packer_spec.rb +0 -557
  92. data/spec/random_compat.rb +0 -24
  93. data/spec/spec_helper.rb +0 -38
  94. data/spec/timestamp_spec.rb +0 -121
  95. data/spec/unpack_spec.rb +0 -57
  96. data/spec/unpacker_spec.rb +0 -716
data/ext/msgpack/buffer.c CHANGED
@@ -19,42 +19,28 @@
19
19
  #include "buffer.h"
20
20
  #include "rmem.h"
21
21
 
22
- #ifndef HAVE_RB_STR_REPLACE
23
- static ID s_replace;
24
- #endif
25
-
26
- #ifdef COMPAT_HAVE_ENCODING /* see compat.h*/
27
22
  int msgpack_rb_encindex_utf8;
28
23
  int msgpack_rb_encindex_usascii;
29
24
  int msgpack_rb_encindex_ascii8bit;
30
- #endif
31
25
 
32
- #ifndef DISABLE_RMEM
26
+ ID s_uminus;
27
+
33
28
  static msgpack_rmem_t s_rmem;
34
- #endif
35
29
 
36
- void msgpack_buffer_static_init()
30
+ void msgpack_buffer_static_init(void)
37
31
  {
38
- #ifdef COMPAT_HAVE_ENCODING
32
+ s_uminus = rb_intern("-@");
33
+
39
34
  msgpack_rb_encindex_utf8 = rb_utf8_encindex();
40
35
  msgpack_rb_encindex_usascii = rb_usascii_encindex();
41
36
  msgpack_rb_encindex_ascii8bit = rb_ascii8bit_encindex();
42
- #endif
43
37
 
44
- #ifndef DISABLE_RMEM
45
38
  msgpack_rmem_init(&s_rmem);
46
- #endif
47
-
48
- #ifndef HAVE_RB_STR_REPLACE
49
- s_replace = rb_intern("replace");
50
- #endif
51
39
  }
52
40
 
53
- void msgpack_buffer_static_destroy()
41
+ void msgpack_buffer_static_destroy(void)
54
42
  {
55
- #ifndef DISABLE_RMEM
56
43
  msgpack_rmem_destroy(&s_rmem);
57
- #endif
58
44
  }
59
45
 
60
46
  void msgpack_buffer_init(msgpack_buffer_t* b)
@@ -72,16 +58,16 @@ void msgpack_buffer_init(msgpack_buffer_t* b)
72
58
  static void _msgpack_buffer_chunk_destroy(msgpack_buffer_chunk_t* c)
73
59
  {
74
60
  if(c->mem != NULL) {
75
- #ifndef DISABLE_RMEM
76
- if(!msgpack_rmem_free(&s_rmem, c->mem)) {
61
+ if(c->rmem) {
62
+ if(!msgpack_rmem_free(&s_rmem, c->mem)) {
63
+ rb_bug("Failed to free an rmem pointer, memory leak?");
64
+ }
65
+ } else {
77
66
  xfree(c->mem);
78
67
  }
79
68
  /* no needs to update rmem_owner because chunks will not be
80
69
  * free()ed (left in free_list) and thus *rmem_owner is
81
70
  * always valid. */
82
- #else
83
- xfree(c->mem);
84
- #endif
85
71
  }
86
72
  c->first = NULL;
87
73
  c->last = NULL;
@@ -108,8 +94,25 @@ void msgpack_buffer_destroy(msgpack_buffer_t* b)
108
94
  }
109
95
  }
110
96
 
111
- void msgpack_buffer_mark(msgpack_buffer_t* b)
97
+ size_t msgpack_buffer_memsize(const msgpack_buffer_t* b)
112
98
  {
99
+ size_t memsize = 0;
100
+ msgpack_buffer_chunk_t* c = b->head;
101
+
102
+ while(c) {
103
+ memsize += sizeof(msgpack_buffer_chunk_t);
104
+ if(c->mapped_string != NO_MAPPED_STRING) {
105
+ memsize += (c->last - c->first);
106
+ }
107
+ c = c->next;
108
+ }
109
+
110
+ return memsize;
111
+ }
112
+
113
+ void msgpack_buffer_mark(void *ptr)
114
+ {
115
+ msgpack_buffer_t* b = ptr;
113
116
  /* head is always available */
114
117
  msgpack_buffer_chunk_t* c = b->head;
115
118
  while(c != &b->tail) {
@@ -120,8 +123,6 @@ void msgpack_buffer_mark(msgpack_buffer_t* b)
120
123
 
121
124
  rb_gc_mark(b->io);
122
125
  rb_gc_mark(b->io_buffer);
123
-
124
- rb_gc_mark(b->owner);
125
126
  }
126
127
 
127
128
  bool _msgpack_buffer_shift_chunk(msgpack_buffer_t* b)
@@ -158,24 +159,17 @@ size_t msgpack_buffer_read_to_string_nonblock(msgpack_buffer_t* b, VALUE string,
158
159
  {
159
160
  size_t avail = msgpack_buffer_top_readable_size(b);
160
161
 
161
- #ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE
162
162
  /* optimize */
163
163
  if(length <= avail && RSTRING_LEN(string) == 0 &&
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);
176
171
  return length;
177
172
  }
178
- #endif
179
173
 
180
174
  size_t const length_orig = length;
181
175
 
@@ -257,12 +251,14 @@ bool _msgpack_buffer_read_all2(msgpack_buffer_t* b, char* buffer, size_t length)
257
251
 
258
252
  static inline msgpack_buffer_chunk_t* _msgpack_buffer_alloc_new_chunk(msgpack_buffer_t* b)
259
253
  {
260
- msgpack_buffer_chunk_t* reuse = b->free_list;
261
- if(reuse == NULL) {
262
- return xmalloc(sizeof(msgpack_buffer_chunk_t));
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));
263
259
  }
264
- b->free_list = b->free_list->next;
265
- return reuse;
260
+ memset(chunk, 0, sizeof(msgpack_buffer_chunk_t));
261
+ return chunk;
266
262
  }
267
263
 
268
264
  static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
@@ -288,15 +284,11 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
288
284
 
289
285
  msgpack_buffer_chunk_t* nc = _msgpack_buffer_alloc_new_chunk(b);
290
286
 
291
- #ifndef DISABLE_RMEM
292
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
293
287
  if(b->rmem_last == b->tail_buffer_end) {
294
288
  /* reuse unused rmem space */
295
289
  size_t unused = b->tail_buffer_end - b->tail.last;
296
290
  b->rmem_last -= unused;
297
291
  }
298
- #endif
299
- #endif
300
292
 
301
293
  /* rebuild tail */
302
294
  *nc = b->tail;
@@ -307,10 +299,13 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
307
299
 
308
300
  static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE string)
309
301
  {
310
- VALUE mapped_string = rb_str_dup(string);
311
- #ifdef COMPAT_HAVE_ENCODING
312
- ENCODING_SET(mapped_string, msgpack_rb_encindex_ascii8bit);
313
- #endif
302
+ VALUE mapped_string;
303
+ if(ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit && RTEST(rb_obj_frozen_p(string))) {
304
+ mapped_string = string;
305
+ } else {
306
+ mapped_string = rb_str_dup(string);
307
+ ENCODING_SET(mapped_string, msgpack_rb_encindex_ascii8bit);
308
+ }
314
309
 
315
310
  _msgpack_buffer_add_new_chunk(b);
316
311
 
@@ -333,29 +328,15 @@ static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE s
333
328
 
334
329
  void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
335
330
  {
336
- size_t length = RSTRING_LEN(string);
337
-
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
- } else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
344
- VALUE s = rb_str_dup(string);
345
- ENCODING_SET(s, msgpack_rb_encindex_ascii8bit);
346
- rb_funcall(b->io, b->io_write_all_method, 1, s);
347
335
  } else {
348
- msgpack_buffer_append(b, RSTRING_PTR(string), length);
336
+ msgpack_buffer_append(b, RSTRING_PTR(string), RSTRING_LEN(string));
349
337
  }
350
- #else
351
- rb_funcall(b->io, b->io_write_all_method, 1, string);
352
- #endif
353
-
354
- } else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
355
- _msgpack_buffer_append_reference(b, string);
356
-
357
338
  } else {
358
- msgpack_buffer_append(b, RSTRING_PTR(string), length);
339
+ _msgpack_buffer_append_reference(b, string);
359
340
  }
360
341
  }
361
342
 
@@ -363,11 +344,10 @@ static inline void* _msgpack_buffer_chunk_malloc(
363
344
  msgpack_buffer_t* b, msgpack_buffer_chunk_t* c,
364
345
  size_t required_size, size_t* allocated_size)
365
346
  {
366
- #ifndef DISABLE_RMEM
367
347
  if(required_size <= MSGPACK_RMEM_PAGE_SIZE) {
368
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
348
+ c->rmem = true;
349
+
369
350
  if((size_t)(b->rmem_end - b->rmem_last) < required_size) {
370
- #endif
371
351
  /* alloc new rmem page */
372
352
  *allocated_size = MSGPACK_RMEM_PAGE_SIZE;
373
353
  char* buffer = msgpack_rmem_alloc(&s_rmem);
@@ -378,8 +358,6 @@ static inline void* _msgpack_buffer_chunk_malloc(
378
358
  b->rmem_last = b->rmem_end = buffer + MSGPACK_RMEM_PAGE_SIZE;
379
359
 
380
360
  return buffer;
381
-
382
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
383
361
  } else {
384
362
  /* reuse unused rmem */
385
363
  *allocated_size = (size_t)(b->rmem_end - b->rmem_last);
@@ -393,18 +371,13 @@ static inline void* _msgpack_buffer_chunk_malloc(
393
371
 
394
372
  return buffer;
395
373
  }
396
- #endif
397
374
  }
398
- #else
399
- if(required_size < 72) {
400
- required_size = 72;
401
- }
402
- #endif
403
375
 
404
376
  // TODO alignment?
405
377
  *allocated_size = required_size;
406
378
  void* mem = xmalloc(required_size);
407
379
  c->mem = mem;
380
+ c->rmem = false;
408
381
  return mem;
409
382
  }
410
383
 
@@ -454,11 +427,7 @@ void _msgpack_buffer_expand(msgpack_buffer_t* b, const char* data, size_t length
454
427
  size_t capacity = b->tail.last - b->tail.first;
455
428
 
456
429
  /* can't realloc mapped chunk or rmem page */
457
- if(b->tail.mapped_string != NO_MAPPED_STRING
458
- #ifndef DISABLE_RMEM
459
- || capacity <= MSGPACK_RMEM_PAGE_SIZE
460
- #endif
461
- ) {
430
+ if(b->tail.mapped_string != NO_MAPPED_STRING || capacity <= MSGPACK_RMEM_PAGE_SIZE) {
462
431
  /* allocate new chunk */
463
432
  _msgpack_buffer_add_new_chunk(b);
464
433
 
@@ -631,13 +600,13 @@ size_t msgpack_buffer_flush_to_io(msgpack_buffer_t* b, VALUE io, ID write_method
631
600
  size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
632
601
  {
633
602
  if(b->io_buffer == Qnil) {
634
- b->io_buffer = rb_funcall(b->io, b->io_partial_read_method, 1, LONG2NUM(b->io_buffer_size));
603
+ b->io_buffer = rb_funcall(b->io, b->io_partial_read_method, 1, SIZET2NUM(b->io_buffer_size));
635
604
  if(b->io_buffer == Qnil) {
636
605
  rb_raise(rb_eEOFError, "IO reached end of file");
637
606
  }
638
607
  StringValue(b->io_buffer);
639
608
  } else {
640
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(b->io_buffer_size), b->io_buffer);
609
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(b->io_buffer_size), b->io_buffer);
641
610
  if(ret == Qnil) {
642
611
  rb_raise(rb_eEOFError, "IO reached end of file");
643
612
  }
@@ -656,9 +625,11 @@ size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
656
625
 
657
626
  size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string, size_t length)
658
627
  {
628
+ #define MIN(x, y) (((x) < (y)) ? (x) : (y))
629
+
659
630
  if(RSTRING_LEN(string) == 0) {
660
631
  /* direct read */
661
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(length), string);
632
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(MIN(b->io_buffer_size, length)), string);
662
633
  if(ret == Qnil) {
663
634
  return 0;
664
635
  }
@@ -670,7 +641,7 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
670
641
  b->io_buffer = rb_str_buf_new(0);
671
642
  }
672
643
 
673
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(length), b->io_buffer);
644
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(MIN(b->io_buffer_size, length)), b->io_buffer);
674
645
  if(ret == Qnil) {
675
646
  return 0;
676
647
  }
@@ -678,6 +649,8 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
678
649
 
679
650
  rb_str_buf_cat(string, (const void*)RSTRING_PTR(b->io_buffer), rl);
680
651
  return rl;
652
+
653
+ #undef MIN
681
654
  }
682
655
 
683
656
  size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
@@ -686,7 +659,7 @@ size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
686
659
  b->io_buffer = rb_str_buf_new(0);
687
660
  }
688
661
 
689
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(length), b->io_buffer);
662
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(length), b->io_buffer);
690
663
  if(ret == Qnil) {
691
664
  return 0;
692
665
  }
data/ext/msgpack/buffer.h CHANGED
@@ -49,11 +49,15 @@
49
49
 
50
50
  #define NO_MAPPED_STRING ((VALUE)0)
51
51
 
52
- #ifdef COMPAT_HAVE_ENCODING /* see compat.h*/
52
+ #ifndef RB_ENC_INTERNED_STR_NULL_CHECK
53
+ #define RB_ENC_INTERNED_STR_NULL_CHECK 0
54
+ #endif
55
+
53
56
  extern int msgpack_rb_encindex_utf8;
54
57
  extern int msgpack_rb_encindex_usascii;
55
58
  extern int msgpack_rb_encindex_ascii8bit;
56
- #endif
59
+
60
+ extern ID s_uminus;
57
61
 
58
62
  struct msgpack_buffer_chunk_t;
59
63
  typedef struct msgpack_buffer_chunk_t msgpack_buffer_chunk_t;
@@ -74,6 +78,7 @@ struct msgpack_buffer_chunk_t {
74
78
  void* mem;
75
79
  msgpack_buffer_chunk_t* next;
76
80
  VALUE mapped_string; /* RBString or NO_MAPPED_STRING */
81
+ bool rmem;
77
82
  };
78
83
 
79
84
  union msgpack_buffer_cast_block_t {
@@ -98,11 +103,9 @@ struct msgpack_buffer_t {
98
103
  msgpack_buffer_chunk_t* head;
99
104
  msgpack_buffer_chunk_t* free_list;
100
105
 
101
- #ifndef DISABLE_RMEM
102
106
  char* rmem_last;
103
107
  char* rmem_end;
104
108
  void** rmem_owner;
105
- #endif
106
109
 
107
110
  union msgpack_buffer_cast_block_t cast_block;
108
111
 
@@ -114,25 +117,25 @@ struct msgpack_buffer_t {
114
117
  size_t write_reference_threshold;
115
118
  size_t read_reference_threshold;
116
119
  size_t io_buffer_size;
117
-
118
- VALUE owner;
119
120
  };
120
121
 
121
122
  /*
122
123
  * initialization functions
123
124
  */
124
- void msgpack_buffer_static_init();
125
+ void msgpack_buffer_static_init(void);
125
126
 
126
- void msgpack_buffer_static_destroy();
127
+ void msgpack_buffer_static_destroy(void);
127
128
 
128
129
  void msgpack_buffer_init(msgpack_buffer_t* b);
129
130
 
130
131
  void msgpack_buffer_destroy(msgpack_buffer_t* b);
131
132
 
132
- void msgpack_buffer_mark(msgpack_buffer_t* b);
133
+ void msgpack_buffer_mark(void* b);
133
134
 
134
135
  void msgpack_buffer_clear(msgpack_buffer_t* b);
135
136
 
137
+ size_t msgpack_buffer_memsize(const msgpack_buffer_t* b);
138
+
136
139
  static inline void msgpack_buffer_set_write_reference_threshold(msgpack_buffer_t* b, size_t length)
137
140
  {
138
141
  if(length < MSGPACK_BUFFER_STRING_WRITE_REFERENCE_MINIMUM) {
@@ -265,14 +268,9 @@ static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE str
265
268
  static inline size_t msgpack_buffer_append_string_reference(msgpack_buffer_t* b, VALUE string)
266
269
  {
267
270
  size_t length = RSTRING_LEN(string);
268
-
269
- if(length > MSGPACK_BUFFER_STRING_WRITE_REFERENCE_MINIMUM) {
271
+ if (length > 0) {
270
272
  _msgpack_buffer_append_long_string(b, string);
271
-
272
- } else {
273
- msgpack_buffer_append(b, RSTRING_PTR(string), length);
274
273
  }
275
-
276
274
  return length;
277
275
  }
278
276
 
@@ -438,24 +436,65 @@ static inline VALUE _msgpack_buffer_refer_head_mapped_string(msgpack_buffer_t* b
438
436
  return rb_str_substr(b->head->mapped_string, offset, length);
439
437
  }
440
438
 
441
- static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen)
439
+ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen, bool utf8)
442
440
  {
443
- #ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE
444
441
  /* optimize */
445
442
  if(!will_be_frozen &&
446
443
  b->head->mapped_string != NO_MAPPED_STRING &&
447
444
  length >= b->read_reference_threshold) {
448
445
  VALUE result = _msgpack_buffer_refer_head_mapped_string(b, length);
446
+ if (utf8) ENCODING_SET(result, msgpack_rb_encindex_utf8);
449
447
  _msgpack_buffer_consumed(b, length);
450
448
  return result;
451
449
  }
452
- #endif
453
450
 
454
- VALUE result = rb_str_new(b->read_buffer, length);
451
+ VALUE result;
452
+
453
+ #ifdef HAVE_RB_ENC_INTERNED_STR
454
+ if (will_be_frozen) {
455
+ if (RB_ENC_INTERNED_STR_NULL_CHECK && length == 0) {
456
+ result = rb_enc_interned_str("", length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
457
+ } else {
458
+ result = rb_enc_interned_str(b->read_buffer, length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
459
+ }
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
+ }
467
+ _msgpack_buffer_consumed(b, length);
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 (will_be_frozen) {
479
+ #if STR_UMINUS_DEDUPE_FROZEN
480
+ // Starting from MRI 2.8 it is preferable to freeze the string
481
+ // before deduplication so that it can be interned directly
482
+ // otherwise it would be duplicated first which is wasteful.
483
+ rb_str_freeze(result);
484
+ #endif //STR_UMINUS_DEDUPE_FROZEN
485
+ // MRI 2.5 and older do not deduplicate strings that are already
486
+ // frozen.
487
+ result = rb_funcall(result, s_uminus, 0);
488
+ }
455
489
  _msgpack_buffer_consumed(b, length);
456
490
  return result;
491
+
492
+ #endif // HAVE_RB_ENC_INTERNED_STR
457
493
  }
458
494
 
495
+ static inline VALUE msgpack_buffer_read_top_as_symbol(msgpack_buffer_t* b, size_t length, bool utf8)
496
+ {
497
+ return rb_str_intern(msgpack_buffer_read_top_as_string(b, length, true, utf8));
498
+ }
459
499
 
460
500
  #endif
461
-