GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/zlibstreams.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 240 316 75.9%
Functions: 26 29 89.7%
Branches: 77 141 54.6%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/encode/zlibstreams.h"
30 #include "gate/memalloc.h"
31 #include "gate/atomics.h"
32 #include "gate/results.h"
33 #include "gate/debugging.h"
34
35 #if defined(GATE_EXTLIB_ZLIB)
36 # define GATE_ENCODE_ZLIBSTREAM_USE_ZLIB 1
37 #else
38 # define GATE_ENCODE_ZLIBSTREAM_NO_IMPL 1
39 #endif
40
41 #if defined(GATE_ENCODE_ZLIBSTREAM_USE_ZLIB)
42
43 #include "zlib.h"
44
45 /* output stream encoder implementation */
46
47 12 static voidpf gate_zlibstream_alloc_func(voidpf opaque, uInt items, uInt size)
48 {
49 voidpf ret;
50 12 gate_size_t const mem_sz = (gate_size_t)items * (gate_size_t)size;
51 (void)opaque;
52
53 12 ret = gate_mem_alloc(mem_sz);
54
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!ret)
55 {
56 GATE_DEBUG_TRACE("ZLIB allocation failed");
57 }
58 else
59 {
60 12 gate_mem_clear(ret, mem_sz);
61 }
62 12 return ret;
63 }
64 12 static void gate_zlibstream_free_func(voidpf opaque, voidpf address)
65 {
66 (void)opaque;
67
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (address)
68 {
69 12 gate_mem_dealloc(address);
70 }
71 12 }
72
73 static void gate_zlibencoder_release_impl(void* self);
74 static int gate_zlibencoder_retain_impl(void* self);
75 2 static char const* gate_zlibencoder_interface_name_impl(void* self)
76 {
77 (void)self;
78 2 return GATE_INTERFACE_NAME_STREAM;
79 }
80 static gate_result_t gate_zlibencoder_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
81 static gate_result_t gate_zlibencoder_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
82 static gate_result_t gate_zlibencoder_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
83 static gate_result_t gate_zlibencoder_flush_impl(void* self);
84
85 static GATE_INTERFACE_VTBL(gate_stream) gate_zlibencoder_vtbl;
86 2 static void gate_init_zlibencoder_vtbl()
87 {
88
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!gate_zlibencoder_vtbl.get_interface_name)
89 {
90 GATE_INTERFACE_VTBL(gate_stream) const local_vtbl =
91 {
92 &gate_zlibencoder_interface_name_impl,
93 &gate_zlibencoder_release_impl,
94 &gate_zlibencoder_retain_impl,
95 &gate_zlibencoder_read_impl,
96 &gate_zlibencoder_peek_impl,
97 &gate_zlibencoder_write_impl,
98 &gate_zlibencoder_flush_impl
99 };
100 1 gate_zlibencoder_vtbl = local_vtbl;
101 }
102 2 }
103
104 typedef struct gate_zlibencoder_impl
105 {
106 GATE_INTERFACE_VTBL(gate_stream)* vtbl;
107
108 gate_atomic_int_t ref_counter;
109 gate_stream_t* dest_stream;
110 z_stream zipper;
111 char data_buffer[GATE_MAX_BLOCK_COPYBUFFER_LENGTH];
112 gate_size_t data_buffer_used;
113
114 } gate_zlibencoder_impl_t;
115
116 2 gate_result_t gate_zlib_encoder_create(gate_stream_t* output, gate_bool_t gzformat, gate_int16_t compression, gate_stream_t** ptr2streamptr)
117 {
118 gate_result_t ret;
119 do
120 {
121 gate_zlibencoder_impl_t* impl;
122 int zresult;
123 2 int level = Z_DEFAULT_COMPRESSION;
124 #if defined(GATE_SYS_WINCE) || defined(GATE_SYS_DOS)
125 int memlevel = MAX_MEM_LEVEL - 2;
126 int window_bits = MAX_WBITS - 1;
127 #else
128 2 int memlevel = MAX_MEM_LEVEL;
129 2 int window_bits = MAX_WBITS;
130 #endif
131
132
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if ((output == NULL) || (ptr2streamptr == NULL))
133 {
134 GATE_DEBUG_TRACE("ZLIB encoder NULL pointer");
135 ret = GATE_RESULT_NULLPOINTER;
136 break;
137 }
138 2 impl = (gate_zlibencoder_impl_t*)gate_mem_alloc(sizeof(gate_zlibencoder_impl_t));
139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (impl == NULL)
140 {
141 GATE_DEBUG_TRACE("Failed to allocate ZLIB encoder");
142 ret = GATE_RESULT_OUTOFMEMORY;
143 break;
144 }
145
146 2 gate_mem_clear(impl, sizeof(gate_zlibencoder_impl_t));
147 2 gate_init_zlibencoder_vtbl();
148 2 impl->vtbl = &gate_zlibencoder_vtbl;
149 2 gate_atomic_int_init(&impl->ref_counter, 1);
150 2 impl->dest_stream = output;
151
152
1/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 switch (compression)
153 {
154 case GATE_ZLIB_COMPRESSION_MINIMUM: level = Z_BEST_SPEED; break;
155 case GATE_ZLIB_COMPRESSION_LOW: level = (Z_BEST_SPEED + (Z_BEST_SPEED + Z_BEST_COMPRESSION) / 2) / 2; break;
156 case GATE_ZLIB_COMPRESSION_MEDIUM: level = (Z_BEST_SPEED + Z_BEST_COMPRESSION) / 2; break;
157 case GATE_ZLIB_COMPRESSION_HIGH: level = (Z_BEST_COMPRESSION + (Z_BEST_SPEED + Z_BEST_COMPRESSION) / 2) / 2; break;
158 case GATE_ZLIB_COMPRESSION_MAXIMUM: level = Z_BEST_COMPRESSION; break;
159 }
160
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (gzformat)
161 {
162 1 window_bits += 16;
163 }
164
165 2 impl->zipper.zalloc = &gate_zlibstream_alloc_func;
166 2 impl->zipper.opaque = Z_NULL;
167 2 impl->zipper.zfree = &gate_zlibstream_free_func;
168
169 2 zresult = deflateInit2(&impl->zipper, level, Z_DEFLATED, window_bits, memlevel, Z_DEFAULT_STRATEGY);
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (zresult != Z_OK)
171 {
172 GATE_DEBUG_TRACE_MSG_VALUE("deflateInit2() failed", zresult);
173 gate_mem_dealloc(impl);
174 ret = GATE_RESULT_FAILED;
175 break;
176 }
177
178 2 impl->data_buffer_used = 0;
179
180 2 gate_object_retain(impl->dest_stream);
181 2 *ptr2streamptr = (gate_stream_t*)impl;
182
183 2 ret = GATE_RESULT_OK;
184 } while (0);
185
186 2 return ret;
187 }
188
189 4 static void gate_zlibencoder_release_impl(void* self)
190 {
191 4 gate_zlibencoder_impl_t* impl = (gate_zlibencoder_impl_t*)self;
192
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (gate_atomic_int_dec(&impl->ref_counter) == 0)
193 {
194 2 gate_zlibencoder_flush_impl(self);
195 2 deflateEnd(&impl->zipper);
196 2 gate_object_release(impl->dest_stream);
197 2 gate_mem_dealloc(impl);
198 }
199 4 }
200 2 static int gate_zlibencoder_retain_impl(void* self)
201 {
202 2 gate_zlibencoder_impl_t* impl = (gate_zlibencoder_impl_t*)self;
203 2 return gate_atomic_int_inc(&impl->ref_counter);
204 }
205 2 static gate_result_t gate_zlibencoder_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
206 {
207 (void)self;
208 (void)buffer;
209 (void)bufferlength;
210 (void)returned;
211 2 return GATE_RESULT_NOTSUPPORTED;
212 }
213 2 static gate_result_t gate_zlibencoder_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
214 {
215 (void)self;
216 (void)buffer;
217 (void)bufferlength;
218 (void)returned;
219 2 return GATE_RESULT_NOTSUPPORTED;
220 }
221 20 static gate_result_t gate_zlibencoder_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
222 {
223 20 gate_result_t ret = GATE_RESULT_OK;
224 20 gate_zlibencoder_impl_t* impl = (gate_zlibencoder_impl_t*)self;
225 char compressed_buffer[GATE_MAX_STACK_COPYBUFFER_LENGTH];
226 20 gate_size_t bytesavailable = sizeof(impl->data_buffer) - impl->data_buffer_used;
227 20 gate_size_t bytesaccepted = bytesavailable < bufferlength ? bytesavailable : bufferlength;
228 int zresult;
229 gate_size_t bytescompressed;
230 gate_size_t byteswritten;
231 gate_size_t bytesremaining;
232
233 do
234 {
235 20 gate_mem_copy(&impl->data_buffer[impl->data_buffer_used], buffer, bytesaccepted);
236
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (written != NULL)
237 {
238 20 *written = bytesaccepted;
239 }
240 20 impl->data_buffer_used += bytesaccepted;
241
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (impl->data_buffer_used == 0)
243 {
244 GATE_DEBUG_TRACE("zlibencoder_write data_buffer_used==0");
245 ret = GATE_RESULT_INVALIDARG;
246 break;
247 }
248
249 20 impl->zipper.avail_in = (uInt)impl->data_buffer_used;
250 20 impl->zipper.next_in = (Bytef*)&impl->data_buffer[0];
251
252
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2 times.
22 while (impl->zipper.avail_in != 0)
253 {
254 20 impl->zipper.avail_out = sizeof(compressed_buffer);
255 20 impl->zipper.next_out = (Bytef*)&compressed_buffer[0];
256
257 20 zresult = deflate(&impl->zipper, Z_NO_FLUSH);
258
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
20 if ((zresult != Z_OK) && (zresult != Z_STREAM_END))
259 {
260 GATE_DEBUG_TRACE_MSG_VALUE("deflate() failed", zresult);
261 ret = GATE_RESULT_FAILED;
262 break;
263 }
264 20 bytescompressed = sizeof(compressed_buffer) - impl->zipper.avail_out;
265
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (bytescompressed > 0)
266 {
267 2 ret = gate_stream_write_block(impl->dest_stream, &compressed_buffer[0], bytescompressed, &byteswritten);
268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
269 {
270 GATE_DEBUG_TRACE_MSG_VALUE("zlib_encoder_write write_block failed", ret);
271 break;
272 }
273 }
274 else
275 {
276 18 break;
277 }
278 }
279
280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (impl->zipper.avail_in != 0)
281 {
282 bytesremaining = impl->zipper.avail_in;
283 gate_mem_move(&impl->data_buffer[0], &impl->data_buffer[impl->data_buffer_used - bytesremaining], bytesremaining);
284 impl->data_buffer_used = bytesremaining;
285 }
286 else
287 {
288 20 impl->data_buffer_used = 0;
289 }
290 } while (0);
291 20 return ret;
292 }
293 4 static gate_result_t gate_zlibencoder_flush_impl(void* self)
294 {
295 4 gate_result_t ret = GATE_RESULT_OK;
296 4 gate_zlibencoder_impl_t* impl = (gate_zlibencoder_impl_t*)self;
297
298 do
299 {
300 char compressed_buffer[GATE_MAX_STACK_COPYBUFFER_LENGTH];
301 int zresult;
302 gate_size_t bytescompressed;
303 gate_size_t byteswritten;
304
305 4 impl->zipper.next_in = (Bytef*)&impl->data_buffer[0];
306 4 impl->zipper.avail_in = (uInt)impl->data_buffer_used;
307
308 4 impl->zipper.avail_out = sizeof(compressed_buffer);
309 4 impl->zipper.next_out = (Bytef*)&compressed_buffer[0];
310
311 4 zresult = deflate(&impl->zipper, Z_FINISH);
312
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if ((zresult != Z_OK) && (zresult != Z_STREAM_END))
313 {
314 GATE_DEBUG_TRACE_MSG_VALUE("deflate(FINISH) failed", zresult);
315 ret = GATE_RESULT_FAILED;
316 break;
317 }
318
319 4 bytescompressed = sizeof(compressed_buffer) - impl->zipper.avail_out;
320 4 ret = gate_stream_write_block(impl->dest_stream, compressed_buffer, bytescompressed, &byteswritten);
321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (GATE_FAILED(ret))
322 {
323 GATE_DEBUG_TRACE_MSG_VALUE("zlibencoder_flush write_block failed", ret);
324 break;
325 }
326
327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (impl->zipper.avail_in < impl->data_buffer_used)
328 {
329 gate_size_t bytesoffset = impl->data_buffer_used - impl->zipper.avail_in;
330 gate_mem_move(&impl->data_buffer[0], &impl->data_buffer[bytesoffset], impl->zipper.avail_in);
331 impl->data_buffer_used = impl->zipper.avail_in;
332 }
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 } while (impl->zipper.avail_out == 0);
334
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
335 {
336 4 ret = gate_stream_flush(impl->dest_stream);
337 }
338 4 return ret;
339 }
340
341
342
343
344 /* input stream decoder implementation */
345
346 static void gate_zlibdecoder_release_impl(void* self);
347 static int gate_zlibdecoder_retain_impl(void* self);
348 static char const* gate_zlibdecoder_interface_name_impl(void* self);
349
350 static gate_result_t gate_zlibdecoder_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
351 static gate_result_t gate_zlibdecoder_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
352 static gate_result_t gate_zlibdecoder_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
353 static gate_result_t gate_zlibdecoder_flush_impl(void* self);
354
355 static gate_result_t gate_zlibdecoder_get_resource_impl(void* self, gate_enumint_t resource_type, gate_uintptr_t* resource);
356
357 static gate_result_t gate_zlibdecoder_can_read_impl(void* self, gate_bool_t* return_value);
358 static gate_result_t gate_zlibdecoder_can_write_impl(void* self, gate_bool_t* return_value);
359 static gate_result_t gate_zlibdecoder_get_size_impl(void* self, gate_int64_t* return_value);
360 static gate_result_t gate_zlibdecoder_get_available_impl(void* self, gate_int64_t* return_value);
361 static gate_result_t gate_zlibdecoder_seek_impl(void* self, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position);
362 static gate_result_t gate_zlibdecoder_reset_impl(void* self);
363 static gate_result_t gate_zlibdecoder_close_impl(void* self, gate_enumint_t close_type);
364
365 static GATE_INTERFACE_VTBL(gate_controlstream) gate_zlibdecoder_vtbl;
366 2 static void gate_init_zlibdecoder_vtbl()
367 {
368
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!gate_zlibdecoder_vtbl.get_interface_name)
369 {
370 static GATE_INTERFACE_VTBL(gate_controlstream) local_vtbl =
371 {
372 &gate_zlibdecoder_interface_name_impl,
373 &gate_zlibdecoder_release_impl,
374 &gate_zlibdecoder_retain_impl,
375
376 &gate_zlibdecoder_read_impl,
377 &gate_zlibdecoder_peek_impl,
378 &gate_zlibdecoder_write_impl,
379 &gate_zlibdecoder_flush_impl,
380
381 &gate_zlibdecoder_get_resource_impl,
382
383 &gate_zlibdecoder_can_read_impl,
384 &gate_zlibdecoder_can_write_impl,
385 &gate_zlibdecoder_get_size_impl,
386 &gate_zlibdecoder_get_available_impl,
387 &gate_zlibdecoder_seek_impl,
388 &gate_zlibdecoder_reset_impl,
389 &gate_zlibdecoder_close_impl
390 };
391 1 gate_zlibdecoder_vtbl = local_vtbl;
392 }
393 2 }
394
395 typedef struct gate_zlibdecoder_impl
396 {
397 GATE_INTERFACE_VTBL(gate_controlstream)* vtbl;
398
399 gate_atomic_int_t ref_counter; /* reference counter */
400 gate_stream_t* source_stream; /* source stream to deliver compressed data */
401 z_stream unzipper; /* unzip processing instance */
402 char source_buffer[GATE_MAX_BLOCK_COPYBUFFER_LENGTH]; /* internal source-stream input buffer */
403 char decoded_buffer[GATE_MAX_BLOCK_COPYBUFFER_LENGTH]; /* internal output buffer */
404 gate_size_t decoded_buffer_length; /* current amount of valid bytes in decoded_buffer */
405 gate_size_t decoded_buffer_offset; /* current start offset of valid bytes in decoded_buffer */
406 gate_uint64_t bytes_decoded_counter; /* sum of bytes that were sucessfully decompressed */
407 gate_uint64_t total_bytes_uncompressed; /* estimated total sum of bytes after decompression (incorrect if original data was greater 2^32 bytes) */
408
409 } gate_zlibdecoder_impl_t;
410
411 2 static gate_bool_t gate_zlib_decoder_get_content_length(gate_stream_t* stream, gate_uint64_t* ptr_length)
412 {
413 2 gate_bool_t ret = false;
414 2 gate_controlstream_t* ctrl = NULL;
415 gate_int64_t start_pos;
416 gate_int64_t avail;
417 gate_int64_t end_pos;
418 gate_result_t result;
419 gate_result_t result2;
420 2 char header[10] = { 0 };
421 2 char tail[8] = { 0 };
422 gate_size_t received;
423 gate_uint32_t uncompressed_size;
424
425 do
426 {
427
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!gate_object_implements_interface((gate_object_t*)stream, GATE_INTERFACE_NAME_CONTROLSTREAM))
428 {
429 break;
430 }
431
432 2 ctrl = (gate_controlstream_t*)stream;
433
434 2 result = gate_stream_peek(stream, header, sizeof(header), NULL);
435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(result);
436
437
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 if ((header[0] != (char)0x01f) || (header[1] != (char)0x08b) /*|| (header[0] != 8)*/)
438 {
439 break;
440 }
441
442 1 result = gate_stream_get_position(ctrl, &start_pos);
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(result);
444
445 1 result = gate_stream_get_available(ctrl, &avail);
446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(result);
447
448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (avail < sizeof(tail))
449 {
450 break;
451 }
452
453 1 end_pos = start_pos + avail;
454
455 /* jump to end of file to read tail-bytes */
456 1 result = gate_stream_seek(ctrl, end_pos - sizeof(tail), GATE_STREAM_SEEK_BEGIN, NULL);
457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(result);
458
459 1 result = gate_stream_peek(stream, tail, sizeof(tail), &received);
460
461 /* always try to jump back to begin of stream */
462 1 result2 = gate_stream_seek(ctrl, start_pos, GATE_STREAM_SEEK_BEGIN, NULL);
463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(result);
464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(result2);
465
466 2 uncompressed_size = ((gate_uint32_t)(gate_uint8_t)tail[4])
467 1 | (((gate_uint32_t)(gate_uint8_t)tail[5]) << 8)
468 1 | (((gate_uint32_t)(gate_uint8_t)tail[6]) << 16)
469 1 | (((gate_uint32_t)(gate_uint8_t)tail[7]) << 24)
470 ;
471 1 *ptr_length = uncompressed_size;
472 1 ret = true;
473 } while (0);
474
475 2 return ret;
476
477 }
478
479 2 gate_result_t gate_zlib_decoder_create(gate_stream_t* input, gate_bool_t gzformat, gate_stream_t** ptr2streamptr)
480 {
481 gate_result_t ret;
482
483 do
484 {
485 gate_zlibdecoder_impl_t* impl;
486 int zresult;
487
488
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if ((input == NULL) || (ptr2streamptr == NULL))
489 {
490 ret = GATE_RESULT_NULLPOINTER;
491 break;
492 }
493 2 impl = (gate_zlibdecoder_impl_t*)gate_mem_alloc(sizeof(gate_zlibdecoder_impl_t));
494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (impl == NULL)
495 {
496 GATE_DEBUG_TRACE("failed to allocate zlibdecoder");
497 ret = GATE_RESULT_OUTOFMEMORY;
498 break;
499 }
500
501 2 gate_mem_clear(impl, sizeof(gate_zlibdecoder_impl_t));
502 2 gate_init_zlibdecoder_vtbl();
503 2 impl->vtbl = &gate_zlibdecoder_vtbl;
504 2 gate_atomic_int_init(&impl->ref_counter, 1);
505 2 impl->source_stream = input;
506
507 2 gate_zlib_decoder_get_content_length(input, &impl->total_bytes_uncompressed);
508
509 2 impl->unzipper.zalloc = &gate_zlibstream_alloc_func;
510 2 impl->unzipper.opaque = Z_NULL;
511 2 impl->unzipper.zfree = &gate_zlibstream_free_func;
512
513
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 zresult = inflateInit2(&impl->unzipper, (gzformat == true ? MAX_WBITS + 32 : MAX_WBITS));
514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (zresult != Z_OK)
515 {
516 GATE_DEBUG_TRACE_MSG_VALUE("inflateInit2() failed", zresult);
517 gate_mem_dealloc(impl);
518 ret = GATE_RESULT_FAILED;
519 break;
520 }
521
522 2 gate_object_retain(impl->source_stream);
523 2 *ptr2streamptr = (gate_stream_t*)impl;
524
525 2 ret = GATE_RESULT_OK;
526 } while (0);
527
528 2 return ret;
529 }
530
531
532 4 static char const* gate_zlibdecoder_interface_name_impl(void* self)
533 {
534 4 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
535
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if (gate_object_implements_interface((gate_object_t*)impl->source_stream, GATE_INTERFACE_NAME_CONTROLSTREAM))
536 {
537 4 return GATE_INTERFACE_NAME_CONTROLSTREAM;
538 }
539 return GATE_INTERFACE_NAME_STREAM;
540 }
541
542 6 static void gate_zlibdecoder_release_impl(void* self)
543 {
544 6 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
545
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (gate_atomic_int_dec(&impl->ref_counter) == 0)
546 {
547 2 inflateEnd(&impl->unzipper);
548 2 gate_object_release(impl->source_stream);
549 2 gate_mem_dealloc(impl);
550 }
551 6 }
552 4 static int gate_zlibdecoder_retain_impl(void* self)
553 {
554 4 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
555 4 return gate_atomic_int_inc(&impl->ref_counter);
556 }
557
558 22 static gate_result_t gate_zlibdecoder_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
559 {
560 22 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
561
562 22 gate_bool_t end_of_stream = false;
563
564
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
24 while ((impl->decoded_buffer_length == 0) && (!end_of_stream))
565 {
566 int zresult;
567 gate_size_t diff;
568
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (impl->unzipper.avail_in == 0)
569 {
570 gate_size_t bytecount;
571 4 gate_result_t result = gate_stream_read(impl->source_stream, impl->source_buffer, sizeof(impl->source_buffer), &bytecount);
572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (GATE_FAILED(result))
573 {
574 GATE_DEBUG_TRACE_MSG_VALUE("zlibdecoder_peek stream_read failed", result);
575 return result;
576 }
577
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (bytecount == 0)
578 {
579 2 break;
580 }
581 2 impl->unzipper.next_in = (Bytef*)&impl->source_buffer[0];
582 2 impl->unzipper.avail_in = (uInt)bytecount;
583 }
584
585
586 2 impl->unzipper.avail_out = sizeof(impl->decoded_buffer);
587 2 impl->unzipper.next_out = (Bytef*)(&impl->decoded_buffer[0]);
588
589 2 zresult = inflate(&impl->unzipper, Z_NO_FLUSH);
590
591
1/5
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2 switch (zresult)
592 {
593 case Z_STREAM_ERROR:
594 case Z_NEED_DICT:
595 case Z_DATA_ERROR:
596 case Z_MEM_ERROR:
597 {
598 GATE_DEBUG_TRACE_MSG_VALUE("inflate() failed", zresult);
599 return GATE_RESULT_FAILED;
600 }
601 2 case Z_STREAM_END:
602 {
603 2 end_of_stream = true;
604 2 break;
605 }
606 case Z_BUF_ERROR:
607 {
608 /* ignore */
609 GATE_DEBUG_BREAKPOINT;
610 break;
611 }
612 case Z_OK:
613 {
614 /* success -> continue */
615 break;
616 }
617 }
618
619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(sizeof(impl->decoded_buffer) >= impl->unzipper.avail_out);
620 2 diff = sizeof(impl->decoded_buffer) - impl->unzipper.avail_out;
621 2 impl->decoded_buffer_length = diff;
622 2 impl->decoded_buffer_offset = 0;
623 }
624
625
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
22 if (bufferlength < impl->decoded_buffer_length)
626 {
627 18 gate_mem_copy(buffer, &impl->decoded_buffer[impl->decoded_buffer_offset], bufferlength);
628
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (returned != NULL)
629 {
630 18 *returned = bufferlength;
631 }
632 }
633 else
634 {
635
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (impl->decoded_buffer_length > 0)
636 {
637 2 gate_mem_copy(buffer, &impl->decoded_buffer[impl->decoded_buffer_offset], impl->decoded_buffer_length);
638 }
639
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (returned != NULL)
640 {
641 4 *returned = impl->decoded_buffer_length;
642 }
643 }
644 22 return GATE_RESULT_OK;
645 }
646
647 22 static gate_result_t gate_zlibdecoder_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
648 {
649 22 gate_size_t tmp = 0;
650 22 gate_result_t ret = gate_zlibdecoder_peek_impl(self, buffer, bufferlength, &tmp);
651
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (returned != NULL)
652 {
653 22 *returned = tmp;
654 }
655
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (GATE_SUCCEEDED(ret))
656 {
657 22 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
658 22 impl->decoded_buffer_offset += tmp;
659 22 impl->decoded_buffer_length -= tmp;
660 22 impl->bytes_decoded_counter += tmp;
661 }
662 22 return ret;
663 }
664
665 2 static gate_result_t gate_zlibdecoder_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
666 {
667 GATE_UNUSED_ARG(self);
668 GATE_UNUSED_ARG(buffer);
669 GATE_UNUSED_ARG(bufferlength);
670 GATE_UNUSED_ARG(written);
671 2 return GATE_RESULT_NOTSUPPORTED;
672 }
673
674 2 static gate_result_t gate_zlibdecoder_flush_impl(void* self)
675 {
676 GATE_UNUSED_ARG(self);
677 2 return GATE_RESULT_NOTSUPPORTED;
678 }
679
680 static gate_result_t gate_zlibdecoder_get_resource_impl(void* self, gate_enumint_t resource_type, gate_uintptr_t* resource)
681 {
682 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
683
684 if (gate_object_implements_interface((gate_object_t*)impl->source_stream, GATE_INTERFACE_NAME_CONTROLSTREAM))
685 {
686 gate_controlstream_t* ctrl = (gate_controlstream_t*)impl->source_stream;
687 return gate_stream_get_resource(ctrl, resource_type, resource);
688 }
689 return GATE_RESULT_NOTSUPPORTED;
690 }
691
692 2 static gate_result_t gate_zlibdecoder_can_read_impl(void* self, gate_bool_t* return_value)
693 {
694 2 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
695
696
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (gate_object_implements_interface((gate_object_t*)impl->source_stream, GATE_INTERFACE_NAME_CONTROLSTREAM))
697 {
698 2 gate_controlstream_t* ctrl = (gate_controlstream_t*)impl->source_stream;
699 2 return gate_stream_can_read(ctrl, return_value);
700 }
701 return GATE_RESULT_NOTSUPPORTED;
702 }
703
704 2 static gate_result_t gate_zlibdecoder_can_write_impl(void* self, gate_bool_t* return_value)
705 {
706 GATE_UNUSED_ARG(self);
707
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (return_value)
708 {
709 2 *return_value = false;
710 }
711 2 return GATE_RESULT_OK;
712 }
713
714 2 static gate_result_t gate_zlibdecoder_get_size_impl(void* self, gate_int64_t* return_value)
715 {
716 2 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
717
718
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (gate_object_implements_interface((gate_object_t*)impl->source_stream, GATE_INTERFACE_NAME_CONTROLSTREAM))
719 {
720 2 gate_controlstream_t* ctrl = (gate_controlstream_t*)impl->source_stream;
721
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (return_value)
722 {
723 2 *return_value = (gate_int64_t)impl->total_bytes_uncompressed;
724 }
725 2 return GATE_RESULT_OK;
726 }
727 return GATE_RESULT_NOTSUPPORTED;
728 }
729
730 2 static gate_result_t gate_zlibdecoder_get_available_impl(void* self, gate_int64_t* return_value)
731 {
732 2 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
733
734
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (gate_object_implements_interface((gate_object_t*)impl->source_stream, GATE_INTERFACE_NAME_CONTROLSTREAM))
735 {
736 2 gate_controlstream_t* ctrl = (gate_controlstream_t*)impl->source_stream;
737
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (return_value)
738 {
739
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (impl->total_bytes_uncompressed >= impl->bytes_decoded_counter)
740 {
741 2 *return_value = (gate_int64_t)impl->total_bytes_uncompressed - impl->bytes_decoded_counter;
742 }
743 else
744 {
745 *return_value = 0;
746 }
747 }
748 2 return GATE_RESULT_OK;
749 }
750 return GATE_RESULT_NOTSUPPORTED;
751 }
752
753
754 2 static gate_result_t gate_zlibdecoder_seek_impl(void* self, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position)
755 {
756 2 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
757
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if ((origin == GATE_STREAM_SEEK_CURRENT) && (position == 0))
758 {
759 /* special case: return current position in decoded stream (no change at all) */
760
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (final_position)
761 {
762 2 *final_position = (gate_int64_t)impl->bytes_decoded_counter;
763 }
764 2 return GATE_RESULT_OK;
765 }
766 return GATE_RESULT_NOTSUPPORTED;
767 }
768
769
770 static gate_result_t gate_zlibdecoder_reset_impl(void* self)
771 {
772 GATE_UNUSED_ARG(self);
773 return GATE_RESULT_NOTSUPPORTED;
774 }
775
776
777 static gate_result_t gate_zlibdecoder_close_impl(void* self, gate_enumint_t close_type)
778 {
779 gate_zlibdecoder_impl_t* impl = (gate_zlibdecoder_impl_t*)self;
780
781 if (gate_object_implements_interface((gate_object_t*)impl->source_stream, GATE_INTERFACE_NAME_CONTROLSTREAM))
782 {
783 gate_controlstream_t* ctrl = (gate_controlstream_t*)impl->source_stream;
784 return gate_stream_close(ctrl, close_type);
785 }
786 return GATE_RESULT_NOTSUPPORTED;
787 }
788
789 #endif /* GATE_ENCODE_ZLIBSTREAM_USE_ZLIB */
790
791
792 #if defined(GATE_ENCODE_ZLIBSTREAM_NO_IMPL)
793
794 gate_result_t gate_zlib_encoder_create(gate_stream_t* output, gate_bool_t gzformat,
795 gate_int16_t compression, gate_stream_t** ptr2streamptr)
796 {
797 return GATE_RESULT_NOTIMPLEMENTED;
798 }
799
800 gate_result_t gate_zlib_decoder_create(gate_stream_t* input, gate_bool_t gzformat,
801 gate_stream_t** ptr2streamptr)
802 {
803 return GATE_RESULT_NOTIMPLEMENTED;
804 }
805
806 #endif /* GATE_ENCODE_ZLIBSTREAM_NO_IMPL */
807