messagepack implementation for embedded systems (mbed / arduino)
Dependents: hello_message_pack
vrefbuffer.c
00001 /* 00002 * MessagePack for C zero-copy buffer implementation 00003 * 00004 * Copyright (C) 2008-2009 FURUHASHI Sadayuki 00005 * 00006 * Distributed under the Boost Software License, Version 1.0. 00007 * (See accompanying file LICENSE_1_0.txt or copy at 00008 * http://www.boost.org/LICENSE_1_0.txt) 00009 */ 00010 #include "include/vrefbuffer.h" 00011 #include <stdlib.h> 00012 #include <string.h> 00013 00014 #define MSGPACK_PACKER_MAX_BUFFER_SIZE 9 00015 00016 struct msgpack_vrefbuffer_chunk { 00017 struct msgpack_vrefbuffer_chunk* next; 00018 /* data ... */ 00019 }; 00020 00021 bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf, 00022 size_t ref_size, size_t chunk_size) 00023 { 00024 size_t nfirst; 00025 struct iovec* array; 00026 msgpack_vrefbuffer_chunk* chunk; 00027 00028 vbuf->chunk_size = chunk_size; 00029 vbuf->ref_size = 00030 ref_size > MSGPACK_PACKER_MAX_BUFFER_SIZE + 1 ? 00031 ref_size : MSGPACK_PACKER_MAX_BUFFER_SIZE + 1 ; 00032 00033 nfirst = (sizeof(struct iovec) < 72/2) ? 00034 72 / sizeof(struct iovec) : 8; 00035 00036 array = (struct iovec*)malloc( 00037 sizeof(struct iovec) * nfirst); 00038 if(array == NULL) { 00039 return false; 00040 } 00041 00042 vbuf->tail = array; 00043 vbuf->end = array + nfirst; 00044 vbuf->array = array; 00045 00046 chunk = (msgpack_vrefbuffer_chunk*)malloc( 00047 sizeof(msgpack_vrefbuffer_chunk) + chunk_size); 00048 if(chunk == NULL) { 00049 free(array); 00050 return false; 00051 } 00052 else { 00053 msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer; 00054 00055 ib->free = chunk_size; 00056 ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk); 00057 ib->head = chunk; 00058 chunk->next = NULL; 00059 00060 return true; 00061 } 00062 } 00063 00064 void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf) 00065 { 00066 msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head; 00067 while(true) { 00068 msgpack_vrefbuffer_chunk* n = c->next; 00069 free(c); 00070 if(n != NULL) { 00071 c = n; 00072 } else { 00073 break; 00074 } 00075 } 00076 free(vbuf->array); 00077 } 00078 00079 void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vbuf) 00080 { 00081 msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head->next; 00082 msgpack_vrefbuffer_chunk* n; 00083 while(c != NULL) { 00084 n = c->next; 00085 free(c); 00086 c = n; 00087 } 00088 00089 { 00090 msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer; 00091 msgpack_vrefbuffer_chunk* chunk = ib->head; 00092 chunk->next = NULL; 00093 ib->free = vbuf->chunk_size; 00094 ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk); 00095 00096 vbuf->tail = vbuf->array; 00097 } 00098 } 00099 00100 int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf, 00101 const char* buf, size_t len) 00102 { 00103 if(vbuf->tail == vbuf->end) { 00104 const size_t nused = (size_t)(vbuf->tail - vbuf->array); 00105 const size_t nnext = nused * 2; 00106 00107 struct iovec* nvec = (struct iovec*)realloc( 00108 vbuf->array, sizeof(struct iovec)*nnext); 00109 if(nvec == NULL) { 00110 return -1; 00111 } 00112 00113 vbuf->array = nvec; 00114 vbuf->end = nvec + nnext; 00115 vbuf->tail = nvec + nused; 00116 } 00117 00118 vbuf->tail->iov_base = (char*)buf; 00119 vbuf->tail->iov_len = len; 00120 ++vbuf->tail; 00121 00122 return 0; 00123 } 00124 00125 int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf, 00126 const char* buf, size_t len) 00127 { 00128 msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer; 00129 char* m; 00130 00131 if(ib->free < len) { 00132 msgpack_vrefbuffer_chunk* chunk; 00133 size_t sz = vbuf->chunk_size; 00134 if(sz < len) { 00135 sz = len; 00136 } 00137 00138 chunk = (msgpack_vrefbuffer_chunk*)malloc( 00139 sizeof(msgpack_vrefbuffer_chunk) + sz); 00140 if(chunk == NULL) { 00141 return -1; 00142 } 00143 00144 chunk->next = ib->head; 00145 ib->head = chunk; 00146 ib->free = sz; 00147 ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk); 00148 } 00149 00150 m = ib->ptr; 00151 memcpy(m, buf, len); 00152 ib->free -= len; 00153 ib->ptr += len; 00154 00155 if(vbuf->tail != vbuf->array && m == 00156 (const char*)((vbuf->tail-1)->iov_base) + (vbuf->tail-1)->iov_len) { 00157 (vbuf->tail-1)->iov_len += len; 00158 return 0; 00159 } else { 00160 return msgpack_vrefbuffer_append_ref(vbuf, m, len); 00161 } 00162 } 00163 00164 int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to) 00165 { 00166 size_t sz = vbuf->chunk_size; 00167 00168 msgpack_vrefbuffer_chunk* empty = (msgpack_vrefbuffer_chunk*)malloc( 00169 sizeof(msgpack_vrefbuffer_chunk) + sz); 00170 if(empty == NULL) { 00171 return -1; 00172 } 00173 00174 empty->next = NULL; 00175 00176 { 00177 const size_t nused = (size_t)(vbuf->tail - vbuf->array); 00178 if(to->tail + nused < vbuf->end) { 00179 struct iovec* nvec; 00180 const size_t tosize = (size_t)(to->tail - to->array); 00181 const size_t reqsize = nused + tosize; 00182 size_t nnext = (size_t)(to->end - to->array) * 2; 00183 while(nnext < reqsize) { 00184 size_t tmp_nnext = nnext * 2; 00185 if (tmp_nnext <= nnext) { 00186 nnext = reqsize; 00187 break; 00188 } 00189 nnext = tmp_nnext; 00190 } 00191 00192 nvec = (struct iovec*)realloc( 00193 to->array, sizeof(struct iovec)*nnext); 00194 if(nvec == NULL) { 00195 free(empty); 00196 return -1; 00197 } 00198 00199 to->array = nvec; 00200 to->end = nvec + nnext; 00201 to->tail = nvec + tosize; 00202 } 00203 00204 memcpy(to->tail, vbuf->array, sizeof(struct iovec)*nused); 00205 00206 to->tail += nused; 00207 vbuf->tail = vbuf->array; 00208 00209 { 00210 msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer; 00211 msgpack_vrefbuffer_inner_buffer* const toib = &to->inner_buffer; 00212 00213 msgpack_vrefbuffer_chunk* last = ib->head; 00214 while(last->next != NULL) { 00215 last = last->next; 00216 } 00217 last->next = toib->head; 00218 toib->head = ib->head; 00219 00220 if(toib->free < ib->free) { 00221 toib->free = ib->free; 00222 toib->ptr = ib->ptr; 00223 } 00224 00225 ib->head = empty; 00226 ib->free = sz; 00227 ib->ptr = ((char*)empty) + sizeof(msgpack_vrefbuffer_chunk); 00228 } 00229 } 00230 00231 return 0; 00232 }
Generated on Tue Jul 12 2022 22:51:46 by 1.7.2