diff --git a/c/vrefbuffer.c b/c/vrefbuffer.c index bbaf61d7..2bf97afe 100644 --- a/c/vrefbuffer.c +++ b/c/vrefbuffer.c @@ -77,7 +77,7 @@ int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf, const char* buf, unsigned int len) { if(vbuf->tail == vbuf->end) { - const size_t nused = vbuf->end - vbuf->array; + const size_t nused = vbuf->tail - vbuf->array; const size_t nnext = nused * 2; struct iovec* nvec = (struct iovec*)realloc( @@ -133,3 +133,30 @@ int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf, } } +int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to) +{ + const size_t tosize = to->tail - to->array; + if(vbuf->tail + tosize < vbuf->end) { + const size_t nused = vbuf->tail - vbuf->array; + const size_t nsize = vbuf->end - vbuf->array; + const size_t reqsize = nused + tosize; + size_t nnext = nsize * 2; + while(nnext < reqsize) { + nnext *= 2; + } + + struct iovec* nvec = (struct iovec*)realloc( + vbuf->array, sizeof(struct iovec)*nnext); + if(nvec == NULL) { + return -1; + } + + vbuf->array = nvec; + vbuf->end = nvec + nnext; + vbuf->tail = nvec + nused; + } + + memcpy(vbuf->tail, vbuf->array, sizeof(struct iovec)*tosize); + return 0; +} + diff --git a/c/vrefbuffer.h b/c/vrefbuffer.h index 063075f8..9f24f14f 100644 --- a/c/vrefbuffer.h +++ b/c/vrefbuffer.h @@ -76,6 +76,7 @@ int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf, int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf, const char* buf, unsigned int len); +int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to); int msgpack_vrefbuffer_write(void* data, const char* buf, unsigned int len) { diff --git a/cpp/vrefbuffer.hpp b/cpp/vrefbuffer.hpp index 549d77fc..c8eca7b6 100644 --- a/cpp/vrefbuffer.hpp +++ b/cpp/vrefbuffer.hpp @@ -71,6 +71,13 @@ public: return msgpack_vrefbuffer_veclen(this); } + void migrate(vrefbuffer* to) + { + if(msgpack_vrefbuffer_migrate(this, to) < 0) { + throw std::bad_alloc(); + } + } + private: typedef msgpack_vrefbuffer base;