MessagePack for C
zbuffer.h
Go to the documentation of this file.
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 <assert.h>
17 #include <zlib.h>
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 
30 typedef struct msgpack_zbuffer {
31  z_stream stream;
32  char* data;
33  size_t init_size;
35 
36 #ifndef MSGPACK_ZBUFFER_INIT_SIZE
37 #define MSGPACK_ZBUFFER_INIT_SIZE 8192
38 #endif
39 
40 static inline bool msgpack_zbuffer_init(
41  msgpack_zbuffer* zbuf, int level, size_t init_size);
42 static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf);
43 
44 static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size);
45 static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf);
46 
47 static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf);
48 
49 static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf);
50 static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf);
51 
52 static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf);
53 static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf);
54 static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf);
55 
56 
57 #ifndef MSGPACK_ZBUFFER_RESERVE_SIZE
58 #define MSGPACK_ZBUFFER_RESERVE_SIZE 512
59 #endif
60 
61 static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len);
62 
63 static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf);
64 
65 
66 static inline bool msgpack_zbuffer_init(msgpack_zbuffer* zbuf,
67  int level, size_t init_size)
68 {
69  memset(zbuf, 0, sizeof(msgpack_zbuffer));
70  zbuf->init_size = init_size;
71  if(deflateInit(&zbuf->stream, level) != Z_OK) {
72  free(zbuf->data);
73  return false;
74  }
75  return true;
76 }
77 
78 static inline void msgpack_zbuffer_destroy(msgpack_zbuffer* zbuf)
79 {
80  deflateEnd(&zbuf->stream);
81  free(zbuf->data);
82 }
83 
84 static inline msgpack_zbuffer* msgpack_zbuffer_new(int level, size_t init_size)
85 {
86  msgpack_zbuffer* zbuf = (msgpack_zbuffer*)malloc(sizeof(msgpack_zbuffer));
87  if (zbuf == NULL) return NULL;
88  if(!msgpack_zbuffer_init(zbuf, level, init_size)) {
89  free(zbuf);
90  return NULL;
91  }
92  return zbuf;
93 }
94 
95 static inline void msgpack_zbuffer_free(msgpack_zbuffer* zbuf)
96 {
97  if(zbuf == NULL) { return; }
98  msgpack_zbuffer_destroy(zbuf);
99  free(zbuf);
100 }
101 
102 static inline bool msgpack_zbuffer_expand(msgpack_zbuffer* zbuf)
103 {
104  size_t used = (size_t)((char *)(zbuf->stream.next_out) - zbuf->data);
105  size_t csize = used + zbuf->stream.avail_out;
106 
107  size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2;
108 
109  char* tmp = (char*)realloc(zbuf->data, nsize);
110  if(tmp == NULL) {
111  return false;
112  }
113 
114  zbuf->data = tmp;
115  zbuf->stream.next_out = (Bytef*)(tmp + used);
116  zbuf->stream.avail_out = (uInt)(nsize - used);
117 
118  return true;
119 }
120 
121 static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len)
122 {
124 
125  assert(buf || len == 0);
126  if(!buf) return 0;
127 
128  zbuf->stream.next_in = (Bytef*)buf;
129  zbuf->stream.avail_in = (uInt)len;
130 
131  while(zbuf->stream.avail_in > 0) {
132  if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
133  if(!msgpack_zbuffer_expand(zbuf)) {
134  return -1;
135  }
136  }
137 
138  if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) {
139  return -1;
140  }
141  }
142 
143  return 0;
144 }
145 
146 static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf)
147 {
148  while(true) {
149  switch(deflate(&zbuf->stream, Z_FINISH)) {
150  case Z_STREAM_END:
151  return zbuf->data;
152  case Z_OK:
153  case Z_BUF_ERROR:
154  if(!msgpack_zbuffer_expand(zbuf)) {
155  return NULL;
156  }
157  break;
158  default:
159  return NULL;
160  }
161  }
162 }
163 
164 static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf)
165 {
166  return zbuf->data;
167 }
168 
169 static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf)
170 {
171  return (size_t)((char *)(zbuf->stream.next_out) - zbuf->data);
172 }
173 
174 static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf)
175 {
176  zbuf->stream.avail_out += (uInt)((char*)zbuf->stream.next_out - zbuf->data);
177  zbuf->stream.next_out = (Bytef*)zbuf->data;
178 }
179 
180 static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf)
181 {
182  if(deflateReset(&zbuf->stream) != Z_OK) {
183  return false;
184  }
185  msgpack_zbuffer_reset_buffer(zbuf);
186  return true;
187 }
188 
189 static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf)
190 {
191  char* tmp = zbuf->data;
192  zbuf->data = NULL;
193  zbuf->stream.next_out = NULL;
194  zbuf->stream.avail_out = 0;
195  return tmp;
196 }
197 
201 #ifdef __cplusplus
202 }
203 #endif
204 
205 #endif /* msgpack/zbuffer.h */
#define MSGPACK_ZBUFFER_RESERVE_SIZE
Definition: zbuffer.h:58
struct msgpack_zbuffer msgpack_zbuffer
Definition: zbuffer.h:30
size_t init_size
Definition: zbuffer.h:33
z_stream stream
Definition: zbuffer.h:31
char * data
Definition: zbuffer.h:32
const char * data
Definition: unpack_template.h:94
const char size_t len
Definition: unpack_template.h:94