Hideaki Tai / msgpack-embedded

Dependents:   hello_message_pack

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers zbuffer.h Source File

zbuffer.h

00001 /*
00002  * MessagePack for C deflate buffer implementation
00003  *
00004  * Copyright (C) 2010 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 #ifndef MSGPACK_ZBUFFER_H
00011 #define MSGPACK_ZBUFFER_H
00012 
00013 #include "sysdep.h"
00014 #include <stdlib.h>
00015 #include <string.h>
00016 #include <zlib.h>
00017 
00018 #ifdef __cplusplus
00019 extern "C" {
00020 #endif
00021 
00022 
00023 /**
00024  * @defgroup msgpack_zbuffer Compressed buffer
00025  * @ingroup msgpack_buffer
00026  * @{
00027  */
00028 
00029 typedef struct msgpack_zbuffer {
00030     z_stream stream;
00031     char* data;
00032     size_t init_size;
00033 } msgpack_zbuffer;
00034 
00035 #ifndef MSGPACK_ZBUFFER_INIT_SIZE
00036     #if defined(__MBED__)
00037         #define MSGPACK_ZBUFFER_INIT_SIZE 512
00038     #elif defined(__AVR__)
00039         #define MSGPACK_ZBUFFER_INIT_SIZE 128
00040     #else
00041         #define MSGPACK_ZBUFFER_INIT_SIZE 8192
00042     #endif
00043 #endif
00044 
00045 static inline bool msgpack_zbuffer_init(
00046     msgpack_zbuffer* zbuf, int level, size_t init_size);
00047 static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf);
00048 
00049 static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size);
00050 static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf);
00051 
00052 static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf);
00053 
00054 static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf);
00055 static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf);
00056 
00057 static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf);
00058 static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf);
00059 static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf);
00060 
00061 
00062 #ifndef MSGPACK_ZBUFFER_RESERVE_SIZE
00063 #define MSGPACK_ZBUFFER_RESERVE_SIZE 512
00064 #endif
00065 
00066 static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len);
00067 
00068 static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf);
00069 
00070 
00071 static inline bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf,
00072         int level, size_t init_size)
00073 {
00074     memset(zbuf, 0, sizeof(msgpack_zbuffer));
00075     zbuf->init_size = init_size;
00076     if(deflateInit(&zbuf->stream, level) != Z_OK) {
00077         free(zbuf->data);
00078         return false;
00079     }
00080     return true;
00081 }
00082 
00083 static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf)
00084 {
00085     deflateEnd(&zbuf->stream);
00086     free(zbuf->data);
00087 }
00088 
00089 static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size)
00090 {
00091     msgpack_zbuffer* zbuf = (msgpack_zbuffer*)malloc(sizeof(msgpack_zbuffer));
00092     if (zbuf == NULL) return NULL;
00093     if(!msgpack_zbuffer_init(zbuf, level, init_size)) {
00094         free(zbuf);
00095         return NULL;
00096     }
00097     return zbuf;
00098 }
00099 
00100 static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf)
00101 {
00102     if(zbuf == NULL) { return; }
00103     msgpack_zbuffer_destroy(zbuf);
00104     free(zbuf);
00105 }
00106 
00107 static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf)
00108 {
00109     size_t used = (char*)zbuf->stream.next_out - zbuf->data;
00110     size_t csize = used + zbuf->stream.avail_out;
00111     size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2;
00112 
00113     char* tmp = (char*)realloc(zbuf->data, nsize);
00114     if(tmp == NULL) {
00115         return false;
00116     }
00117 
00118     zbuf->data = tmp;
00119     zbuf->stream.next_out  = (Bytef*)(tmp + used);
00120     zbuf->stream.avail_out = nsize - used;
00121 
00122     return true;
00123 }
00124 
00125 static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len)
00126 {
00127     msgpack_zbuffer* zbuf = (msgpack_zbuffer*)data;
00128 
00129     zbuf->stream.next_in = (Bytef*)buf;
00130     zbuf->stream.avail_in = len;
00131 
00132     while(zbuf->stream.avail_in > 0) {
00133         if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
00134             if(!msgpack_zbuffer_expand(zbuf)) {
00135                 return -1;
00136             }
00137         }
00138 
00139         if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) {
00140             return -1;
00141         }
00142     }
00143 
00144     return 0;
00145 }
00146 
00147 static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf)
00148 {
00149     while(true) {
00150         switch(deflate(&zbuf->stream, Z_FINISH)) {
00151         case Z_STREAM_END:
00152             return zbuf->data;
00153         case Z_OK:
00154             if(!msgpack_zbuffer_expand(zbuf)) {
00155                 return NULL;
00156             }
00157             break;
00158         default:
00159             return NULL;
00160         }
00161     }
00162 }
00163 
00164 static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf)
00165 {
00166     return zbuf->data;
00167 }
00168 
00169 static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf)
00170 {
00171     return (char*)zbuf->stream.next_out - zbuf->data;
00172 }
00173 
00174 static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf)
00175 {
00176     zbuf->stream.avail_out += (char*)zbuf->stream.next_out - zbuf->data;
00177     zbuf->stream.next_out = (Bytef*)zbuf->data;
00178 }
00179 
00180 static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf)
00181 {
00182     if(deflateReset(&zbuf->stream) != Z_OK) {
00183         return false;
00184     }
00185     msgpack_zbuffer_reset_buffer(zbuf);
00186     return true;
00187 }
00188 
00189 static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf)
00190 {
00191     char* tmp = zbuf->data;
00192     zbuf->data = NULL;
00193     zbuf->stream.next_out = NULL;
00194     zbuf->stream.avail_out = 0;
00195     return tmp;
00196 }
00197 
00198 /** @} */
00199 
00200 
00201 #ifdef __cplusplus
00202 }
00203 #endif
00204 
00205 #endif /* msgpack/zbuffer.h */
00206