msgpack 1.5.1 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +55 -0
  3. data/README.md +30 -1
  4. data/ext/java/org/msgpack/jruby/Buffer.java +3 -3
  5. data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +11 -20
  6. data/ext/java/org/msgpack/jruby/ExtensionValue.java +1 -1
  7. data/ext/java/org/msgpack/jruby/Factory.java +11 -50
  8. data/ext/java/org/msgpack/jruby/Packer.java +9 -24
  9. data/ext/java/org/msgpack/jruby/Unpacker.java +15 -32
  10. data/ext/msgpack/buffer.c +54 -69
  11. data/ext/msgpack/buffer.h +16 -18
  12. data/ext/msgpack/buffer_class.c +138 -37
  13. data/ext/msgpack/buffer_class.h +1 -0
  14. data/ext/msgpack/compat.h +0 -99
  15. data/ext/msgpack/extconf.rb +25 -39
  16. data/ext/msgpack/factory_class.c +75 -86
  17. data/ext/msgpack/packer.c +12 -39
  18. data/ext/msgpack/packer.h +1 -11
  19. data/ext/msgpack/packer_class.c +73 -99
  20. data/ext/msgpack/packer_class.h +11 -0
  21. data/ext/msgpack/packer_ext_registry.c +31 -28
  22. data/ext/msgpack/packer_ext_registry.h +10 -14
  23. data/ext/msgpack/rbinit.c +1 -1
  24. data/ext/msgpack/rmem.c +3 -4
  25. data/ext/msgpack/sysdep.h +5 -2
  26. data/ext/msgpack/unpacker.c +66 -94
  27. data/ext/msgpack/unpacker.h +13 -12
  28. data/ext/msgpack/unpacker_class.c +64 -80
  29. data/ext/msgpack/unpacker_class.h +11 -0
  30. data/ext/msgpack/unpacker_ext_registry.c +4 -16
  31. data/ext/msgpack/unpacker_ext_registry.h +3 -7
  32. data/lib/msgpack/buffer.rb +9 -0
  33. data/lib/msgpack/factory.rb +90 -63
  34. data/lib/msgpack/packer.rb +10 -1
  35. data/lib/msgpack/unpacker.rb +14 -1
  36. data/lib/msgpack/version.rb +1 -1
  37. data/lib/msgpack.rb +1 -0
  38. data/msgpack.gemspec +7 -3
  39. metadata +33 -56
  40. data/.github/workflows/ci.yaml +0 -57
  41. data/.gitignore +0 -23
  42. data/.rubocop.yml +0 -36
  43. data/Gemfile +0 -9
  44. data/Rakefile +0 -70
  45. data/appveyor.yml +0 -18
  46. data/bench/pack.rb +0 -23
  47. data/bench/pack_log.rb +0 -33
  48. data/bench/pack_log_long.rb +0 -65
  49. data/bench/pack_symbols.rb +0 -28
  50. data/bench/run.sh +0 -14
  51. data/bench/run_long.sh +0 -35
  52. data/bench/run_symbols.sh +0 -26
  53. data/bench/unpack.rb +0 -21
  54. data/bench/unpack_log.rb +0 -34
  55. data/bench/unpack_log_long.rb +0 -67
  56. data/doclib/msgpack/buffer.rb +0 -193
  57. data/doclib/msgpack/core_ext.rb +0 -101
  58. data/doclib/msgpack/error.rb +0 -19
  59. data/doclib/msgpack/extension_value.rb +0 -9
  60. data/doclib/msgpack/factory.rb +0 -145
  61. data/doclib/msgpack/packer.rb +0 -209
  62. data/doclib/msgpack/time.rb +0 -22
  63. data/doclib/msgpack/timestamp.rb +0 -44
  64. data/doclib/msgpack/unpacker.rb +0 -183
  65. data/doclib/msgpack.rb +0 -87
  66. data/msgpack.org.md +0 -46
  67. data/spec/bigint_spec.rb +0 -26
  68. data/spec/cases.json +0 -1
  69. data/spec/cases.msg +0 -0
  70. data/spec/cases_compact.msg +0 -0
  71. data/spec/cases_spec.rb +0 -39
  72. data/spec/cruby/buffer_io_spec.rb +0 -255
  73. data/spec/cruby/buffer_packer.rb +0 -29
  74. data/spec/cruby/buffer_spec.rb +0 -575
  75. data/spec/cruby/buffer_unpacker.rb +0 -19
  76. data/spec/cruby/unpacker_spec.rb +0 -70
  77. data/spec/ext_value_spec.rb +0 -99
  78. data/spec/exttypes.rb +0 -51
  79. data/spec/factory_spec.rb +0 -654
  80. data/spec/format_spec.rb +0 -301
  81. data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
  82. data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
  83. data/spec/jruby/unpacker_spec.rb +0 -186
  84. data/spec/msgpack_spec.rb +0 -214
  85. data/spec/pack_spec.rb +0 -61
  86. data/spec/packer_spec.rb +0 -575
  87. data/spec/random_compat.rb +0 -24
  88. data/spec/spec_helper.rb +0 -65
  89. data/spec/timestamp_spec.rb +0 -159
  90. data/spec/unpack_spec.rb +0 -57
  91. data/spec/unpacker_spec.rb +0 -847
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,7 +159,6 @@ 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 &&
@@ -170,7 +170,6 @@ size_t msgpack_buffer_read_to_string_nonblock(msgpack_buffer_t* b, VALUE string,
170
170
  _msgpack_buffer_consumed(b, length);
171
171
  return length;
172
172
  }
173
- #endif
174
173
 
175
174
  size_t const length_orig = length;
176
175
 
@@ -252,12 +251,14 @@ bool _msgpack_buffer_read_all2(msgpack_buffer_t* b, char* buffer, size_t length)
252
251
 
253
252
  static inline msgpack_buffer_chunk_t* _msgpack_buffer_alloc_new_chunk(msgpack_buffer_t* b)
254
253
  {
255
- msgpack_buffer_chunk_t* reuse = b->free_list;
256
- if(reuse == NULL) {
257
- 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));
258
259
  }
259
- b->free_list = b->free_list->next;
260
- return reuse;
260
+ memset(chunk, 0, sizeof(msgpack_buffer_chunk_t));
261
+ return chunk;
261
262
  }
262
263
 
263
264
  static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
@@ -283,15 +284,11 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
283
284
 
284
285
  msgpack_buffer_chunk_t* nc = _msgpack_buffer_alloc_new_chunk(b);
285
286
 
286
- #ifndef DISABLE_RMEM
287
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
288
287
  if(b->rmem_last == b->tail_buffer_end) {
289
288
  /* reuse unused rmem space */
290
289
  size_t unused = b->tail_buffer_end - b->tail.last;
291
290
  b->rmem_last -= unused;
292
291
  }
293
- #endif
294
- #endif
295
292
 
296
293
  /* rebuild tail */
297
294
  *nc = b->tail;
@@ -302,8 +299,13 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
302
299
 
303
300
  static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE string)
304
301
  {
305
- VALUE mapped_string = rb_str_dup(string);
306
- 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
+ }
307
309
 
308
310
  _msgpack_buffer_add_new_chunk(b);
309
311
 
@@ -326,24 +328,15 @@ static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE s
326
328
 
327
329
  void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
328
330
  {
329
- size_t length = RSTRING_LEN(string);
330
-
331
331
  if(b->io != Qnil) {
332
332
  msgpack_buffer_flush(b);
333
333
  if (ENCODING_GET(string) == msgpack_rb_encindex_ascii8bit) {
334
334
  rb_funcall(b->io, b->io_write_all_method, 1, string);
335
- } else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
336
- VALUE s = rb_str_dup(string);
337
- ENCODING_SET(s, msgpack_rb_encindex_ascii8bit);
338
- rb_funcall(b->io, b->io_write_all_method, 1, s);
339
335
  } else {
340
- msgpack_buffer_append(b, RSTRING_PTR(string), length);
336
+ msgpack_buffer_append(b, RSTRING_PTR(string), RSTRING_LEN(string));
341
337
  }
342
- } else if(!STR_DUP_LIKELY_DOES_COPY(string)) {
343
- _msgpack_buffer_append_reference(b, string);
344
-
345
338
  } else {
346
- msgpack_buffer_append(b, RSTRING_PTR(string), length);
339
+ _msgpack_buffer_append_reference(b, string);
347
340
  }
348
341
  }
349
342
 
@@ -351,11 +344,10 @@ static inline void* _msgpack_buffer_chunk_malloc(
351
344
  msgpack_buffer_t* b, msgpack_buffer_chunk_t* c,
352
345
  size_t required_size, size_t* allocated_size)
353
346
  {
354
- #ifndef DISABLE_RMEM
355
347
  if(required_size <= MSGPACK_RMEM_PAGE_SIZE) {
356
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
348
+ c->rmem = true;
349
+
357
350
  if((size_t)(b->rmem_end - b->rmem_last) < required_size) {
358
- #endif
359
351
  /* alloc new rmem page */
360
352
  *allocated_size = MSGPACK_RMEM_PAGE_SIZE;
361
353
  char* buffer = msgpack_rmem_alloc(&s_rmem);
@@ -366,8 +358,6 @@ static inline void* _msgpack_buffer_chunk_malloc(
366
358
  b->rmem_last = b->rmem_end = buffer + MSGPACK_RMEM_PAGE_SIZE;
367
359
 
368
360
  return buffer;
369
-
370
- #ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
371
361
  } else {
372
362
  /* reuse unused rmem */
373
363
  *allocated_size = (size_t)(b->rmem_end - b->rmem_last);
@@ -381,18 +371,13 @@ static inline void* _msgpack_buffer_chunk_malloc(
381
371
 
382
372
  return buffer;
383
373
  }
384
- #endif
385
374
  }
386
- #else
387
- if(required_size < 72) {
388
- required_size = 72;
389
- }
390
- #endif
391
375
 
392
376
  // TODO alignment?
393
377
  *allocated_size = required_size;
394
378
  void* mem = xmalloc(required_size);
395
379
  c->mem = mem;
380
+ c->rmem = false;
396
381
  return mem;
397
382
  }
398
383
 
@@ -442,11 +427,7 @@ void _msgpack_buffer_expand(msgpack_buffer_t* b, const char* data, size_t length
442
427
  size_t capacity = b->tail.last - b->tail.first;
443
428
 
444
429
  /* can't realloc mapped chunk or rmem page */
445
- if(b->tail.mapped_string != NO_MAPPED_STRING
446
- #ifndef DISABLE_RMEM
447
- || capacity <= MSGPACK_RMEM_PAGE_SIZE
448
- #endif
449
- ) {
430
+ if(b->tail.mapped_string != NO_MAPPED_STRING || capacity <= MSGPACK_RMEM_PAGE_SIZE) {
450
431
  /* allocate new chunk */
451
432
  _msgpack_buffer_add_new_chunk(b);
452
433
 
@@ -619,13 +600,13 @@ size_t msgpack_buffer_flush_to_io(msgpack_buffer_t* b, VALUE io, ID write_method
619
600
  size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
620
601
  {
621
602
  if(b->io_buffer == Qnil) {
622
- 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));
623
604
  if(b->io_buffer == Qnil) {
624
605
  rb_raise(rb_eEOFError, "IO reached end of file");
625
606
  }
626
607
  StringValue(b->io_buffer);
627
608
  } else {
628
- 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);
629
610
  if(ret == Qnil) {
630
611
  rb_raise(rb_eEOFError, "IO reached end of file");
631
612
  }
@@ -644,9 +625,11 @@ size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
644
625
 
645
626
  size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string, size_t length)
646
627
  {
628
+ #define MIN(x, y) (((x) < (y)) ? (x) : (y))
629
+
647
630
  if(RSTRING_LEN(string) == 0) {
648
631
  /* direct read */
649
- 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);
650
633
  if(ret == Qnil) {
651
634
  return 0;
652
635
  }
@@ -658,7 +641,7 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
658
641
  b->io_buffer = rb_str_buf_new(0);
659
642
  }
660
643
 
661
- 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);
662
645
  if(ret == Qnil) {
663
646
  return 0;
664
647
  }
@@ -666,6 +649,8 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
666
649
 
667
650
  rb_str_buf_cat(string, (const void*)RSTRING_PTR(b->io_buffer), rl);
668
651
  return rl;
652
+
653
+ #undef MIN
669
654
  }
670
655
 
671
656
  size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
@@ -674,7 +659,7 @@ size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
674
659
  b->io_buffer = rb_str_buf_new(0);
675
660
  }
676
661
 
677
- 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);
678
663
  if(ret == Qnil) {
679
664
  return 0;
680
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,7 +486,6 @@ 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