MessagePack C implementation for mbed, modified from https://github.com/msgpack/msgpack-c

Dependents:   msgpack_example

Committer:
yihui
Date:
Sat Oct 25 16:53:10 2014 +0000
Revision:
2:5237a514fdab
Parent:
0:1382f081365b
delete gcc_atomic.h

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 0:1382f081365b 1 /*
yihui 0:1382f081365b 2 * MessagePack for C zero-copy buffer implementation
yihui 0:1382f081365b 3 *
yihui 0:1382f081365b 4 * Copyright (C) 2008-2009 FURUHASHI Sadayuki
yihui 0:1382f081365b 5 *
yihui 0:1382f081365b 6 * Licensed under the Apache License, Version 2.0 (the "License");
yihui 0:1382f081365b 7 * you may not use this file except in compliance with the License.
yihui 0:1382f081365b 8 * You may obtain a copy of the License at
yihui 0:1382f081365b 9 *
yihui 0:1382f081365b 10 * http://www.apache.org/licenses/LICENSE-2.0
yihui 0:1382f081365b 11 *
yihui 0:1382f081365b 12 * Unless required by applicable law or agreed to in writing, software
yihui 0:1382f081365b 13 * distributed under the License is distributed on an "AS IS" BASIS,
yihui 0:1382f081365b 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
yihui 0:1382f081365b 15 * See the License for the specific language governing permissions and
yihui 0:1382f081365b 16 * limitations under the License.
yihui 0:1382f081365b 17 */
yihui 0:1382f081365b 18 #include "msgpack/vrefbuffer.h"
yihui 0:1382f081365b 19 #include <stdlib.h>
yihui 0:1382f081365b 20 #include <string.h>
yihui 0:1382f081365b 21
yihui 0:1382f081365b 22 struct msgpack_vrefbuffer_chunk {
yihui 0:1382f081365b 23 struct msgpack_vrefbuffer_chunk* next;
yihui 0:1382f081365b 24 /* data ... */
yihui 0:1382f081365b 25 };
yihui 0:1382f081365b 26
yihui 0:1382f081365b 27 bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
yihui 0:1382f081365b 28 size_t ref_size, size_t chunk_size)
yihui 0:1382f081365b 29 {
yihui 0:1382f081365b 30 vbuf->chunk_size = chunk_size;
yihui 0:1382f081365b 31 vbuf->ref_size = ref_size;
yihui 0:1382f081365b 32
yihui 0:1382f081365b 33 size_t nfirst = (sizeof(struct iovec) < 72/2) ?
yihui 0:1382f081365b 34 72 / sizeof(struct iovec) : 8;
yihui 0:1382f081365b 35
yihui 0:1382f081365b 36 struct iovec* array = (struct iovec*)malloc(
yihui 0:1382f081365b 37 sizeof(struct iovec) * nfirst);
yihui 0:1382f081365b 38 if(array == NULL) {
yihui 0:1382f081365b 39 return false;
yihui 0:1382f081365b 40 }
yihui 0:1382f081365b 41
yihui 0:1382f081365b 42 vbuf->tail = array;
yihui 0:1382f081365b 43 vbuf->end = array + nfirst;
yihui 0:1382f081365b 44 vbuf->array = array;
yihui 0:1382f081365b 45
yihui 0:1382f081365b 46 msgpack_vrefbuffer_chunk* chunk = (msgpack_vrefbuffer_chunk*)malloc(
yihui 0:1382f081365b 47 sizeof(msgpack_vrefbuffer_chunk) + chunk_size);
yihui 0:1382f081365b 48 if(chunk == NULL) {
yihui 0:1382f081365b 49 free(array);
yihui 0:1382f081365b 50 return false;
yihui 0:1382f081365b 51 }
yihui 0:1382f081365b 52
yihui 0:1382f081365b 53 msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
yihui 0:1382f081365b 54
yihui 0:1382f081365b 55 ib->free = chunk_size;
yihui 0:1382f081365b 56 ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
yihui 0:1382f081365b 57 ib->head = chunk;
yihui 0:1382f081365b 58 chunk->next = NULL;
yihui 0:1382f081365b 59
yihui 0:1382f081365b 60 return true;
yihui 0:1382f081365b 61 }
yihui 0:1382f081365b 62
yihui 0:1382f081365b 63 void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf)
yihui 0:1382f081365b 64 {
yihui 0:1382f081365b 65 msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head;
yihui 0:1382f081365b 66 while(true) {
yihui 0:1382f081365b 67 msgpack_vrefbuffer_chunk* n = c->next;
yihui 0:1382f081365b 68 free(c);
yihui 0:1382f081365b 69 if(n != NULL) {
yihui 0:1382f081365b 70 c = n;
yihui 0:1382f081365b 71 } else {
yihui 0:1382f081365b 72 break;
yihui 0:1382f081365b 73 }
yihui 0:1382f081365b 74 }
yihui 0:1382f081365b 75 free(vbuf->array);
yihui 0:1382f081365b 76 }
yihui 0:1382f081365b 77
yihui 0:1382f081365b 78 void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vbuf)
yihui 0:1382f081365b 79 {
yihui 0:1382f081365b 80 msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head->next;
yihui 0:1382f081365b 81 msgpack_vrefbuffer_chunk* n;
yihui 0:1382f081365b 82 while(c != NULL) {
yihui 0:1382f081365b 83 n = c->next;
yihui 0:1382f081365b 84 free(c);
yihui 0:1382f081365b 85 c = n;
yihui 0:1382f081365b 86 }
yihui 0:1382f081365b 87
yihui 0:1382f081365b 88 msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
yihui 0:1382f081365b 89 msgpack_vrefbuffer_chunk* chunk = ib->head;
yihui 0:1382f081365b 90 chunk->next = NULL;
yihui 0:1382f081365b 91 ib->free = vbuf->chunk_size;
yihui 0:1382f081365b 92 ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
yihui 0:1382f081365b 93
yihui 0:1382f081365b 94 vbuf->tail = vbuf->array;
yihui 0:1382f081365b 95 }
yihui 0:1382f081365b 96
yihui 0:1382f081365b 97 int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
yihui 0:1382f081365b 98 const char* buf, size_t len)
yihui 0:1382f081365b 99 {
yihui 0:1382f081365b 100 if(vbuf->tail == vbuf->end) {
yihui 0:1382f081365b 101 const size_t nused = (size_t)(vbuf->tail - vbuf->array);
yihui 0:1382f081365b 102 const size_t nnext = nused * 2;
yihui 0:1382f081365b 103
yihui 0:1382f081365b 104 struct iovec* nvec = (struct iovec*)realloc(
yihui 0:1382f081365b 105 vbuf->array, sizeof(struct iovec)*nnext);
yihui 0:1382f081365b 106 if(nvec == NULL) {
yihui 0:1382f081365b 107 return -1;
yihui 0:1382f081365b 108 }
yihui 0:1382f081365b 109
yihui 0:1382f081365b 110 vbuf->array = nvec;
yihui 0:1382f081365b 111 vbuf->end = nvec + nnext;
yihui 0:1382f081365b 112 vbuf->tail = nvec + nused;
yihui 0:1382f081365b 113 }
yihui 0:1382f081365b 114
yihui 0:1382f081365b 115 vbuf->tail->iov_base = (char*)buf;
yihui 0:1382f081365b 116 vbuf->tail->iov_len = len;
yihui 0:1382f081365b 117 ++vbuf->tail;
yihui 0:1382f081365b 118
yihui 0:1382f081365b 119 return 0;
yihui 0:1382f081365b 120 }
yihui 0:1382f081365b 121
yihui 0:1382f081365b 122 int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
yihui 0:1382f081365b 123 const char* buf, size_t len)
yihui 0:1382f081365b 124 {
yihui 0:1382f081365b 125 msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
yihui 0:1382f081365b 126
yihui 0:1382f081365b 127 if(ib->free < len) {
yihui 0:1382f081365b 128 size_t sz = vbuf->chunk_size;
yihui 0:1382f081365b 129 if(sz < len) {
yihui 0:1382f081365b 130 sz = len;
yihui 0:1382f081365b 131 }
yihui 0:1382f081365b 132
yihui 0:1382f081365b 133 msgpack_vrefbuffer_chunk* chunk = (msgpack_vrefbuffer_chunk*)malloc(
yihui 0:1382f081365b 134 sizeof(msgpack_vrefbuffer_chunk) + sz);
yihui 0:1382f081365b 135 if(chunk == NULL) {
yihui 0:1382f081365b 136 return -1;
yihui 0:1382f081365b 137 }
yihui 0:1382f081365b 138
yihui 0:1382f081365b 139 chunk->next = ib->head;
yihui 0:1382f081365b 140 ib->head = chunk;
yihui 0:1382f081365b 141 ib->free = sz;
yihui 0:1382f081365b 142 ib->ptr = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
yihui 0:1382f081365b 143 }
yihui 0:1382f081365b 144
yihui 0:1382f081365b 145 char* m = ib->ptr;
yihui 0:1382f081365b 146 memcpy(m, buf, len);
yihui 0:1382f081365b 147 ib->free -= len;
yihui 0:1382f081365b 148 ib->ptr += len;
yihui 0:1382f081365b 149
yihui 0:1382f081365b 150 if(vbuf->tail != vbuf->array && m ==
yihui 0:1382f081365b 151 (const char*)((vbuf->tail-1)->iov_base) + (vbuf->tail-1)->iov_len) {
yihui 0:1382f081365b 152 (vbuf->tail-1)->iov_len += len;
yihui 0:1382f081365b 153 return 0;
yihui 0:1382f081365b 154 } else {
yihui 0:1382f081365b 155 return msgpack_vrefbuffer_append_ref(vbuf, m, len);
yihui 0:1382f081365b 156 }
yihui 0:1382f081365b 157 }
yihui 0:1382f081365b 158
yihui 0:1382f081365b 159 int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to)
yihui 0:1382f081365b 160 {
yihui 0:1382f081365b 161 size_t sz = vbuf->chunk_size;
yihui 0:1382f081365b 162
yihui 0:1382f081365b 163 msgpack_vrefbuffer_chunk* empty = (msgpack_vrefbuffer_chunk*)malloc(
yihui 0:1382f081365b 164 sizeof(msgpack_vrefbuffer_chunk) + sz);
yihui 0:1382f081365b 165 if(empty == NULL) {
yihui 0:1382f081365b 166 return -1;
yihui 0:1382f081365b 167 }
yihui 0:1382f081365b 168
yihui 0:1382f081365b 169 empty->next = NULL;
yihui 0:1382f081365b 170
yihui 0:1382f081365b 171
yihui 0:1382f081365b 172 const size_t nused = (size_t)(vbuf->tail - vbuf->array);
yihui 0:1382f081365b 173 if(to->tail + nused < vbuf->end) {
yihui 0:1382f081365b 174 const size_t tosize = (size_t)(to->tail - to->array);
yihui 0:1382f081365b 175 const size_t reqsize = nused + tosize;
yihui 0:1382f081365b 176 size_t nnext = (size_t)(to->end - to->array) * 2;
yihui 0:1382f081365b 177 while(nnext < reqsize) {
yihui 0:1382f081365b 178 nnext *= 2;
yihui 0:1382f081365b 179 }
yihui 0:1382f081365b 180
yihui 0:1382f081365b 181 struct iovec* nvec = (struct iovec*)realloc(
yihui 0:1382f081365b 182 to->array, sizeof(struct iovec)*nnext);
yihui 0:1382f081365b 183 if(nvec == NULL) {
yihui 0:1382f081365b 184 free(empty);
yihui 0:1382f081365b 185 return -1;
yihui 0:1382f081365b 186 }
yihui 0:1382f081365b 187
yihui 0:1382f081365b 188 to->array = nvec;
yihui 0:1382f081365b 189 to->end = nvec + nnext;
yihui 0:1382f081365b 190 to->tail = nvec + tosize;
yihui 0:1382f081365b 191 }
yihui 0:1382f081365b 192
yihui 0:1382f081365b 193 memcpy(to->tail, vbuf->array, sizeof(struct iovec)*nused);
yihui 0:1382f081365b 194
yihui 0:1382f081365b 195 to->tail += nused;
yihui 0:1382f081365b 196 vbuf->tail = vbuf->array;
yihui 0:1382f081365b 197
yihui 0:1382f081365b 198
yihui 0:1382f081365b 199 msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
yihui 0:1382f081365b 200 msgpack_vrefbuffer_inner_buffer* const toib = &to->inner_buffer;
yihui 0:1382f081365b 201
yihui 0:1382f081365b 202 msgpack_vrefbuffer_chunk* last = ib->head;
yihui 0:1382f081365b 203 while(last->next != NULL) {
yihui 0:1382f081365b 204 last = last->next;
yihui 0:1382f081365b 205 }
yihui 0:1382f081365b 206 last->next = toib->head;
yihui 0:1382f081365b 207 toib->head = ib->head;
yihui 0:1382f081365b 208
yihui 0:1382f081365b 209 if(toib->free < ib->free) {
yihui 0:1382f081365b 210 toib->free = ib->free;
yihui 0:1382f081365b 211 toib->ptr = ib->ptr;
yihui 0:1382f081365b 212 }
yihui 0:1382f081365b 213
yihui 0:1382f081365b 214 ib->head = empty;
yihui 0:1382f081365b 215 ib->free = sz;
yihui 0:1382f081365b 216 ib->ptr = ((char*)empty) + sizeof(msgpack_vrefbuffer_chunk);
yihui 0:1382f081365b 217
yihui 0:1382f081365b 218 return 0;
yihui 0:1382f081365b 219 }
yihui 0:1382f081365b 220