25
|
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 |
|
19 extern "C" { |
|
20 #endif |
|
21 |
|
22 |
|
23 /** |
|
24 * @defgroup msgpack_zbuffer Compressed buffer |
|
25 * @ingroup msgpack_buffer |
|
26 * @{ |
|
27 */ |
|
28 |
|
29 typedef 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 |
|
39 static inline bool msgpack_zbuffer_init( |
|
40 msgpack_zbuffer* zbuf, int level, size_t init_size); |
|
41 static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf); |
|
42 |
|
43 static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size); |
|
44 static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf); |
|
45 |
|
46 static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf); |
|
47 |
|
48 static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf); |
|
49 static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf); |
|
50 |
|
51 static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf); |
|
52 static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf); |
|
53 static 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 |
|
60 static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len); |
|
61 |
|
62 static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf); |
|
63 |
|
64 |
|
65 static 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 |
|
77 static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf) |
|
78 { |
|
79 deflateEnd(&zbuf->stream); |
|
80 free(zbuf->data); |
|
81 } |
|
82 |
|
83 static 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 |
|
94 static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf) |
|
95 { |
|
96 if(zbuf == NULL) { return; } |
|
97 msgpack_zbuffer_destroy(zbuf); |
|
98 free(zbuf); |
|
99 } |
|
100 |
|
101 static 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 |
|
119 static 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 |
|
141 static 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 |
|
158 static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf) |
|
159 { |
|
160 return zbuf->data; |
|
161 } |
|
162 |
|
163 static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf) |
|
164 { |
|
165 return (char*)zbuf->stream.next_out - zbuf->data; |
|
166 } |
|
167 |
|
168 static 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 |
|
174 static 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 |
|
183 static 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 |