libnavajo
web server for static and dynamic pages developement in C++
nvjGzip.h
Go to the documentation of this file.
1 //********************************************************
12 //********************************************************
13 
14 #ifndef NVJGZIP_H_
15 #define NVJGZIP_H_
16 
17 
18 #include <stdlib.h>
19 #include <string>
20 #include <stdexcept>
21 
22 #include "zlib.h"
23 #if (ZLIB_VERNUM < 0x1271)
24  #include "zlibPatchOldVersion.h"
25 #endif
26 
27 #define CHUNK 16384
28 
29 
30 
31 //********************************************************
32 
33 inline size_t nvj_gzip( unsigned char** dst, const unsigned char* src, const size_t sizeSrc, bool rawDeflateData=false )
34 {
35  z_stream strm;
36  size_t sizeDst=CHUNK;
37 
38  /* allocate deflate state */
39  strm.zalloc = Z_NULL;
40  strm.zfree = Z_NULL;
41  strm.opaque = Z_NULL;
42 
43  if ( deflateInit2(&strm, Z_BEST_SPEED, Z_DEFLATED, rawDeflateData ? -15 : 16+MAX_WBITS, 9, Z_DEFAULT_STRATEGY) != Z_OK)
44  throw std::runtime_error(std::string("gzip : inflateInit2 error") );
45 
46  if ( (*dst=(unsigned char *)malloc(CHUNK * sizeof (unsigned char))) == NULL )
47  throw std::runtime_error(std::string("gzip : malloc error (1)") );
48 
49  strm.avail_in = sizeSrc;
50  strm.next_in = (Bytef*)src;
51 
52  int i=0;
53 
54  do
55  {
56  strm.avail_out = CHUNK;
57  strm.next_out = (Bytef*)*dst + i*CHUNK;
58  sizeDst=CHUNK * (i+1);
59 
60  if (deflate(&strm, Z_FINISH ) == Z_STREAM_ERROR) /* state not clobbered */
61  {
62  free (*dst);
63  throw std::runtime_error(std::string("gzip : deflate error") );
64  }
65 
66  i++;
67 
68  if (strm.avail_out == 0)
69  {
70  unsigned char* reallocDst = (unsigned char*) realloc (*dst, CHUNK * (i+1) * sizeof (unsigned char) );
71 
72  if (reallocDst!=NULL)
73  *dst=reallocDst;
74  else
75  {
76  free (reallocDst);
77  free (*dst);
78  throw std::runtime_error(std::string("gzip : (re)allocating memory") );
79  }
80  }
81  }
82  while (strm.avail_out == 0);
83 
84  /* clean up and return */
85  (void)deflateEnd(&strm);
86  return sizeDst - strm.avail_out;
87 }
88 
89 //********************************************************
90 
91 inline size_t nvj_gunzip( unsigned char** dst, const unsigned char* src, const size_t sizeSrc, bool rawDeflateData=false )
92 {
93  z_stream strm;
94  size_t sizeDst=CHUNK;
95  int ret;
96 
97  if (src == NULL)
98  throw std::runtime_error(std::string("gunzip : src == NULL !") );
99 
100  /* allocate inflate state */
101  strm.zalloc = Z_NULL;
102  strm.zfree = Z_NULL;
103  strm.opaque = Z_NULL;
104  strm.avail_in = 0;
105  strm.next_in = Z_NULL;
106 
107 
108  if (inflateInit2(&strm, rawDeflateData ? -15 : 16+MAX_WBITS) != Z_OK)
109  throw std::runtime_error(std::string("gunzip : inflateInit2 error") );
110 
111  if ( (*dst=(unsigned char *)malloc(CHUNK * sizeof (unsigned char))) == NULL )
112  throw std::runtime_error(std::string("gunzip : malloc error (2)") );
113 
114  strm.avail_in = sizeSrc;
115  strm.next_in = (Bytef*)src;
116 
117  int i=0;
118 
119  do
120  {
121  strm.avail_out = CHUNK;
122  strm.next_out = (Bytef*)*dst + i*CHUNK;
123  sizeDst=CHUNK * (i+1);
124 
125  ret = inflate(&strm, Z_NO_FLUSH);
126 
127  switch (ret)
128  {
129  case Z_STREAM_ERROR:
130  free (*dst);
131  throw std::runtime_error(std::string("gunzip : inflate Z_STREAM_ERROR") );
132  case Z_NEED_DICT:
133  case Z_DATA_ERROR:
134  case Z_MEM_ERROR:
135  (void)inflateEnd(&strm);
136  free (*dst);
137  throw std::runtime_error(std::string("gunzip : inflate error") );
138  }
139 
140  i++;
141  if (strm.avail_out == 0)
142  {
143  unsigned char* reallocDst = (unsigned char*) realloc (*dst, CHUNK * (i+1) * sizeof (unsigned char) );
144 
145  if (reallocDst!=NULL)
146  *dst=reallocDst;
147  else
148  {
149  free (reallocDst);
150  free (*dst);
151  throw std::runtime_error(std::string("gunzip : (re)allocating memory") );
152  }
153  }
154  }
155  while (strm.avail_out == 0);
156 
157  /* clean up and return */
158  (void)inflateEnd(&strm);
159  return sizeDst - strm.avail_out;
160 }
161 
162 //----------------------------------------------------------------------------------------
163 
164  inline size_t nvj_gzip_websocket_v2( unsigned char** dst, const unsigned char* src, const size_t sizeSrc, z_stream* pstream=NULL, const unsigned int sizeChunk = CHUNK)
165  {
166 
167  size_t sizeDst = 0;
168 
169  int rmndr = sizeSrc % sizeChunk;
170  int iterations = (rmndr == 0 ? sizeSrc / sizeChunk : sizeSrc / sizeChunk + 1) ;
171  int in = sizeChunk;
172  int flush = Z_NO_FLUSH;
173 
174  *dst = NULL;
175 
176  for ( int i = 0; i < iterations; i++ )
177  {
178  if(i == iterations - 1){
179  flush = Z_SYNC_FLUSH;
180  if(rmndr != 0){
181  in = rmndr;
182  }
183  }
184 
185 
186  (*pstream).avail_in = in;
187  (*pstream).next_in = (Bytef*)src + i * sizeChunk;
188 
189  do
190  {
191  unsigned char* reallocDst = (unsigned char*) realloc (*dst, (sizeDst + sizeChunk) * sizeof (unsigned char) );
192 
193  if (reallocDst!=NULL){
194  *dst = reallocDst;
195  }
196  else
197  {
198  free (reallocDst);
199  free (*dst);
200  throw std::runtime_error(std::string("gzip : (re)allocating memory") );
201  }
202 
203  (*pstream).avail_out = sizeChunk;
204  (*pstream).next_out = (Bytef*)*dst + sizeDst;
205 
206  if (deflate(pstream, flush) == Z_STREAM_ERROR) /* state not clobbered */
207  {
208  free (*dst);
209  throw std::runtime_error(std::string("gzip : deflate error") );
210  }
211  sizeDst += sizeChunk - (*pstream).avail_out;
212  }
213  while ((*pstream).avail_out == 0 );
214  }
215 
216  sizeDst -= 4;
217 
218  unsigned char* reallocDst = (unsigned char*) realloc (*dst, sizeDst * sizeof (unsigned char) );
219 
220  if (reallocDst!=NULL){
221  *dst = reallocDst;
222  }
223  else
224  {
225  free (reallocDst);
226  free (*dst);
227  throw std::runtime_error(std::string("gzip : (re)allocating memory") );
228  }
229 
230  return sizeDst;
231 
232  }
233 
234 
235 
236  //********************************************************
237 
238  inline void nvj_end_stream(z_stream* pstream=NULL){
239  (void)deflateEnd(pstream);
240  }
241 
242  //********************************************************
243 
244  inline void nvj_init_stream(z_stream* pstream=NULL, bool rawDeflateData=false, int level=Z_BEST_COMPRESSION, int strategy=Z_DEFAULT_STRATEGY ){
245  (*pstream).zalloc = Z_NULL;
246  (*pstream).zfree = Z_NULL;
247  (*pstream).opaque = Z_NULL;
248  if ( deflateInit2(pstream, level, Z_DEFLATED, rawDeflateData ? -15 : 16+MAX_WBITS, 9, strategy) != Z_OK)
249  throw std::runtime_error(std::string("gzip : deflateInit2 error") );
250  }
251 
252  //********************************************************
253 
254 inline size_t nvj_gunzip_websocket_v2( unsigned char** dst, const unsigned char* src, size_t sizeSrc, bool rawDeflateData=false, unsigned char* dictionary = NULL, unsigned int* dictLength = NULL, const unsigned int sizeChunk = CHUNK)
255 {
256  z_stream strm;
257  size_t sizeDst=0;
258  int rmndr = sizeSrc % sizeChunk;
259  int iterations = (rmndr == 0 ? sizeSrc / sizeChunk : sizeSrc / sizeChunk + 1) ;
260  int in = sizeChunk;
261  int ret;
262  *dst = NULL;
263 
264  if (src == NULL)
265  throw std::runtime_error(std::string("gunzip : src == NULL !") );
266 
267  /* allocate inflate state */
268  strm.zalloc = Z_NULL;
269  strm.zfree = Z_NULL;
270  strm.opaque = Z_NULL;
271  strm.avail_in = 0;
272  strm.next_in = Z_NULL;
273 
274 
275  if (inflateInit2(&strm, rawDeflateData ? -15 : 16+MAX_WBITS) != Z_OK)
276  throw std::runtime_error(std::string("gunzip : inflateInit2 error") );
277 
278  if( *dictLength != 0) {
279  if( inflateSetDictionary(&strm, (Bytef*) dictionary, *dictLength) != Z_OK )
280  throw std::runtime_error(std::string("gunzip : inflateSetDictionary error") ) ;
281  }
282 
283  for ( int i = 0; i < iterations; i++ ) //TODO Ne pas oublier le reste
284  {
285 
286  if( (i == iterations - 1) && (rmndr != 0) ){
287  in = rmndr;
288  }
289 
290  strm.avail_in = in;
291  strm.next_in = (Bytef*)src + i * sizeChunk;
292 
293  do
294  {
295 
296  unsigned char* reallocDst = (unsigned char*) realloc (*dst, (sizeDst + sizeChunk) * sizeof (unsigned char) );
297 
298  if (reallocDst!=NULL)
299  *dst=reallocDst;
300  else
301  {
302  free (reallocDst);
303  free (*dst);
304  throw std::runtime_error(std::string("gunzip : (re)allocating memory") );
305  }
306 
307  strm.avail_out = sizeChunk;
308  strm.next_out = (Bytef*)*dst + sizeDst;
309 
310  ret = inflate(&strm, Z_NO_FLUSH);
311 
312  switch (ret)
313  {
314  case Z_STREAM_ERROR:
315  free (*dst);
316  throw std::runtime_error(std::string("gunzip : inflate Z_STREAM_ERROR") );
317  case Z_NEED_DICT:
318  case Z_DATA_ERROR:
319  // ICI
320  case Z_MEM_ERROR:
321  (void)inflateEnd(&strm);
322  free (*dst);
323  throw std::runtime_error(std::string("gunzip : inflate error") );
324  }
325 
326  sizeDst += sizeChunk - strm.avail_out;
327  }
328  while (strm.avail_out == 0);
329  }
330 
331  unsigned char* reallocDst = (unsigned char*) realloc (*dst, (sizeDst) * sizeof (unsigned char) );
332 
333  if (reallocDst!=NULL)
334  *dst=reallocDst;
335  else
336  {
337  free (reallocDst);
338  free (*dst);
339  throw std::runtime_error(std::string("gunzip : (re)allocating memory") );
340  }
341 
342  inflateGetDictionary(&strm, (Bytef*)dictionary, dictLength);
343 
344  /* clean up and return */
345  (void)inflateEnd(&strm);
346  return sizeDst;
347 }
348 
349 #endif
350 
functions inflateSetDictionary and inflateGetDictionary for versions older than 1.8