mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-20 14:02:40 +02:00
ruby: fixes buffering routine
This commit is contained in:
@@ -386,90 +386,70 @@ static VALUE MessagePack_Unpacker_stream_set(VALUE self, VALUE val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef RUBY_VM
|
static void reserve_buffer(msgpack_unpack_t* mp, size_t require)
|
||||||
# ifndef STR_SHARED
|
|
||||||
# define STR_SHARED FL_USER2
|
|
||||||
# endif
|
|
||||||
# ifndef STR_NOEMBED
|
|
||||||
# define STR_NOEMBED FL_USER1
|
|
||||||
# endif
|
|
||||||
# ifndef STR_ASSOC
|
|
||||||
# define STR_ASSOC FL_USER3
|
|
||||||
# endif
|
|
||||||
# ifndef STR_NOCAPA_P
|
|
||||||
# define STR_NOCAPA_P(s) (FL_TEST(s,STR_NOEMBED) && FL_ANY(s,STR_SHARED|STR_ASSOC))
|
|
||||||
# endif
|
|
||||||
# define NEED_MORE_CAPA(s,size) (!STR_NOCAPA_P(s) && RSTRING(s)->as.heap.aux.capa < size)
|
|
||||||
#else
|
|
||||||
# ifndef STR_NOCAPA
|
|
||||||
# ifndef STR_ASSOC
|
|
||||||
# define STR_ASSOC FL_USER3
|
|
||||||
# endif
|
|
||||||
# ifndef ELTS_SHARED
|
|
||||||
# define ELTS_SHARED FL_USER2
|
|
||||||
# endif
|
|
||||||
# define STR_NOCAPA (ELTS_SHARED|STR_ASSOC)
|
|
||||||
# endif
|
|
||||||
# define NEED_MORE_CAPA(s,size) (!FL_TEST(s,STR_NOCAPA) && RSTRING(s)->aux.capa < size)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void feed_buffer(msgpack_unpack_t* mp, const char* ptr, size_t len)
|
|
||||||
{
|
{
|
||||||
struct unpack_buffer* buffer = &mp->user.buffer;
|
struct unpack_buffer* buffer = &mp->user.buffer;
|
||||||
|
|
||||||
if(buffer->size == 0) {
|
if(buffer->size == 0) {
|
||||||
char* tmp = ALLOC_N(char, MSGPACK_UNPACKER_BUFFER_INIT_SIZE);
|
size_t nsize = MSGPACK_UNPACKER_BUFFER_INIT_SIZE;
|
||||||
|
while(nsize < require) {
|
||||||
|
nsize *= 2;
|
||||||
|
}
|
||||||
|
char* tmp = ALLOC_N(char, nsize);
|
||||||
buffer->ptr = tmp;
|
buffer->ptr = tmp;
|
||||||
buffer->free = MSGPACK_UNPACKER_BUFFER_INIT_SIZE;
|
buffer->free = nsize;
|
||||||
buffer->size = 0;
|
buffer->size = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} else if(buffer->size <= mp->user.offset) {
|
if(buffer->size <= mp->user.offset) {
|
||||||
/* clear buffer and rewind offset */
|
/* clear buffer and rewind offset */
|
||||||
buffer->free += buffer->size;
|
buffer->free += buffer->size;
|
||||||
buffer->size = 0;
|
buffer->size = 0;
|
||||||
mp->user.offset = 0;
|
mp->user.offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(len <= buffer->free) {
|
if(require <= buffer->free) {
|
||||||
/* enough free space: just copy */
|
/* enough free space */
|
||||||
memcpy(buffer->ptr+buffer->size, ptr, len);
|
|
||||||
buffer->size += len;
|
|
||||||
buffer->free -= len;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t csize = buffer->size + buffer->free;
|
size_t nsize = (buffer->size + buffer->free) * 2;
|
||||||
|
|
||||||
if(mp->user.offset <= buffer->size / 2) {
|
if(mp->user.offset <= buffer->size / 2) {
|
||||||
/* parsed less than half: realloc and copy */
|
/* parsed less than half: realloc only */
|
||||||
csize *= 2;
|
while(nsize < buffer->size + require) {
|
||||||
while(csize < buffer->size + len) {
|
nsize *= 2;
|
||||||
csize *= 2;
|
|
||||||
}
|
}
|
||||||
char* tmp = REALLOC_N(buffer->ptr, char, csize);
|
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
||||||
memcpy(tmp + buffer->size, ptr, len);
|
buffer->free = nsize - buffer->size;
|
||||||
buffer->ptr = tmp;
|
buffer->ptr = tmp;
|
||||||
buffer->free = csize - buffer->size;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t not_parsed = buffer->size - mp->user.offset;
|
} else {
|
||||||
|
/* parsed more than half: realloc and move */
|
||||||
if(csize < not_parsed + len) {
|
size_t not_parsed = buffer->size - mp->user.offset;
|
||||||
/* more buffer size */
|
while(nsize < not_parsed + require) {
|
||||||
csize *= 2;
|
nsize *= 2;
|
||||||
while(csize < not_parsed + len) {
|
|
||||||
csize *= 2;
|
|
||||||
}
|
}
|
||||||
char* tmp = REALLOC_N(buffer->ptr, char, csize);
|
char* tmp = REALLOC_N(buffer->ptr, char, nsize);
|
||||||
|
memcpy(tmp, tmp + mp->user.offset, not_parsed);
|
||||||
|
buffer->free = nsize - buffer->size;
|
||||||
|
buffer->size = not_parsed;
|
||||||
buffer->ptr = tmp;
|
buffer->ptr = tmp;
|
||||||
|
mp->user.offset = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(buffer->ptr+not_parsed, ptr, not_parsed);
|
static inline void feed_buffer(msgpack_unpack_t* mp, const char* ptr, size_t len)
|
||||||
buffer->size = not_parsed;
|
{
|
||||||
buffer->free = csize - buffer->size;
|
struct unpack_buffer* buffer = &mp->user.buffer;
|
||||||
buffer->ptr = buffer->ptr;
|
|
||||||
mp->user.offset = 0;
|
if(buffer->free < len) {
|
||||||
|
reserve_buffer(mp, len);
|
||||||
|
}
|
||||||
|
memcpy(buffer->ptr + buffer->size, ptr, len);
|
||||||
|
buffer->size += len;
|
||||||
|
buffer->free -= len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user