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