messagepack implementation for embedded systems (mbed / arduino)
Dependents: hello_message_pack
msgpack-c & msgpack-c++ https://github.com/msgpack/msgpack-c implementation for embedded systems (mbed / Arduino)
Diff: include/zbuffer.h
- Revision:
- 0:3f9dbf1e2cb0
- Child:
- 3:a56553e46a9a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/zbuffer.h Sat Feb 13 01:53:11 2016 +0000 @@ -0,0 +1,200 @@ +/* + * MessagePack for C deflate buffer implementation + * + * Copyright (C) 2010 FURUHASHI Sadayuki + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef MSGPACK_ZBUFFER_H +#define MSGPACK_ZBUFFER_H + +#include "sysdep.h" +#include <stdlib.h> +#include <string.h> +#include <zlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @defgroup msgpack_zbuffer Compressed buffer + * @ingroup msgpack_buffer + * @{ + */ + +typedef struct msgpack_zbuffer { + z_stream stream; + char* data; + size_t init_size; +} msgpack_zbuffer; + +#ifndef MSGPACK_ZBUFFER_INIT_SIZE +#define MSGPACK_ZBUFFER_INIT_SIZE 8192 +#endif + +static inline bool msgpack_zbuffer_init( + msgpack_zbuffer* zbuf, int level, size_t init_size); +static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf); + +static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size); +static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf); + +static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf); + +static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf); +static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf); + +static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf); +static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf); +static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf); + + +#ifndef MSGPACK_ZBUFFER_RESERVE_SIZE +#define MSGPACK_ZBUFFER_RESERVE_SIZE 512 +#endif + +static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len); + +static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf); + + +static inline bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf, + int level, size_t init_size) +{ + memset(zbuf, 0, sizeof(msgpack_zbuffer)); + zbuf->init_size = init_size; + if(deflateInit(&zbuf->stream, level) != Z_OK) { + free(zbuf->data); + return false; + } + return true; +} + +static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf) +{ + deflateEnd(&zbuf->stream); + free(zbuf->data); +} + +static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size) +{ + msgpack_zbuffer* zbuf = (msgpack_zbuffer*)malloc(sizeof(msgpack_zbuffer)); + if (zbuf == NULL) return NULL; + if(!msgpack_zbuffer_init(zbuf, level, init_size)) { + free(zbuf); + return NULL; + } + return zbuf; +} + +static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf) +{ + if(zbuf == NULL) { return; } + msgpack_zbuffer_destroy(zbuf); + free(zbuf); +} + +static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf) +{ + size_t used = (char*)zbuf->stream.next_out - zbuf->data; + size_t csize = used + zbuf->stream.avail_out; + size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2; + + char* tmp = (char*)realloc(zbuf->data, nsize); + if(tmp == NULL) { + return false; + } + + zbuf->data = tmp; + zbuf->stream.next_out = (Bytef*)(tmp + used); + zbuf->stream.avail_out = nsize - used; + + return true; +} + +static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len) +{ + msgpack_zbuffer* zbuf = (msgpack_zbuffer*)data; + + zbuf->stream.next_in = (Bytef*)buf; + zbuf->stream.avail_in = len; + + while(zbuf->stream.avail_in > 0) { + if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) { + if(!msgpack_zbuffer_expand(zbuf)) { + return -1; + } + } + + if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) { + return -1; + } + } + + return 0; +} + +static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf) +{ + while(true) { + switch(deflate(&zbuf->stream, Z_FINISH)) { + case Z_STREAM_END: + return zbuf->data; + case Z_OK: + if(!msgpack_zbuffer_expand(zbuf)) { + return NULL; + } + break; + default: + return NULL; + } + } +} + +static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf) +{ + return zbuf->data; +} + +static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf) +{ + return (char*)zbuf->stream.next_out - zbuf->data; +} + +static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf) +{ + zbuf->stream.avail_out += (char*)zbuf->stream.next_out - zbuf->data; + zbuf->stream.next_out = (Bytef*)zbuf->data; +} + +static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf) +{ + if(deflateReset(&zbuf->stream) != Z_OK) { + return false; + } + msgpack_zbuffer_reset_buffer(zbuf); + return true; +} + +static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf) +{ + char* tmp = zbuf->data; + zbuf->data = NULL; + zbuf->stream.next_out = NULL; + zbuf->stream.avail_out = 0; + return tmp; +} + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif /* msgpack/zbuffer.h */ +