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

Dependents:   msgpack_example

Revision:
0:1382f081365b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vrefbuffer.c	Sat Oct 25 16:32:57 2014 +0000
@@ -0,0 +1,220 @@
+/*
+ * MessagePack for C zero-copy buffer implementation
+ *
+ * Copyright (C) 2008-2009 FURUHASHI Sadayuki
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+#include "msgpack/vrefbuffer.h"
+#include <stdlib.h>
+#include <string.h>
+
+struct msgpack_vrefbuffer_chunk {
+	struct msgpack_vrefbuffer_chunk* next;
+	/* data ... */
+};
+
+bool msgpack_vrefbuffer_init(msgpack_vrefbuffer* vbuf,
+		size_t ref_size, size_t chunk_size)
+{
+	vbuf->chunk_size = chunk_size;
+	vbuf->ref_size = ref_size;
+
+	size_t nfirst = (sizeof(struct iovec) < 72/2) ?
+			72 / sizeof(struct iovec) : 8;
+
+	struct iovec* array = (struct iovec*)malloc(
+			sizeof(struct iovec) * nfirst);
+	if(array == NULL) {
+		return false;
+	}
+
+	vbuf->tail  = array;
+	vbuf->end   = array + nfirst;
+	vbuf->array = array;
+
+	msgpack_vrefbuffer_chunk* chunk = (msgpack_vrefbuffer_chunk*)malloc(
+			sizeof(msgpack_vrefbuffer_chunk) + chunk_size);
+	if(chunk == NULL) {
+		free(array);
+		return false;
+	}
+
+	msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
+
+	ib->free = chunk_size;
+	ib->ptr  = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
+	ib->head = chunk;
+	chunk->next = NULL;
+
+	return true;
+}
+
+void msgpack_vrefbuffer_destroy(msgpack_vrefbuffer* vbuf)
+{
+	msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head;
+	while(true) {
+		msgpack_vrefbuffer_chunk* n = c->next;
+		free(c);
+		if(n != NULL) {
+			c = n;
+		} else {
+			break;
+		}
+	}
+	free(vbuf->array);
+}
+
+void msgpack_vrefbuffer_clear(msgpack_vrefbuffer* vbuf)
+{
+	msgpack_vrefbuffer_chunk* c = vbuf->inner_buffer.head->next;
+	msgpack_vrefbuffer_chunk* n;
+	while(c != NULL) {
+		n = c->next;
+		free(c);
+		c = n;
+	}
+
+	msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
+	msgpack_vrefbuffer_chunk* chunk = ib->head;
+	chunk->next = NULL;
+	ib->free = vbuf->chunk_size;
+	ib->ptr  = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
+
+	vbuf->tail = vbuf->array;
+}
+
+int msgpack_vrefbuffer_append_ref(msgpack_vrefbuffer* vbuf,
+		const char* buf, size_t len)
+{
+	if(vbuf->tail == vbuf->end) {
+		const size_t nused = (size_t)(vbuf->tail - vbuf->array);
+		const size_t nnext = nused * 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;
+	}
+
+	vbuf->tail->iov_base = (char*)buf;
+	vbuf->tail->iov_len  = len;
+	++vbuf->tail;
+
+	return 0;
+}
+
+int msgpack_vrefbuffer_append_copy(msgpack_vrefbuffer* vbuf,
+		const char* buf, size_t len)
+{
+	msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
+
+	if(ib->free < len) {
+		size_t sz = vbuf->chunk_size;
+		if(sz < len) {
+			sz = len;
+		}
+
+		msgpack_vrefbuffer_chunk* chunk = (msgpack_vrefbuffer_chunk*)malloc(
+				sizeof(msgpack_vrefbuffer_chunk) + sz);
+		if(chunk == NULL) {
+			return -1;
+		}
+
+		chunk->next = ib->head;
+		ib->head = chunk;
+		ib->free = sz;
+		ib->ptr  = ((char*)chunk) + sizeof(msgpack_vrefbuffer_chunk);
+	}
+
+	char* m = ib->ptr;
+	memcpy(m, buf, len);
+	ib->free -= len;
+	ib->ptr  += len;
+
+	if(vbuf->tail != vbuf->array && m ==
+			(const char*)((vbuf->tail-1)->iov_base) + (vbuf->tail-1)->iov_len) {
+		(vbuf->tail-1)->iov_len += len;
+		return 0;
+	} else {
+		return msgpack_vrefbuffer_append_ref(vbuf, m, len);
+	}
+}
+
+int msgpack_vrefbuffer_migrate(msgpack_vrefbuffer* vbuf, msgpack_vrefbuffer* to)
+{
+	size_t sz = vbuf->chunk_size;
+
+	msgpack_vrefbuffer_chunk* empty = (msgpack_vrefbuffer_chunk*)malloc(
+			sizeof(msgpack_vrefbuffer_chunk) + sz);
+	if(empty == NULL) {
+		return -1;
+	}
+
+	empty->next = NULL;
+
+
+	const size_t nused = (size_t)(vbuf->tail - vbuf->array);
+	if(to->tail + nused < vbuf->end) {
+		const size_t tosize = (size_t)(to->tail - to->array);
+		const size_t reqsize = nused + tosize;
+		size_t nnext = (size_t)(to->end - to->array) * 2;
+		while(nnext < reqsize) {
+			nnext *= 2;
+		}
+
+		struct iovec* nvec = (struct iovec*)realloc(
+				to->array, sizeof(struct iovec)*nnext);
+		if(nvec == NULL) {
+			free(empty);
+			return -1;
+		}
+
+		to->array = nvec;
+		to->end   = nvec + nnext;
+		to->tail  = nvec + tosize;
+	}
+
+	memcpy(to->tail, vbuf->array, sizeof(struct iovec)*nused);
+
+	to->tail += nused;
+	vbuf->tail = vbuf->array;
+
+
+	msgpack_vrefbuffer_inner_buffer* const ib = &vbuf->inner_buffer;
+	msgpack_vrefbuffer_inner_buffer* const toib = &to->inner_buffer;
+
+	msgpack_vrefbuffer_chunk* last = ib->head;
+	while(last->next != NULL) {
+		last = last->next;
+	}
+	last->next = toib->head;
+	toib->head = ib->head;
+
+	if(toib->free < ib->free) {
+		toib->free = ib->free;
+		toib->ptr  = ib->ptr;
+	}
+
+	ib->head = empty;
+	ib->free = sz;
+	ib->ptr  = ((char*)empty) + sizeof(msgpack_vrefbuffer_chunk);
+
+	return 0;
+}
+