2 * MessagePack for C zero-copy buffer implementation
4 * Copyright (C) 2008-2009 FURUHASHI Sadayuki
6 * Distributed under the Boost Software License, Version 1.0.
7 * (See accompanying file LICENSE_1_0.txt or copy at
8 * http://www.boost.org/LICENSE_1_0.txt)
10 #include "vendor/msgpack/vrefbuffer.h"
14 #define MSGPACK_PACKER_MAX_BUFFER_SIZE 9
16 struct msgpack_vrefbuffer_chunk
{
17 struct msgpack_vrefbuffer_chunk
* next
;
21 bool msgpack_vrefbuffer_init(msgpack_vrefbuffer
* vbuf
,
22 size_t ref_size
, size_t chunk_size
)
26 msgpack_vrefbuffer_chunk
* chunk
;
29 ref_size
= MSGPACK_VREFBUFFER_REF_SIZE
;
32 chunk_size
= MSGPACK_VREFBUFFER_CHUNK_SIZE
;
34 vbuf
->chunk_size
= chunk_size
;
36 ref_size
> MSGPACK_PACKER_MAX_BUFFER_SIZE
+ 1 ?
37 ref_size
: MSGPACK_PACKER_MAX_BUFFER_SIZE
+ 1 ;
39 if((sizeof(msgpack_vrefbuffer_chunk
) + chunk_size
) < chunk_size
) {
43 nfirst
= (sizeof(msgpack_iovec
) < 72/2) ?
44 72 / sizeof(msgpack_iovec
) : 8;
46 array
= (msgpack_iovec
*)malloc(
47 sizeof(msgpack_iovec
) * nfirst
);
53 vbuf
->end
= array
+ nfirst
;
56 chunk
= (msgpack_vrefbuffer_chunk
*)malloc(
57 sizeof(msgpack_vrefbuffer_chunk
) + chunk_size
);
63 msgpack_vrefbuffer_inner_buffer
* const ib
= &vbuf
->inner_buffer
;
65 ib
->free
= chunk_size
;
66 ib
->ptr
= ((char*)chunk
) + sizeof(msgpack_vrefbuffer_chunk
);
74 void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer
* vbuf
)
76 msgpack_vrefbuffer_chunk
* c
= vbuf
->inner_buffer
.head
;
78 msgpack_vrefbuffer_chunk
* n
= c
->next
;
89 void msgpack_vrefbuffer_clear(msgpack_vrefbuffer
* vbuf
)
91 msgpack_vrefbuffer_chunk
* c
= vbuf
->inner_buffer
.head
->next
;
92 msgpack_vrefbuffer_chunk
* n
;
100 msgpack_vrefbuffer_inner_buffer
* const ib
= &vbuf
->inner_buffer
;
101 msgpack_vrefbuffer_chunk
* chunk
= ib
->head
;
103 ib
->free
= vbuf
->chunk_size
;
104 ib
->ptr
= ((char*)chunk
) + sizeof(msgpack_vrefbuffer_chunk
);
106 vbuf
->tail
= vbuf
->array
;
110 int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer
* vbuf
,
111 const char* buf
, size_t len
)
113 if(vbuf
->tail
== vbuf
->end
) {
114 const size_t nused
= (size_t)(vbuf
->tail
- vbuf
->array
);
115 const size_t nnext
= nused
* 2;
117 msgpack_iovec
* nvec
= (msgpack_iovec
*)realloc(
118 vbuf
->array
, sizeof(msgpack_iovec
)*nnext
);
124 vbuf
->end
= nvec
+ nnext
;
125 vbuf
->tail
= nvec
+ nused
;
128 vbuf
->tail
->iov_base
= (char*)buf
;
129 vbuf
->tail
->iov_len
= len
;
135 int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer
* vbuf
,
136 const char* buf
, size_t len
)
138 msgpack_vrefbuffer_inner_buffer
* const ib
= &vbuf
->inner_buffer
;
142 msgpack_vrefbuffer_chunk
* chunk
;
143 size_t sz
= vbuf
->chunk_size
;
148 if((sizeof(msgpack_vrefbuffer_chunk
) + sz
) < sz
){
151 chunk
= (msgpack_vrefbuffer_chunk
*)malloc(
152 sizeof(msgpack_vrefbuffer_chunk
) + sz
);
157 chunk
->next
= ib
->head
;
160 ib
->ptr
= ((char*)chunk
) + sizeof(msgpack_vrefbuffer_chunk
);
168 if(vbuf
->tail
!= vbuf
->array
&& m
==
169 (const char*)((vbuf
->tail
-1)->iov_base
) + (vbuf
->tail
-1)->iov_len
) {
170 (vbuf
->tail
-1)->iov_len
+= len
;
173 return msgpack_vrefbuffer_append_ref(vbuf
, m
, len
);
177 int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer
* vbuf
, msgpack_vrefbuffer
* to
)
179 size_t sz
= vbuf
->chunk_size
;
180 msgpack_vrefbuffer_chunk
* empty
;
182 if((sizeof(msgpack_vrefbuffer_chunk
) + sz
) < sz
){
186 empty
= (msgpack_vrefbuffer_chunk
*)malloc(
187 sizeof(msgpack_vrefbuffer_chunk
) + sz
);
195 const size_t nused
= (size_t)(vbuf
->tail
- vbuf
->array
);
196 if(to
->tail
+ nused
< vbuf
->end
) {
198 const size_t tosize
= (size_t)(to
->tail
- to
->array
);
199 const size_t reqsize
= nused
+ tosize
;
200 size_t nnext
= (size_t)(to
->end
- to
->array
) * 2;
201 while(nnext
< reqsize
) {
202 size_t tmp_nnext
= nnext
* 2;
203 if (tmp_nnext
<= nnext
) {
210 nvec
= (msgpack_iovec
*)realloc(
211 to
->array
, sizeof(msgpack_iovec
)*nnext
);
218 to
->end
= nvec
+ nnext
;
219 to
->tail
= nvec
+ tosize
;
222 memcpy(to
->tail
, vbuf
->array
, sizeof(msgpack_iovec
)*nused
);
225 vbuf
->tail
= vbuf
->array
;
228 msgpack_vrefbuffer_inner_buffer
* const ib
= &vbuf
->inner_buffer
;
229 msgpack_vrefbuffer_inner_buffer
* const toib
= &to
->inner_buffer
;
231 msgpack_vrefbuffer_chunk
* last
= ib
->head
;
232 while(last
->next
!= NULL
) {
235 last
->next
= toib
->head
;
236 toib
->head
= ib
->head
;
238 if(toib
->free
< ib
->free
) {
239 toib
->free
= ib
->free
;
245 ib
->ptr
= ((char*)empty
) + sizeof(msgpack_vrefbuffer_chunk
);