msgpack 1.3.3 → 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 (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
-