msgpack 1.4.2 → 1.7.3

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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +89 -0
  3. data/README.md +73 -13
  4. data/ext/java/org/msgpack/jruby/Buffer.java +26 -19
  5. data/ext/java/org/msgpack/jruby/Decoder.java +29 -21
  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 +80 -73
  12. data/ext/msgpack/buffer.c +54 -74
  13. data/ext/msgpack/buffer.h +21 -18
  14. data/ext/msgpack/buffer_class.c +161 -52
  15. data/ext/msgpack/buffer_class.h +1 -0
  16. data/ext/msgpack/compat.h +0 -99
  17. data/ext/msgpack/extconf.rb +25 -46
  18. data/ext/msgpack/factory_class.c +143 -87
  19. data/ext/msgpack/packer.c +66 -43
  20. data/ext/msgpack/packer.h +25 -20
  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 +136 -111
  29. data/ext/msgpack/unpacker.h +16 -13
  30. data/ext/msgpack/unpacker_class.c +86 -126
  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 +1 -1
  42. data/lib/msgpack.rb +6 -7
  43. data/msgpack.gemspec +8 -5
  44. metadata +37 -82
  45. data/.gitignore +0 -23
  46. data/.rubocop.yml +0 -36
  47. data/.travis.yml +0 -39
  48. data/Gemfile +0 -9
  49. data/Rakefile +0 -71
  50. data/appveyor.yml +0 -18
  51. data/bench/pack.rb +0 -23
  52. data/bench/pack_log.rb +0 -33
  53. data/bench/pack_log_long.rb +0 -65
  54. data/bench/pack_symbols.rb +0 -28
  55. data/bench/run.sh +0 -14
  56. data/bench/run_long.sh +0 -35
  57. data/bench/run_symbols.sh +0 -26
  58. data/bench/unpack.rb +0 -21
  59. data/bench/unpack_log.rb +0 -34
  60. data/bench/unpack_log_long.rb +0 -67
  61. data/doclib/msgpack/buffer.rb +0 -193
  62. data/doclib/msgpack/core_ext.rb +0 -101
  63. data/doclib/msgpack/error.rb +0 -19
  64. data/doclib/msgpack/extension_value.rb +0 -9
  65. data/doclib/msgpack/factory.rb +0 -101
  66. data/doclib/msgpack/packer.rb +0 -208
  67. data/doclib/msgpack/time.rb +0 -22
  68. data/doclib/msgpack/timestamp.rb +0 -44
  69. data/doclib/msgpack/unpacker.rb +0 -183
  70. data/doclib/msgpack.rb +0 -87
  71. data/msgpack.org.md +0 -46
  72. data/spec/cases.json +0 -1
  73. data/spec/cases.msg +0 -0
  74. data/spec/cases_compact.msg +0 -0
  75. data/spec/cases_spec.rb +0 -39
  76. data/spec/cruby/buffer_io_spec.rb +0 -255
  77. data/spec/cruby/buffer_packer.rb +0 -29
  78. data/spec/cruby/buffer_spec.rb +0 -575
  79. data/spec/cruby/buffer_unpacker.rb +0 -19
  80. data/spec/cruby/unpacker_spec.rb +0 -70
  81. data/spec/ext_value_spec.rb +0 -99
  82. data/spec/exttypes.rb +0 -51
  83. data/spec/factory_spec.rb +0 -367
  84. data/spec/format_spec.rb +0 -301
  85. data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
  86. data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
  87. data/spec/jruby/unpacker_spec.rb +0 -186
  88. data/spec/msgpack_spec.rb +0 -214
  89. data/spec/pack_spec.rb +0 -61
  90. data/spec/packer_spec.rb +0 -557
  91. data/spec/random_compat.rb +0 -24
  92. data/spec/spec_helper.rb +0 -55
  93. data/spec/timestamp_spec.rb +0 -121
  94. data/spec/unpack_spec.rb +0 -57
  95. data/spec/unpacker_spec.rb +0 -819
data/ext/msgpack/buffer.c CHANGED
@@ -19,21 +19,15 @@
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
22
  int msgpack_rb_encindex_utf8;
27
23
  int msgpack_rb_encindex_usascii;
28
24
  int msgpack_rb_encindex_ascii8bit;
29
25
 
30
26
  ID s_uminus;
31
27
 
32
- #ifndef DISABLE_RMEM
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
32
  s_uminus = rb_intern("-@");
39
33
 
@@ -41,20 +35,12 @@ void msgpack_buffer_static_init()
41
35
  msgpack_rb_encindex_usascii = rb_usascii_encindex();
42
36
  msgpack_rb_encindex_ascii8bit = rb_ascii8bit_encindex();
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)
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)
112
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,8 +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
- ENCODING_SET(mapped_string, msgpack_rb_encindex_ascii8bit);
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
+ }
312
309
 
313
310
  _msgpack_buffer_add_new_chunk(b);
314
311
 
@@ -331,24 +328,15 @@ static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE s
331
328
 
332
329
  void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
333
330
  {
334
- size_t length = RSTRING_LEN(string);
335
-
336
331
  if(b->io != Qnil) {
337
332
  msgpack_buffer_flush(b);
338
333
  if (ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit) {
339
334
  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
335
  } else {
345
- msgpack_buffer_append(b, RSTRING_PTR(string), length);
336
+ msgpack_buffer_append(b, RSTRING_PTR(string), RSTRING_LEN(string));
346
337
  }
347
- } else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
348
- _msgpack_buffer_append_reference(b, string);
349
-
350
338
  } else {
351
- msgpack_buffer_append(b, RSTRING_PTR(string), length);
339
+ _msgpack_buffer_append_reference(b, string);
352
340
  }
353
341
  }
354
342
 
@@ -356,11 +344,10 @@ static inline void* _msgpack_buffer_chunk_malloc(
356
344
  msgpack_buffer_t* b, msgpack_buffer_chunk_t* c,
357
345
  size_t required_size, size_t* allocated_size)
358
346
  {
359
- #ifndef DISABLE_RMEM
360
347
  if(required_size <= MSGPACK_RMEM_PAGE_SIZE) {
361
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
348
+ c->rmem = true;
349
+
362
350
  if((size_t)(b->rmem_end - b->rmem_last) < required_size) {
363
- #endif
364
351
  /* alloc new rmem page */
365
352
  *allocated_size = MSGPACK_RMEM_PAGE_SIZE;
366
353
  char* buffer = msgpack_rmem_alloc(&s_rmem);
@@ -371,8 +358,6 @@ static inline void* _msgpack_buffer_chunk_malloc(
371
358
  b->rmem_last = b->rmem_end = buffer + MSGPACK_RMEM_PAGE_SIZE;
372
359
 
373
360
  return buffer;
374
-
375
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
376
361
  } else {
377
362
  /* reuse unused rmem */
378
363
  *allocated_size = (size_t)(b->rmem_end - b->rmem_last);
@@ -386,18 +371,13 @@ static inline void* _msgpack_buffer_chunk_malloc(
386
371
 
387
372
  return buffer;
388
373
  }
389
- #endif
390
374
  }
391
- #else
392
- if(required_size < 72) {
393
- required_size = 72;
394
- }
395
- #endif
396
375
 
397
376
  // TODO alignment?
398
377
  *allocated_size = required_size;
399
378
  void* mem = xmalloc(required_size);
400
379
  c->mem = mem;
380
+ c->rmem = false;
401
381
  return mem;
402
382
  }
403
383
 
@@ -447,11 +427,7 @@ void _msgpack_buffer_expand(msgpack_buffer_t* b, const char* data, size_t length
447
427
  size_t capacity = b->tail.last - b->tail.first;
448
428
 
449
429
  /* 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
- ) {
430
+ if(b->tail.mapped_string != NO_MAPPED_STRING || capacity <= MSGPACK_RMEM_PAGE_SIZE) {
455
431
  /* allocate new chunk */
456
432
  _msgpack_buffer_add_new_chunk(b);
457
433
 
@@ -624,13 +600,13 @@ size_t msgpack_buffer_flush_to_io(msgpack_buffer_t* b, VALUE io, ID write_method
624
600
  size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
625
601
  {
626
602
  if(b->io_buffer == Qnil) {
627
- 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));
628
604
  if(b->io_buffer == Qnil) {
629
605
  rb_raise(rb_eEOFError, "IO reached end of file");
630
606
  }
631
607
  StringValue(b->io_buffer);
632
608
  } else {
633
- 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);
634
610
  if(ret == Qnil) {
635
611
  rb_raise(rb_eEOFError, "IO reached end of file");
636
612
  }
@@ -649,9 +625,11 @@ size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
649
625
 
650
626
  size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string, size_t length)
651
627
  {
628
+ #define MIN(x, y) (((x) < (y)) ? (x) : (y))
629
+
652
630
  if(RSTRING_LEN(string) == 0) {
653
631
  /* direct read */
654
- 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);
655
633
  if(ret == Qnil) {
656
634
  return 0;
657
635
  }
@@ -663,7 +641,7 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
663
641
  b->io_buffer = rb_str_buf_new(0);
664
642
  }
665
643
 
666
- 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);
667
645
  if(ret == Qnil) {
668
646
  return 0;
669
647
  }
@@ -671,6 +649,8 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
671
649
 
672
650
  rb_str_buf_cat(string, (const void*)RSTRING_PTR(b->io_buffer), rl);
673
651
  return rl;
652
+
653
+ #undef MIN
674
654
  }
675
655
 
676
656
  size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
@@ -679,7 +659,7 @@ size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
679
659
  b->io_buffer = rb_str_buf_new(0);
680
660
  }
681
661
 
682
- 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);
683
663
  if(ret == Qnil) {
684
664
  return 0;
685
665
  }
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;
@@ -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
 
@@ -440,7 +438,6 @@ static inline VALUE _msgpack_buffer_refer_head_mapped_string(msgpack_buffer_t* b
440
438
 
441
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 &&
@@ -450,13 +447,16 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
450
447
  _msgpack_buffer_consumed(b, length);
451
448
  return result;
452
449
  }
453
- #endif
454
450
 
455
451
  VALUE result;
456
452
 
457
453
  #ifdef HAVE_RB_ENC_INTERNED_STR
458
454
  if (will_be_frozen) {
459
- result = rb_enc_interned_str(b->read_buffer, length, utf8 ? rb_utf8_encoding() : rb_ascii8bit_encoding());
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
460
  } else {
461
461
  if (utf8) {
462
462
  result = rb_utf8_str_new(b->read_buffer, length);
@@ -475,7 +475,6 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
475
475
  result = rb_str_new(b->read_buffer, length);
476
476
  }
477
477
 
478
- #if STR_UMINUS_DEDUPE
479
478
  if (will_be_frozen) {
480
479
  #if STR_UMINUS_DEDUPE_FROZEN
481
480
  // Starting from MRI 2.8 it is preferable to freeze the string
@@ -487,11 +486,15 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
487
486
  // frozen.
488
487
  result = rb_funcall(result, s_uminus, 0);
489
488
  }
490
- #endif // STR_UMINUS_DEDUPE
491
489
  _msgpack_buffer_consumed(b, length);
492
490
  return result;
493
491
 
494
492
  #endif // HAVE_RB_ENC_INTERNED_STR
495
493
  }
496
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
+ }
499
+
497
500
  #endif