1/* 2 * MessagePack for C deflate buffer implementation 3 * 4 * Copyright (C) 2010 FURUHASHI Sadayuki 5 * 6 * Distributed under the Boost Software License, Version 1.0. 7 * (See accompanying file LICENSE_1_0.txt or copy at 8 * http://www.boost.org/LICENSE_1_0.txt) 9 */ 10#ifndef MSGPACK_ZBUFFER_H 11#define MSGPACK_ZBUFFER_H 12 13#include "sysdep.h" 14#include <stdlib.h> 15#include <string.h> 16#include <zlib.h> 17 18#ifdef __cplusplus 19extern "C" { 20#endif 21 22 23/** 24 * @defgroup msgpack_zbuffer Compressed buffer 25 * @ingroup msgpack_buffer 26 * @{ 27 */ 28 29typedef struct msgpack_zbuffer { 30 z_stream stream; 31 char* data; 32 size_t init_size; 33} msgpack_zbuffer; 34 35#ifndef MSGPACK_ZBUFFER_INIT_SIZE 36#define MSGPACK_ZBUFFER_INIT_SIZE 8192 37#endif 38 39static inline bool msgpack_zbuffer_init( 40 msgpack_zbuffer* zbuf, int level, size_t init_size); 41static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf); 42 43static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size); 44static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf); 45 46static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf); 47 48static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf); 49static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf); 50 51static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf); 52static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf); 53static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf); 54 55 56#ifndef MSGPACK_ZBUFFER_RESERVE_SIZE 57#define MSGPACK_ZBUFFER_RESERVE_SIZE 512 58#endif 59 60static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len); 61 62static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf); 63 64 65static inline bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf, 66 int level, size_t init_size) 67{ 68 memset(zbuf, 0, sizeof(msgpack_zbuffer)); 69 zbuf->init_size = init_size; 70 if(deflateInit(&zbuf->stream, level) != Z_OK) { 71 free(zbuf->data); 72 return false; 73 } 74 return true; 75} 76 77static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf) 78{ 79 deflateEnd(&zbuf->stream); 80 free(zbuf->data); 81} 82 83static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size) 84{ 85 msgpack_zbuffer* zbuf = (msgpack_zbuffer*)malloc(sizeof(msgpack_zbuffer)); 86 if (zbuf == NULL) return NULL; 87 if(!msgpack_zbuffer_init(zbuf, level, init_size)) { 88 free(zbuf); 89 return NULL; 90 } 91 return zbuf; 92} 93 94static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf) 95{ 96 if(zbuf == NULL) { return; } 97 msgpack_zbuffer_destroy(zbuf); 98 free(zbuf); 99} 100 101static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf) 102{ 103 size_t used = (char*)zbuf->stream.next_out - zbuf->data; 104 size_t csize = used + zbuf->stream.avail_out; 105 size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2; 106 107 char* tmp = (char*)realloc(zbuf->data, nsize); 108 if(tmp == NULL) { 109 return false; 110 } 111 112 zbuf->data = tmp; 113 zbuf->stream.next_out = (Bytef*)(tmp + used); 114 zbuf->stream.avail_out = nsize - used; 115 116 return true; 117} 118 119static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len) 120{ 121 msgpack_zbuffer* zbuf = (msgpack_zbuffer*)data; 122 123 zbuf->stream.next_in = (Bytef*)buf; 124 zbuf->stream.avail_in = len; 125 126 while(zbuf->stream.avail_in > 0) { 127 if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) { 128 if(!msgpack_zbuffer_expand(zbuf)) { 129 return -1; 130 } 131 } 132 133 if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) { 134 return -1; 135 } 136 } 137 138 return 0; 139} 140 141static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf) 142{ 143 while(true) { 144 switch(deflate(&zbuf->stream, Z_FINISH)) { 145 case Z_STREAM_END: 146 return zbuf->data; 147 case Z_OK: 148 if(!msgpack_zbuffer_expand(zbuf)) { 149 return NULL; 150 } 151 break; 152 default: 153 return NULL; 154 } 155 } 156} 157 158static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf) 159{ 160 return zbuf->data; 161} 162 163static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf) 164{ 165 return (char*)zbuf->stream.next_out - zbuf->data; 166} 167 168static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf) 169{ 170 zbuf->stream.avail_out += (char*)zbuf->stream.next_out - zbuf->data; 171 zbuf->stream.next_out = (Bytef*)zbuf->data; 172} 173 174static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf) 175{ 176 if(deflateReset(&zbuf->stream) != Z_OK) { 177 return false; 178 } 179 msgpack_zbuffer_reset_buffer(zbuf); 180 return true; 181} 182 183static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf) 184{ 185 char* tmp = zbuf->data; 186 zbuf->data = NULL; 187 zbuf->stream.next_out = NULL; 188 zbuf->stream.avail_out = 0; 189 return tmp; 190} 191 192/** @} */ 193 194 195#ifdef __cplusplus 196} 197#endif 198 199#endif /* msgpack/zbuffer.h */ 200 201