msgpack 1.5.4 → 1.8.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.
- checksums.yaml +4 -4
- data/ChangeLog +80 -1
- data/README.md +49 -13
- data/ext/java/org/msgpack/jruby/Buffer.java +3 -3
- data/ext/java/org/msgpack/jruby/Decoder.java +15 -7
- data/ext/java/org/msgpack/jruby/ExtensionRegistry.java +11 -20
- data/ext/java/org/msgpack/jruby/ExtensionValue.java +1 -1
- data/ext/java/org/msgpack/jruby/Factory.java +11 -50
- data/ext/java/org/msgpack/jruby/Packer.java +9 -24
- data/ext/java/org/msgpack/jruby/Unpacker.java +15 -32
- data/ext/msgpack/buffer.c +101 -58
- data/ext/msgpack/buffer.h +138 -44
- data/ext/msgpack/buffer_class.c +132 -31
- data/ext/msgpack/buffer_class.h +1 -0
- data/ext/msgpack/extconf.rb +20 -30
- data/ext/msgpack/factory_class.c +75 -86
- data/ext/msgpack/packer.c +13 -16
- data/ext/msgpack/packer.h +18 -21
- data/ext/msgpack/packer_class.c +72 -98
- data/ext/msgpack/packer_class.h +11 -0
- data/ext/msgpack/packer_ext_registry.c +31 -28
- data/ext/msgpack/packer_ext_registry.h +10 -14
- data/ext/msgpack/rbinit.c +1 -1
- data/ext/msgpack/rmem.c +3 -4
- data/ext/msgpack/sysdep.h +5 -2
- data/ext/msgpack/unpacker.c +241 -218
- data/ext/msgpack/unpacker.h +29 -31
- data/ext/msgpack/unpacker_class.c +87 -92
- data/ext/msgpack/unpacker_class.h +11 -0
- data/ext/msgpack/unpacker_ext_registry.c +4 -16
- data/ext/msgpack/unpacker_ext_registry.h +3 -7
- data/lib/msgpack/buffer.rb +9 -0
- data/lib/msgpack/factory.rb +90 -63
- data/lib/msgpack/packer.rb +10 -1
- data/lib/msgpack/unpacker.rb +14 -1
- data/lib/msgpack/version.rb +1 -1
- data/lib/msgpack.rb +1 -0
- data/msgpack.gemspec +13 -12
- metadata +13 -152
- data/.github/workflows/ci.yaml +0 -57
- data/.gitignore +0 -23
- data/.rubocop.yml +0 -36
- data/Gemfile +0 -9
- data/Rakefile +0 -70
- data/appveyor.yml +0 -18
- data/bench/bench.rb +0 -78
- data/doclib/msgpack/buffer.rb +0 -193
- data/doclib/msgpack/core_ext.rb +0 -101
- data/doclib/msgpack/error.rb +0 -19
- data/doclib/msgpack/extension_value.rb +0 -9
- data/doclib/msgpack/factory.rb +0 -145
- data/doclib/msgpack/packer.rb +0 -209
- data/doclib/msgpack/time.rb +0 -22
- data/doclib/msgpack/timestamp.rb +0 -44
- data/doclib/msgpack/unpacker.rb +0 -183
- data/doclib/msgpack.rb +0 -87
- data/msgpack.org.md +0 -46
- data/spec/bigint_spec.rb +0 -26
- data/spec/cases.json +0 -1
- data/spec/cases.msg +0 -0
- data/spec/cases_compact.msg +0 -0
- data/spec/cases_spec.rb +0 -39
- data/spec/cruby/buffer_io_spec.rb +0 -255
- data/spec/cruby/buffer_packer.rb +0 -29
- data/spec/cruby/buffer_spec.rb +0 -575
- data/spec/cruby/buffer_unpacker.rb +0 -19
- data/spec/cruby/unpacker_spec.rb +0 -70
- data/spec/ext_value_spec.rb +0 -99
- data/spec/exttypes.rb +0 -51
- data/spec/factory_spec.rb +0 -664
- data/spec/format_spec.rb +0 -301
- data/spec/jruby/benchmarks/shootout_bm.rb +0 -73
- data/spec/jruby/benchmarks/symbolize_keys_bm.rb +0 -25
- data/spec/jruby/unpacker_spec.rb +0 -186
- data/spec/msgpack_spec.rb +0 -214
- data/spec/pack_spec.rb +0 -61
- data/spec/packer_spec.rb +0 -575
- data/spec/random_compat.rb +0 -24
- data/spec/spec_helper.rb +0 -71
- data/spec/timestamp_spec.rb +0 -159
- data/spec/unpack_spec.rb +0 -57
- data/spec/unpacker_spec.rb +0 -859
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
|
-
|
|
76
|
-
|
|
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
|
-
|
|
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,12 +123,19 @@ 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)
|
|
128
129
|
{
|
|
130
|
+
if(b->rmem_owner == &b->head->mem) {
|
|
131
|
+
/* the chunk that owns the rmem page is going away and takes the page
|
|
132
|
+
* with it. don't carve the remaining space out of a page that is
|
|
133
|
+
* already back in the pool. */
|
|
134
|
+
b->rmem_end = NULL;
|
|
135
|
+
b->rmem_last = NULL;
|
|
136
|
+
b->rmem_owner = NULL;
|
|
137
|
+
}
|
|
138
|
+
|
|
129
139
|
_msgpack_buffer_chunk_destroy(b->head);
|
|
130
140
|
|
|
131
141
|
if(b->head == &b->tail) {
|
|
@@ -133,6 +143,9 @@ bool _msgpack_buffer_shift_chunk(msgpack_buffer_t* b)
|
|
|
133
143
|
* because head should be always available */
|
|
134
144
|
b->tail_buffer_end = NULL;
|
|
135
145
|
b->read_buffer = NULL;
|
|
146
|
+
b->rmem_end = NULL;
|
|
147
|
+
b->rmem_last = NULL;
|
|
148
|
+
b->rmem_owner = NULL;
|
|
136
149
|
return false;
|
|
137
150
|
}
|
|
138
151
|
|
|
@@ -158,7 +171,6 @@ size_t msgpack_buffer_read_to_string_nonblock(msgpack_buffer_t* b, VALUE string,
|
|
|
158
171
|
{
|
|
159
172
|
size_t avail = msgpack_buffer_top_readable_size(b);
|
|
160
173
|
|
|
161
|
-
#ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE
|
|
162
174
|
/* optimize */
|
|
163
175
|
if(length <= avail && RSTRING_LEN(string) == 0 &&
|
|
164
176
|
b->head->mapped_string != NO_MAPPED_STRING &&
|
|
@@ -170,7 +182,6 @@ size_t msgpack_buffer_read_to_string_nonblock(msgpack_buffer_t* b, VALUE string,
|
|
|
170
182
|
_msgpack_buffer_consumed(b, length);
|
|
171
183
|
return length;
|
|
172
184
|
}
|
|
173
|
-
#endif
|
|
174
185
|
|
|
175
186
|
size_t const length_orig = length;
|
|
176
187
|
|
|
@@ -252,12 +263,26 @@ bool _msgpack_buffer_read_all2(msgpack_buffer_t* b, char* buffer, size_t length)
|
|
|
252
263
|
|
|
253
264
|
static inline msgpack_buffer_chunk_t* _msgpack_buffer_alloc_new_chunk(msgpack_buffer_t* b)
|
|
254
265
|
{
|
|
255
|
-
msgpack_buffer_chunk_t*
|
|
256
|
-
if(
|
|
257
|
-
|
|
266
|
+
msgpack_buffer_chunk_t* chunk = b->free_list;
|
|
267
|
+
if (chunk) {
|
|
268
|
+
b->free_list = b->free_list->next;
|
|
269
|
+
} else {
|
|
270
|
+
chunk = xmalloc(sizeof(msgpack_buffer_chunk_t));
|
|
271
|
+
}
|
|
272
|
+
memset(chunk, 0, sizeof(msgpack_buffer_chunk_t));
|
|
273
|
+
return chunk;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* b->tail is copied into nc and then rebuilt, so the rmem page pointer moves
|
|
277
|
+
* to nc. the owner has to follow it: if it kept pointing at b->tail.mem, the
|
|
278
|
+
* transfer in _msgpack_buffer_chunk_malloc would degenerate into a
|
|
279
|
+
* self-assignment and the page would be released by nc while the rebuilt tail
|
|
280
|
+
* is still reading from it. */
|
|
281
|
+
static inline void _msgpack_buffer_transfer_rmem_owner(msgpack_buffer_t* b, msgpack_buffer_chunk_t* nc)
|
|
282
|
+
{
|
|
283
|
+
if(b->rmem_owner == &b->tail.mem) {
|
|
284
|
+
b->rmem_owner = &nc->mem;
|
|
258
285
|
}
|
|
259
|
-
b->free_list = b->free_list->next;
|
|
260
|
-
return reuse;
|
|
261
286
|
}
|
|
262
287
|
|
|
263
288
|
static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
|
|
@@ -271,6 +296,7 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
|
|
|
271
296
|
msgpack_buffer_chunk_t* nc = _msgpack_buffer_alloc_new_chunk(b);
|
|
272
297
|
|
|
273
298
|
*nc = b->tail;
|
|
299
|
+
_msgpack_buffer_transfer_rmem_owner(b, nc);
|
|
274
300
|
b->head = nc;
|
|
275
301
|
nc->next = &b->tail;
|
|
276
302
|
|
|
@@ -283,36 +309,61 @@ static inline void _msgpack_buffer_add_new_chunk(msgpack_buffer_t* b)
|
|
|
283
309
|
|
|
284
310
|
msgpack_buffer_chunk_t* nc = _msgpack_buffer_alloc_new_chunk(b);
|
|
285
311
|
|
|
286
|
-
#ifndef DISABLE_RMEM
|
|
287
|
-
#ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
|
|
288
312
|
if(b->rmem_last == b->tail_buffer_end) {
|
|
289
313
|
/* reuse unused rmem space */
|
|
290
314
|
size_t unused = b->tail_buffer_end - b->tail.last;
|
|
291
315
|
b->rmem_last -= unused;
|
|
292
316
|
}
|
|
293
|
-
#endif
|
|
294
|
-
#endif
|
|
295
317
|
|
|
296
318
|
/* rebuild tail */
|
|
297
319
|
*nc = b->tail;
|
|
320
|
+
_msgpack_buffer_transfer_rmem_owner(b, nc);
|
|
298
321
|
before_tail->next = nc;
|
|
299
322
|
nc->next = &b->tail;
|
|
300
323
|
}
|
|
301
324
|
}
|
|
302
325
|
|
|
303
|
-
void
|
|
326
|
+
static inline void _msgpack_buffer_append_reference(msgpack_buffer_t* b, VALUE string)
|
|
304
327
|
{
|
|
305
|
-
|
|
328
|
+
VALUE mapped_string;
|
|
329
|
+
if(ENCODING_GET_INLINED(string) == msgpack_rb_encindex_ascii8bit && RB_OBJ_FROZEN_RAW(string)) {
|
|
330
|
+
mapped_string = string;
|
|
331
|
+
} else {
|
|
332
|
+
mapped_string = rb_str_dup(string);
|
|
333
|
+
ENCODING_SET(mapped_string, msgpack_rb_encindex_ascii8bit);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
_msgpack_buffer_add_new_chunk(b);
|
|
337
|
+
|
|
338
|
+
char* data;
|
|
339
|
+
size_t length;
|
|
340
|
+
RSTRING_GETMEM(mapped_string, data, length);
|
|
341
|
+
|
|
342
|
+
b->tail.first = (char*) data;
|
|
343
|
+
b->tail.last = (char*) data + length;
|
|
344
|
+
b->tail.mapped_string = mapped_string;
|
|
345
|
+
b->tail.mem = NULL;
|
|
346
|
+
|
|
347
|
+
/* msgpack_buffer_writable_size should return 0 for mapped chunk */
|
|
348
|
+
b->tail_buffer_end = b->tail.last;
|
|
349
|
+
|
|
350
|
+
/* consider read_buffer */
|
|
351
|
+
if(b->head == &b->tail) {
|
|
352
|
+
b->read_buffer = b->tail.first;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
306
355
|
|
|
356
|
+
void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string)
|
|
357
|
+
{
|
|
307
358
|
if(b->io != Qnil) {
|
|
308
359
|
msgpack_buffer_flush(b);
|
|
309
|
-
if (
|
|
360
|
+
if (ENCODING_GET_INLINED(string) == msgpack_rb_encindex_ascii8bit) {
|
|
310
361
|
rb_funcall(b->io, b->io_write_all_method, 1, string);
|
|
311
362
|
} else {
|
|
312
|
-
msgpack_buffer_append(b, RSTRING_PTR(string),
|
|
363
|
+
msgpack_buffer_append(b, RSTRING_PTR(string), RSTRING_LEN(string));
|
|
313
364
|
}
|
|
314
365
|
} else {
|
|
315
|
-
|
|
366
|
+
_msgpack_buffer_append_reference(b, string);
|
|
316
367
|
}
|
|
317
368
|
}
|
|
318
369
|
|
|
@@ -320,11 +371,10 @@ static inline void* _msgpack_buffer_chunk_malloc(
|
|
|
320
371
|
msgpack_buffer_t* b, msgpack_buffer_chunk_t* c,
|
|
321
372
|
size_t required_size, size_t* allocated_size)
|
|
322
373
|
{
|
|
323
|
-
#ifndef DISABLE_RMEM
|
|
324
374
|
if(required_size <= MSGPACK_RMEM_PAGE_SIZE) {
|
|
325
|
-
|
|
375
|
+
c->rmem = true;
|
|
376
|
+
|
|
326
377
|
if((size_t)(b->rmem_end - b->rmem_last) < required_size) {
|
|
327
|
-
#endif
|
|
328
378
|
/* alloc new rmem page */
|
|
329
379
|
*allocated_size = MSGPACK_RMEM_PAGE_SIZE;
|
|
330
380
|
char* buffer = msgpack_rmem_alloc(&s_rmem);
|
|
@@ -335,8 +385,6 @@ static inline void* _msgpack_buffer_chunk_malloc(
|
|
|
335
385
|
b->rmem_last = b->rmem_end = buffer + MSGPACK_RMEM_PAGE_SIZE;
|
|
336
386
|
|
|
337
387
|
return buffer;
|
|
338
|
-
|
|
339
|
-
#ifndef DISABLE_RMEM_REUSE_INTERNAL_FRAGMENT
|
|
340
388
|
} else {
|
|
341
389
|
/* reuse unused rmem */
|
|
342
390
|
*allocated_size = (size_t)(b->rmem_end - b->rmem_last);
|
|
@@ -350,18 +398,13 @@ static inline void* _msgpack_buffer_chunk_malloc(
|
|
|
350
398
|
|
|
351
399
|
return buffer;
|
|
352
400
|
}
|
|
353
|
-
#endif
|
|
354
|
-
}
|
|
355
|
-
#else
|
|
356
|
-
if(required_size < 72) {
|
|
357
|
-
required_size = 72;
|
|
358
401
|
}
|
|
359
|
-
#endif
|
|
360
402
|
|
|
361
403
|
// TODO alignment?
|
|
362
404
|
*allocated_size = required_size;
|
|
363
405
|
void* mem = xmalloc(required_size);
|
|
364
406
|
c->mem = mem;
|
|
407
|
+
c->rmem = false;
|
|
365
408
|
return mem;
|
|
366
409
|
}
|
|
367
410
|
|
|
@@ -411,11 +454,7 @@ void _msgpack_buffer_expand(msgpack_buffer_t* b, const char* data, size_t length
|
|
|
411
454
|
size_t capacity = b->tail.last - b->tail.first;
|
|
412
455
|
|
|
413
456
|
/* can't realloc mapped chunk or rmem page */
|
|
414
|
-
if(b->tail.mapped_string != NO_MAPPED_STRING
|
|
415
|
-
#ifndef DISABLE_RMEM
|
|
416
|
-
|| capacity <= MSGPACK_RMEM_PAGE_SIZE
|
|
417
|
-
#endif
|
|
418
|
-
) {
|
|
457
|
+
if(b->tail.mapped_string != NO_MAPPED_STRING || capacity <= MSGPACK_RMEM_PAGE_SIZE) {
|
|
419
458
|
/* allocate new chunk */
|
|
420
459
|
_msgpack_buffer_add_new_chunk(b);
|
|
421
460
|
|
|
@@ -613,9 +652,11 @@ size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
|
|
|
613
652
|
|
|
614
653
|
size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string, size_t length)
|
|
615
654
|
{
|
|
655
|
+
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
|
656
|
+
|
|
616
657
|
if(RSTRING_LEN(string) == 0) {
|
|
617
658
|
/* direct read */
|
|
618
|
-
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(length), string);
|
|
659
|
+
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(MIN(b->io_buffer_size, length)), string);
|
|
619
660
|
if(ret == Qnil) {
|
|
620
661
|
return 0;
|
|
621
662
|
}
|
|
@@ -627,7 +668,7 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
|
|
|
627
668
|
b->io_buffer = rb_str_buf_new(0);
|
|
628
669
|
}
|
|
629
670
|
|
|
630
|
-
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(length), b->io_buffer);
|
|
671
|
+
VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(MIN(b->io_buffer_size, length)), b->io_buffer);
|
|
631
672
|
if(ret == Qnil) {
|
|
632
673
|
return 0;
|
|
633
674
|
}
|
|
@@ -635,6 +676,8 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
|
|
|
635
676
|
|
|
636
677
|
rb_str_buf_cat(string, (const void*)RSTRING_PTR(b->io_buffer), rl);
|
|
637
678
|
return rl;
|
|
679
|
+
|
|
680
|
+
#undef MIN
|
|
638
681
|
}
|
|
639
682
|
|
|
640
683
|
size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
|
data/ext/msgpack/buffer.h
CHANGED
|
@@ -78,20 +78,7 @@ struct msgpack_buffer_chunk_t {
|
|
|
78
78
|
void* mem;
|
|
79
79
|
msgpack_buffer_chunk_t* next;
|
|
80
80
|
VALUE mapped_string; /* RBString or NO_MAPPED_STRING */
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
union msgpack_buffer_cast_block_t {
|
|
84
|
-
char buffer[8];
|
|
85
|
-
uint8_t u8;
|
|
86
|
-
uint16_t u16;
|
|
87
|
-
uint32_t u32;
|
|
88
|
-
uint64_t u64;
|
|
89
|
-
int8_t i8;
|
|
90
|
-
int16_t i16;
|
|
91
|
-
int32_t i32;
|
|
92
|
-
int64_t i64;
|
|
93
|
-
float f;
|
|
94
|
-
double d;
|
|
81
|
+
bool rmem;
|
|
95
82
|
};
|
|
96
83
|
|
|
97
84
|
struct msgpack_buffer_t {
|
|
@@ -102,13 +89,9 @@ struct msgpack_buffer_t {
|
|
|
102
89
|
msgpack_buffer_chunk_t* head;
|
|
103
90
|
msgpack_buffer_chunk_t* free_list;
|
|
104
91
|
|
|
105
|
-
#ifndef DISABLE_RMEM
|
|
106
92
|
char* rmem_last;
|
|
107
93
|
char* rmem_end;
|
|
108
94
|
void** rmem_owner;
|
|
109
|
-
#endif
|
|
110
|
-
|
|
111
|
-
union msgpack_buffer_cast_block_t cast_block;
|
|
112
95
|
|
|
113
96
|
VALUE io;
|
|
114
97
|
VALUE io_buffer;
|
|
@@ -118,25 +101,25 @@ struct msgpack_buffer_t {
|
|
|
118
101
|
size_t write_reference_threshold;
|
|
119
102
|
size_t read_reference_threshold;
|
|
120
103
|
size_t io_buffer_size;
|
|
121
|
-
|
|
122
|
-
VALUE owner;
|
|
123
104
|
};
|
|
124
105
|
|
|
125
106
|
/*
|
|
126
107
|
* initialization functions
|
|
127
108
|
*/
|
|
128
|
-
void msgpack_buffer_static_init();
|
|
109
|
+
void msgpack_buffer_static_init(void);
|
|
129
110
|
|
|
130
|
-
void msgpack_buffer_static_destroy();
|
|
111
|
+
void msgpack_buffer_static_destroy(void);
|
|
131
112
|
|
|
132
113
|
void msgpack_buffer_init(msgpack_buffer_t* b);
|
|
133
114
|
|
|
134
115
|
void msgpack_buffer_destroy(msgpack_buffer_t* b);
|
|
135
116
|
|
|
136
|
-
void msgpack_buffer_mark(
|
|
117
|
+
void msgpack_buffer_mark(void* b);
|
|
137
118
|
|
|
138
119
|
void msgpack_buffer_clear(msgpack_buffer_t* b);
|
|
139
120
|
|
|
121
|
+
size_t msgpack_buffer_memsize(const msgpack_buffer_t* b);
|
|
122
|
+
|
|
140
123
|
static inline void msgpack_buffer_set_write_reference_threshold(msgpack_buffer_t* b, size_t length)
|
|
141
124
|
{
|
|
142
125
|
if(length < MSGPACK_BUFFER_STRING_WRITE_REFERENCE_MINIMUM) {
|
|
@@ -254,13 +237,14 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string);
|
|
|
254
237
|
|
|
255
238
|
static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE string)
|
|
256
239
|
{
|
|
257
|
-
size_t length
|
|
240
|
+
size_t length;
|
|
241
|
+
char *ptr;
|
|
242
|
+
RSTRING_GETMEM(string, ptr, length);
|
|
258
243
|
|
|
259
244
|
if(length > b->write_reference_threshold) {
|
|
260
245
|
_msgpack_buffer_append_long_string(b, string);
|
|
261
|
-
|
|
262
246
|
} else {
|
|
263
|
-
msgpack_buffer_append(b,
|
|
247
|
+
msgpack_buffer_append(b, ptr, length);
|
|
264
248
|
}
|
|
265
249
|
|
|
266
250
|
return length;
|
|
@@ -269,14 +253,9 @@ static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE str
|
|
|
269
253
|
static inline size_t msgpack_buffer_append_string_reference(msgpack_buffer_t* b, VALUE string)
|
|
270
254
|
{
|
|
271
255
|
size_t length = RSTRING_LEN(string);
|
|
272
|
-
|
|
273
|
-
if(length > MSGPACK_BUFFER_STRING_WRITE_REFERENCE_MINIMUM) {
|
|
256
|
+
if (length > 0) {
|
|
274
257
|
_msgpack_buffer_append_long_string(b, string);
|
|
275
|
-
|
|
276
|
-
} else {
|
|
277
|
-
msgpack_buffer_append(b, RSTRING_PTR(string), length);
|
|
278
258
|
}
|
|
279
|
-
|
|
280
259
|
return length;
|
|
281
260
|
}
|
|
282
261
|
|
|
@@ -389,14 +368,6 @@ static inline size_t msgpack_buffer_skip_nonblock(msgpack_buffer_t* b, size_t le
|
|
|
389
368
|
return length;
|
|
390
369
|
}
|
|
391
370
|
|
|
392
|
-
static inline union msgpack_buffer_cast_block_t* msgpack_buffer_read_cast_block(msgpack_buffer_t* b, size_t n)
|
|
393
|
-
{
|
|
394
|
-
if(!msgpack_buffer_read_all(b, b->cast_block.buffer, n)) {
|
|
395
|
-
return NULL;
|
|
396
|
-
}
|
|
397
|
-
return &b->cast_block;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
371
|
size_t msgpack_buffer_read_to_string_nonblock(msgpack_buffer_t* b, VALUE string, size_t length);
|
|
401
372
|
|
|
402
373
|
static inline size_t msgpack_buffer_read_to_string(msgpack_buffer_t* b, VALUE string, size_t length)
|
|
@@ -444,7 +415,6 @@ static inline VALUE _msgpack_buffer_refer_head_mapped_string(msgpack_buffer_t* b
|
|
|
444
415
|
|
|
445
416
|
static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen, bool utf8)
|
|
446
417
|
{
|
|
447
|
-
#ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE
|
|
448
418
|
/* optimize */
|
|
449
419
|
if(!will_be_frozen &&
|
|
450
420
|
b->head->mapped_string != NO_MAPPED_STRING &&
|
|
@@ -454,7 +424,6 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
|
|
|
454
424
|
_msgpack_buffer_consumed(b, length);
|
|
455
425
|
return result;
|
|
456
426
|
}
|
|
457
|
-
#endif
|
|
458
427
|
|
|
459
428
|
VALUE result;
|
|
460
429
|
|
|
@@ -483,7 +452,6 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
|
|
|
483
452
|
result = rb_str_new(b->read_buffer, length);
|
|
484
453
|
}
|
|
485
454
|
|
|
486
|
-
#if STR_UMINUS_DEDUPE
|
|
487
455
|
if (will_be_frozen) {
|
|
488
456
|
#if STR_UMINUS_DEDUPE_FROZEN
|
|
489
457
|
// Starting from MRI 2.8 it is preferable to freeze the string
|
|
@@ -495,7 +463,6 @@ static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_
|
|
|
495
463
|
// frozen.
|
|
496
464
|
result = rb_funcall(result, s_uminus, 0);
|
|
497
465
|
}
|
|
498
|
-
#endif // STR_UMINUS_DEDUPE
|
|
499
466
|
_msgpack_buffer_consumed(b, length);
|
|
500
467
|
return result;
|
|
501
468
|
|
|
@@ -507,4 +474,131 @@ static inline VALUE msgpack_buffer_read_top_as_symbol(msgpack_buffer_t* b, size_
|
|
|
507
474
|
return rb_str_intern(msgpack_buffer_read_top_as_string(b, length, true, utf8));
|
|
508
475
|
}
|
|
509
476
|
|
|
477
|
+
// Hash keys are likely to be repeated, and are frozen.
|
|
478
|
+
// As such we can re-use them if we keep a cache of the ones we've seen so far,
|
|
479
|
+
// and save much more expensive lookups into the global fstring table.
|
|
480
|
+
// This cache implementation is deliberately simple, as we're optimizing for compactness,
|
|
481
|
+
// to be able to fit easily embeded inside msgpack_unpacker_t.
|
|
482
|
+
// As such, binary search into a sorted array gives a good tradeoff between compactness and
|
|
483
|
+
// performance.
|
|
484
|
+
#define MSGPACK_KEY_CACHE_CAPACITY 63
|
|
485
|
+
|
|
486
|
+
typedef struct msgpack_key_cache_t msgpack_key_cache_t;
|
|
487
|
+
struct msgpack_key_cache_t {
|
|
488
|
+
int length;
|
|
489
|
+
VALUE entries[MSGPACK_KEY_CACHE_CAPACITY];
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
static inline VALUE build_interned_string(const char *str, const long length)
|
|
493
|
+
{
|
|
494
|
+
# ifdef HAVE_RB_ENC_INTERNED_STR
|
|
495
|
+
return rb_enc_interned_str(str, length, rb_utf8_encoding());
|
|
496
|
+
# else
|
|
497
|
+
VALUE rstring = rb_utf8_str_new(str, length);
|
|
498
|
+
return rb_funcall(rb_str_freeze(rstring), s_uminus, 0);
|
|
499
|
+
# endif
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
static inline VALUE build_symbol(const char *str, const long length)
|
|
503
|
+
{
|
|
504
|
+
return rb_str_intern(build_interned_string(str, length));
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
static void rvalue_cache_insert_at(msgpack_key_cache_t *cache, int index, VALUE rstring)
|
|
508
|
+
{
|
|
509
|
+
MEMMOVE(&cache->entries[index + 1], &cache->entries[index], VALUE, cache->length - index);
|
|
510
|
+
cache->length++;
|
|
511
|
+
cache->entries[index] = rstring;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
static inline int rstring_cache_cmp(const char *str, const long length, VALUE rstring)
|
|
515
|
+
{
|
|
516
|
+
long rstring_length = RSTRING_LEN(rstring);
|
|
517
|
+
if (length == rstring_length) {
|
|
518
|
+
return memcmp(str, RSTRING_PTR(rstring), length);
|
|
519
|
+
} else {
|
|
520
|
+
return (int)(length - rstring_length);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
static VALUE rstring_cache_fetch(msgpack_key_cache_t *cache, const char *str, const long length)
|
|
525
|
+
{
|
|
526
|
+
int low = 0;
|
|
527
|
+
int high = cache->length - 1;
|
|
528
|
+
int mid = 0;
|
|
529
|
+
int last_cmp = 0;
|
|
530
|
+
|
|
531
|
+
while (low <= high) {
|
|
532
|
+
mid = (high + low) >> 1;
|
|
533
|
+
VALUE entry = cache->entries[mid];
|
|
534
|
+
last_cmp = rstring_cache_cmp(str, length, entry);
|
|
535
|
+
|
|
536
|
+
if (last_cmp == 0) {
|
|
537
|
+
return entry;
|
|
538
|
+
} else if (last_cmp > 0) {
|
|
539
|
+
low = mid + 1;
|
|
540
|
+
} else {
|
|
541
|
+
high = mid - 1;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
VALUE rstring = build_interned_string(str, length);
|
|
546
|
+
|
|
547
|
+
if (cache->length < MSGPACK_KEY_CACHE_CAPACITY) {
|
|
548
|
+
if (last_cmp > 0) {
|
|
549
|
+
mid += 1;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
rvalue_cache_insert_at(cache, mid, rstring);
|
|
553
|
+
}
|
|
554
|
+
return rstring;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
static VALUE rsymbol_cache_fetch(msgpack_key_cache_t *cache, const char *str, const long length)
|
|
558
|
+
{
|
|
559
|
+
int low = 0;
|
|
560
|
+
int high = cache->length - 1;
|
|
561
|
+
int mid = 0;
|
|
562
|
+
int last_cmp = 0;
|
|
563
|
+
|
|
564
|
+
while (low <= high) {
|
|
565
|
+
mid = (high + low) >> 1;
|
|
566
|
+
VALUE entry = cache->entries[mid];
|
|
567
|
+
last_cmp = rstring_cache_cmp(str, length, rb_sym2str(entry));
|
|
568
|
+
|
|
569
|
+
if (last_cmp == 0) {
|
|
570
|
+
return entry;
|
|
571
|
+
} else if (last_cmp > 0) {
|
|
572
|
+
low = mid + 1;
|
|
573
|
+
} else {
|
|
574
|
+
high = mid - 1;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
VALUE rsymbol = build_symbol(str, length);
|
|
579
|
+
|
|
580
|
+
if (cache->length < MSGPACK_KEY_CACHE_CAPACITY) {
|
|
581
|
+
if (last_cmp > 0) {
|
|
582
|
+
mid += 1;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
rvalue_cache_insert_at(cache, mid, rsymbol);
|
|
586
|
+
}
|
|
587
|
+
return rsymbol;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
static inline VALUE msgpack_buffer_read_top_as_interned_symbol(msgpack_buffer_t* b, msgpack_key_cache_t *cache, size_t length)
|
|
591
|
+
{
|
|
592
|
+
VALUE result = rsymbol_cache_fetch(cache, b->read_buffer, length);
|
|
593
|
+
_msgpack_buffer_consumed(b, length);
|
|
594
|
+
return result;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
static inline VALUE msgpack_buffer_read_top_as_interned_string(msgpack_buffer_t* b, msgpack_key_cache_t *cache, size_t length)
|
|
598
|
+
{
|
|
599
|
+
VALUE result = rstring_cache_fetch(cache, b->read_buffer, length);
|
|
600
|
+
_msgpack_buffer_consumed(b, length);
|
|
601
|
+
return result;
|
|
602
|
+
}
|
|
603
|
+
|
|
510
604
|
#endif
|