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(
48 msgpack_zbuffer* zbuf, 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, size_t 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 static inline 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 static inline 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 static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size)
92 {
93 msgpack_zbuffer* zbuf = (msgpack_zbuffer*)malloc(sizeof(msgpack_zbuffer));
94 if (zbuf == NULL) return NULL;
95 if(!msgpack_zbuffer_init(zbuf, level, init_size)) {
96 free(zbuf);
97 return NULL;
98 }
99 return zbuf;
100 }
101
msgpack_zbuffer_free(msgpack_zbuffer * zbuf)102 static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf)
103 {
104 if(zbuf == NULL) { return; }
105 msgpack_zbuffer_destroy(zbuf);
106 free(zbuf);
107 }
108
msgpack_zbuffer_expand(msgpack_zbuffer * zbuf)109 static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf)
110 {
111 size_t used = (char*)zbuf->stream.next_out - zbuf->data;
112 size_t csize = used + zbuf->stream.avail_out;
113 size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2;
114
115 char* tmp = (char*)realloc(zbuf->data, nsize);
116 if(tmp == NULL) {
117 return false;
118 }
119
120 zbuf->data = tmp;
121 zbuf->stream.next_out = (Bytef*)(tmp + used);
122 zbuf->stream.avail_out = nsize - used;
123
124 return true;
125 }
126
msgpack_zbuffer_write(void * data,const char * buf,size_t len)127 static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len)
128 {
129 msgpack_zbuffer* zbuf = (msgpack_zbuffer*)data;
130
131 zbuf->stream.next_in = (Bytef*)buf;
132 zbuf->stream.avail_in = len;
133
134 while(zbuf->stream.avail_in > 0) {
135 if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
136 if(!msgpack_zbuffer_expand(zbuf)) {
137 return -1;
138 }
139 }
140
141 if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) {
142 return -1;
143 }
144 }
145
146 return 0;
147 }
148
msgpack_zbuffer_flush(msgpack_zbuffer * zbuf)149 static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf)
150 {
151 while(true) {
152 switch(deflate(&zbuf->stream, Z_FINISH)) {
153 case Z_STREAM_END:
154 return zbuf->data;
155 case Z_OK:
156 if(!msgpack_zbuffer_expand(zbuf)) {
157 return NULL;
158 }
159 break;
160 default:
161 return NULL;
162 }
163 }
164 }
165
msgpack_zbuffer_data(const msgpack_zbuffer * zbuf)166 static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf)
167 {
168 return zbuf->data;
169 }
170
msgpack_zbuffer_size(const msgpack_zbuffer * zbuf)171 static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf)
172 {
173 return (char*)zbuf->stream.next_out - zbuf->data;
174 }
175
msgpack_zbuffer_reset_buffer(msgpack_zbuffer * zbuf)176 static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf)
177 {
178 zbuf->stream.avail_out += (char*)zbuf->stream.next_out - zbuf->data;
179 zbuf->stream.next_out = (Bytef*)zbuf->data;
180 }
181
msgpack_zbuffer_reset(msgpack_zbuffer * zbuf)182 static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf)
183 {
184 if(deflateReset(&zbuf->stream) != Z_OK) {
185 return false;
186 }
187 msgpack_zbuffer_reset_buffer(zbuf);
188 return true;
189 }
190
msgpack_zbuffer_release_buffer(msgpack_zbuffer * zbuf)191 static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf)
192 {
193 char* tmp = zbuf->data;
194 zbuf->data = NULL;
195 zbuf->stream.next_out = NULL;
196 zbuf->stream.avail_out = 0;
197 return tmp;
198 }
199
200 /** @} */
201
202
203 #ifdef __cplusplus
204 }
205 #endif
206
207 #endif /* msgpack/zbuffer.h */
208
209