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 <zlib.h>
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 
29 typedef struct msgpack_zbuffer {
30  z_stream stream;
31  char* data;
32  size_t init_size;
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 = (size_t)((char *)(zbuf->stream.next_out) - zbuf->data);
104  size_t csize = used + zbuf->stream.avail_out;
105 
106  size_t nsize = (csize == 0) ? zbuf->init_size : csize * 2;
107 
108  char* tmp = (char*)realloc(zbuf->data, nsize);
109  if(tmp == NULL) {
110  return false;
111  }
112 
113  zbuf->data = tmp;
114  zbuf->stream.next_out = (Bytef*)(tmp + used);
115  zbuf->stream.avail_out = (uInt)(nsize - used);
116 
117  return true;
118 }
119 
120 static inline int msgpack_zbuffer_write(void* data, const char* buf, size_t len)
121 {
123 
124  zbuf->stream.next_in = (Bytef*)buf;
125  zbuf->stream.avail_in = (uInt)len;
126 
127  while(zbuf->stream.avail_in > 0) {
128  if(zbuf->stream.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
129  if(!msgpack_zbuffer_expand(zbuf)) {
130  return -1;
131  }
132  }
133 
134  if(deflate(&zbuf->stream, Z_NO_FLUSH) != Z_OK) {
135  return -1;
136  }
137  }
138 
139  return 0;
140 }
141 
142 static inline char* msgpack_zbuffer_flush(msgpack_zbuffer* zbuf)
143 {
144  while(true) {
145  switch(deflate(&zbuf->stream, Z_FINISH)) {
146  case Z_STREAM_END:
147  return zbuf->data;
148  case Z_OK:
149  case Z_BUF_ERROR:
150  if(!msgpack_zbuffer_expand(zbuf)) {
151  return NULL;
152  }
153  break;
154  default:
155  return NULL;
156  }
157  }
158 }
159 
160 static inline const char* msgpack_zbuffer_data(const msgpack_zbuffer* zbuf)
161 {
162  return zbuf->data;
163 }
164 
165 static inline size_t msgpack_zbuffer_size(const msgpack_zbuffer* zbuf)
166 {
167  return (size_t)((char *)(zbuf->stream.next_out) - zbuf->data);
168 }
169 
170 static inline void msgpack_zbuffer_reset_buffer(msgpack_zbuffer* zbuf)
171 {
172  zbuf->stream.avail_out += (uInt)((char*)zbuf->stream.next_out - zbuf->data);
173  zbuf->stream.next_out = (Bytef*)zbuf->data;
174 }
175 
176 static inline bool msgpack_zbuffer_reset(msgpack_zbuffer* zbuf)
177 {
178  if(deflateReset(&zbuf->stream) != Z_OK) {
179  return false;
180  }
181  msgpack_zbuffer_reset_buffer(zbuf);
182  return true;
183 }
184 
185 static inline char* msgpack_zbuffer_release_buffer(msgpack_zbuffer* zbuf)
186 {
187  char* tmp = zbuf->data;
188  zbuf->data = NULL;
189  zbuf->stream.next_out = NULL;
190  zbuf->stream.avail_out = 0;
191  return tmp;
192 }
193 
197 #ifdef __cplusplus
198 }
199 #endif
200 
201 #endif /* msgpack/zbuffer.h */
sysdep.h
MSGPACK_ZBUFFER_RESERVE_SIZE
#define MSGPACK_ZBUFFER_RESERVE_SIZE
Definition: zbuffer.h:57
msgpack_zbuffer::stream
z_stream stream
Definition: zbuffer.h:30
data
const char * data
Definition: unpack_template.h:94
msgpack_zbuffer
Definition: zbuffer.h:29
msgpack_zbuffer::init_size
size_t init_size
Definition: zbuffer.h:32
msgpack_zbuffer
struct msgpack_zbuffer msgpack_zbuffer
len
const char size_t len
Definition: unpack_template.h:94
msgpack_zbuffer::data
char * data
Definition: zbuffer.h:31