GCC Code Coverage Report


Directory: src/gate/
File: src/gate/streams.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 985 1182 83.3%
Functions: 113 121 93.4%
Branches: 334 531 62.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, 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/streams.h"
30 #include "gate/results.h"
31 #include "gate/strings.h"
32 #include "gate/atomics.h"
33 #include "gate/debugging.h"
34 #include "gate/times.h"
35 #include "gate/arrays.h"
36 #include "gate/localbuffer.h"
37
38 #include <stdarg.h>
39
40 #if defined(GATE_SYS_WIN)
41 # define GATE_CORE_STREAMS_WINAPI 1
42 #elif defined(GATE_SYS_DOS)
43 # define GATE_CORE_STREAMS_POSIX 1
44 #elif defined(GATE_SYS_POSIX)
45 # define GATE_CORE_STREAMS_POSIX 1
46 #endif
47
48
49
50 /********************************
51 * memory stream implementation *
52 ********************************/
53
54 static void gate_memstream_release_impl(void* self);
55 static int gate_memstream_retain_impl(void* self);
56 static char const* gate_memstream_interface_name_impl(void* self);
57 static gate_result_t gate_memstream_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
58 static gate_result_t gate_memstream_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
59 static gate_result_t gate_memstream_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
60 static gate_result_t gate_memstream_flush_impl(void* self);
61 static gate_result_t gate_memstream_reserve_impl(void* self, gate_size_t space);
62 static gate_size_t gate_memstream_size_impl(void* self);
63 static gate_result_t gate_memstream_fill_impl(void* self, char fillitem, gate_size_t fillsize);
64 static gate_size_t gate_memstream_discard_impl(void* self, gate_size_t bytestodiscard);
65 static gate_size_t gate_memstream_discard_back_impl(void* self, gate_size_t bytestodiscard);
66 static char const* gate_memstream_get_data_impl(void* self);
67 static gate_result_t gate_memstream_reset_impl(void* self);
68
69
70 static void gate_memstream_release_static_impl(void* self);
71 static int gate_memstream_retain_static_impl(void* self);
72 static gate_result_t gate_memstream_write_static_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
73 static gate_result_t gate_memstream_reserve_static_impl(void* self, gate_size_t space);
74 static gate_result_t gate_memstream_fill_static_impl(void* self, char fillitem, gate_size_t fillsize);
75 static gate_result_t gate_memstream_write_disabled_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
76 static gate_result_t gate_memstream_reserve_disabled_impl(void* self, gate_size_t space);
77 static gate_result_t gate_memstream_fill_disabled_impl(void* self, char fillitem, gate_size_t fillsize);
78
79 static void gate_memstream_release_static_unmanaged_impl(void* self);
80
81 static GATE_INTERFACE_VTBL(gate_memstream) gate_memstream_static_unmanaged_readonly_vtbl;
82
83 10 static void gate_init_memstream_static_unmanaged_readonly_vtbl()
84 {
85
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 if (!gate_memstream_static_unmanaged_readonly_vtbl.get_interface_name)
86 {
87 GATE_INTERFACE_VTBL(gate_memstream) const local_vtbl =
88 {
89 &gate_memstream_interface_name_impl,
90 &gate_memstream_release_static_unmanaged_impl,
91 &gate_memstream_retain_static_impl,
92
93 &gate_memstream_read_impl,
94 &gate_memstream_peek_impl,
95 &gate_memstream_write_disabled_impl,
96 &gate_memstream_flush_impl,
97
98 &gate_memstream_get_data_impl,
99 &gate_memstream_size_impl,
100 &gate_memstream_reserve_disabled_impl,
101 &gate_memstream_fill_disabled_impl,
102 &gate_memstream_discard_impl,
103 &gate_memstream_discard_back_impl,
104 &gate_memstream_reset_impl
105 };
106 4 gate_memstream_static_unmanaged_readonly_vtbl = local_vtbl;
107 }
108 10 }
109
110
111
112 134 static void gate_memstream_release_impl(void* self)
113 {
114 134 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
115
2/2
✓ Branch 1 taken 122 times.
✓ Branch 2 taken 12 times.
134 if (gate_atomic_int_dec(&strm->ref_counter) == 0)
116 {
117 /* release memstream */
118
2/2
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 3 times.
122 if (strm->priv_membuffer != NULL)
119 {
120 119 gate_mem_dealloc(strm->priv_membuffer);
121 119 strm->priv_membuffer = NULL;
122 }
123 122 gate_mem_dealloc(strm);
124 }
125 134 }
126 12 static int gate_memstream_retain_impl(void* self)
127 {
128 12 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
129 12 return gate_atomic_int_inc(&strm->ref_counter);
130 }
131 8 static char const* gate_memstream_interface_name_impl(void* self)
132 {
133 (void)self;
134 8 return GATE_INTERFACE_NAME_MEMSTREAM;
135 }
136
137 122138 gate_result_t gate_memstream_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
138 {
139 122138 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
140
2/2
✓ Branch 0 taken 94 times.
✓ Branch 1 taken 122044 times.
122138 if (bufferlength > strm->priv_memlength)
141 {
142 94 bufferlength = strm->priv_memlength;
143 }
144
2/2
✓ Branch 0 taken 122085 times.
✓ Branch 1 taken 53 times.
122138 if (bufferlength != 0)
145 {
146 122085 gate_mem_copy(buffer, &strm->priv_membuffer[strm->priv_memoffset], bufferlength);
147 122085 strm->priv_memlength -= bufferlength;
148
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 121998 times.
122085 if (strm->priv_memlength == 0)
149 {
150 87 strm->priv_memoffset = 0;
151 }
152 else
153 {
154 121998 strm->priv_memoffset += bufferlength;
155 }
156 }
157
1/2
✓ Branch 0 taken 122138 times.
✗ Branch 1 not taken.
122138 if (returned != NULL)
158 {
159 122138 *returned = bufferlength;
160 }
161 122138 return GATE_RESULT_OK;
162 }
163 601 gate_result_t gate_memstream_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
164 {
165 601 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
166
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 600 times.
601 if (bufferlength > strm->priv_memlength)
167 {
168 1 bufferlength = strm->priv_memlength;
169 }
170
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 1 times.
601 if (bufferlength != 0)
171 {
172 600 gate_mem_copy(buffer, strm->priv_membuffer, bufferlength);
173 }
174
1/2
✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
601 if (returned != NULL)
175 {
176 601 *returned = bufferlength;
177 }
178 601 return GATE_RESULT_OK;
179 }
180 182422 gate_result_t gate_memstream_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
181 {
182 182422 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
183 182422 gate_result_t result = strm->vtbl->reserve(strm, bufferlength);
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182422 times.
182422 if (GATE_FAILED(result))
185 {
186 return result;
187 }
188
189 182422 gate_mem_copy(&strm->priv_membuffer[strm->priv_memoffset + strm->priv_memlength], buffer, bufferlength);
190 182422 strm->priv_memlength += bufferlength;
191
192
1/2
✓ Branch 0 taken 182422 times.
✗ Branch 1 not taken.
182422 if (written != NULL)
193 {
194 182422 *written = bufferlength;
195 }
196 182422 return GATE_RESULT_OK;
197 }
198 304 gate_result_t gate_memstream_flush_impl(void* self)
199 {
200 (void)self;
201 304 return GATE_RESULT_OK;
202 }
203 182457 static gate_result_t gate_memstream_reserve_impl(void* self, gate_size_t space)
204 {
205 182457 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
206 182457 gate_size_t unusedspace = strm->priv_memcapacity - strm->priv_memlength;
207 182457 gate_size_t freespace = unusedspace - strm->priv_memoffset;
208
2/2
✓ Branch 0 taken 684 times.
✓ Branch 1 taken 181773 times.
182457 if (space > freespace)
209 {
210
1/2
✓ Branch 0 taken 684 times.
✗ Branch 1 not taken.
684 if (space > unusedspace)
211 {
212 /* reallocation is required */
213 684 gate_size_t newcapacity = (strm->priv_memcapacity + space) + (strm->priv_memcapacity / 2);
214 684 char* newbuffer = (char*)gate_mem_alloc(newcapacity);
215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 684 times.
684 if (newbuffer == NULL)
216 {
217 return GATE_RESULT_OUTOFMEMORY;
218 }
219
2/2
✓ Branch 0 taken 563 times.
✓ Branch 1 taken 121 times.
684 if (strm->priv_memlength != 0)
220 {
221 563 gate_mem_copy(&newbuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
222 }
223
2/2
✓ Branch 0 taken 565 times.
✓ Branch 1 taken 119 times.
684 if (strm->priv_membuffer != NULL)
224 {
225 565 gate_mem_dealloc(strm->priv_membuffer);
226 }
227 684 strm->priv_membuffer = newbuffer;
228 684 strm->priv_memoffset = 0;
229 684 strm->priv_memcapacity = newcapacity;
230 }
231 else
232 {
233 /* moving bytes to origin of buffer */
234 gate_mem_copy(&strm->priv_membuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
235 strm->priv_memoffset = 0;
236 }
237 }
238 182457 return GATE_RESULT_OK;
239 }
240 37 static gate_size_t gate_memstream_size_impl(void* self)
241 {
242 37 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
243 37 return strm->priv_memlength;
244 }
245 1 static gate_result_t gate_memstream_fill_impl(void* self, char fillitem, gate_size_t fillsize)
246 {
247 1 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
248 gate_size_t ndx;
249 char* ptr;
250 1 gate_result_t result = strm->vtbl->reserve(strm, fillsize);
251
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
253 {
254 return result;
255 }
256
257 1 ptr = &strm->priv_membuffer[strm->priv_memoffset + strm->priv_memlength];
258
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 for (ndx = 0; ndx < fillsize; ++ndx, ++ptr)
259 {
260 5 *ptr = fillitem;
261 }
262 1 strm->priv_memlength += fillsize;
263 1 return GATE_RESULT_OK;
264 }
265 5 static gate_size_t gate_memstream_discard_impl(void* self, gate_size_t bytestodiscard)
266 {
267 5 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
268 gate_size_t ret;
269
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (bytestodiscard >= strm->priv_memlength)
270 {
271 1 ret = strm->priv_memlength;
272 1 strm->priv_memoffset = 0;
273 1 strm->priv_memlength = 0;
274 }
275 else
276 {
277 4 ret = bytestodiscard;
278 4 strm->priv_memoffset += bytestodiscard;
279 4 strm->priv_memlength -= bytestodiscard;
280 }
281 5 return ret;
282 }
283 3 static gate_size_t gate_memstream_discard_back_impl(void* self, gate_size_t bytestodiscard)
284 {
285 3 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
286 gate_size_t ret;
287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (bytestodiscard >= strm->priv_memlength)
288 {
289 ret = strm->priv_memlength;
290 strm->priv_memoffset = 0;
291 strm->priv_memlength = 0;
292 }
293 else
294 {
295 3 ret = bytestodiscard;
296 3 strm->priv_memlength -= bytestodiscard;
297 }
298 3 return ret;
299 }
300 32 static char const* gate_memstream_get_data_impl(void* self)
301 {
302 32 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
303 32 return &strm->priv_membuffer[strm->priv_memoffset];
304 }
305
306 static gate_result_t gate_memstream_reset_impl(void* self)
307 {
308 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
309 strm->priv_memoffset = 0;
310 strm->priv_memlength = 0;
311 return GATE_RESULT_OK;
312 }
313
314 static GATE_INTERFACE_VTBL(gate_memstream) gate_memstream_vtbl;
315
316 122 void gate_init_memstream_vtbl()
317 {
318
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 114 times.
122 if (!gate_memstream_vtbl.get_interface_name)
319 {
320 GATE_INTERFACE_VTBL(gate_memstream) const local_vtbl =
321 {
322 &gate_memstream_interface_name_impl,
323 &gate_memstream_release_impl,
324 &gate_memstream_retain_impl,
325
326 &gate_memstream_read_impl,
327 &gate_memstream_peek_impl,
328 &gate_memstream_write_impl,
329 &gate_memstream_flush_impl,
330
331 &gate_memstream_get_data_impl,
332 &gate_memstream_size_impl,
333 &gate_memstream_reserve_impl,
334 &gate_memstream_fill_impl,
335 &gate_memstream_discard_impl,
336 &gate_memstream_discard_back_impl,
337 &gate_memstream_reset_impl
338 };
339 8 gate_memstream_vtbl = local_vtbl;
340 }
341 122 }
342
343 122 gate_memstream_t* gate_memstream_create(gate_size_t capacity)
344 {
345 gate_result_t result;
346 122 gate_memstream_impl_t* ret = (gate_memstream_impl_t*)gate_mem_alloc(sizeof(gate_memstream_impl_t));
347
1/2
✓ Branch 0 taken 122 times.
✗ Branch 1 not taken.
122 if (ret != NULL)
348 {
349 122 gate_init_memstream_vtbl();
350 122 ret->vtbl = &gate_memstream_vtbl;
351 122 gate_atomic_int_set(&ret->ref_counter, 1);
352 122 ret->priv_membuffer = NULL;
353 122 ret->priv_memcapacity = 0;
354 122 ret->priv_memoffset = 0;
355 122 ret->priv_memlength = 0;
356
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 89 times.
122 if (capacity > 0)
357 {
358 33 result = ret->vtbl->reserve(ret, capacity);
359 (void)result;
360 }
361
362 }
363 122 return (gate_memstream_t*)ret;
364 }
365
366
367 5 static void gate_memstream_release_static_impl(void* self)
368 {
369 5 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
370
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
5 if (0 == gate_atomic_int_dec(&strm->ref_counter))
371 {
372 3 gate_mem_dealloc(self);
373 }
374 5 }
375 3 static int gate_memstream_retain_static_impl(void* self)
376 {
377 3 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
378 3 return (int)gate_atomic_int_inc(&strm->ref_counter);
379 }
380 236 static gate_result_t gate_memstream_write_static_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
381 {
382 236 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
383 236 gate_result_t ret = GATE_RESULT_OK;
384 gate_size_t avail;
385
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
236 if (bufferlength > 0)
386 {
387 236 avail = strm->priv_memcapacity - strm->priv_memlength;
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236 times.
236 if (bufferlength > avail)
389 {
390 if (bufferlength < strm->priv_memcapacity)
391 {
392 avail = strm->priv_memcapacity - bufferlength;
393 if (avail > strm->priv_memlength) avail = strm->priv_memlength;
394 gate_mem_copy(
395 &strm->priv_membuffer[0],
396 &strm->priv_membuffer[strm->priv_memoffset + strm->priv_memlength - avail],
397 avail);
398 strm->priv_memoffset = 0;
399 strm->priv_memlength = avail;
400 gate_mem_copy(&strm->priv_membuffer[strm->priv_memlength], buffer, bufferlength);
401 strm->priv_memlength += bufferlength;
402 }
403 else
404 {
405 gate_mem_copy(
406 &strm->priv_membuffer[0],
407 &buffer[bufferlength - strm->priv_memcapacity],
408 strm->priv_memcapacity);
409 strm->priv_memoffset = 0;
410 strm->priv_memlength = strm->priv_memcapacity;
411 }
412 }
413 else
414 {
415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 236 times.
236 if (strm->priv_memoffset != 0)
416 {
417 gate_mem_copy(&strm->priv_membuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
418 strm->priv_memoffset = 0;
419 }
420 236 gate_mem_copy(&strm->priv_membuffer[strm->priv_memlength], buffer, bufferlength);
421 236 strm->priv_memlength += bufferlength;
422 }
423 }
424
1/2
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
236 if (written != NULL) *written = bufferlength;
425 236 return ret;
426 }
427 1 static gate_result_t gate_memstream_write_disabled_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
428 {
429 (void)self;
430 (void)buffer;
431 (void)bufferlength;
432 (void)written;
433 1 return GATE_RESULT_NOTSUPPORTED;
434 }
435 1 static gate_result_t gate_memstream_reserve_disabled_impl(void* self, gate_size_t space)
436 {
437 (void)self;
438 (void)space;
439 1 return GATE_RESULT_NOTSUPPORTED;
440 }
441 1 static gate_result_t gate_memstream_fill_disabled_impl(void* self, char fillitem, gate_size_t fillsize)
442 {
443 (void)self;
444 (void)fillitem;
445 (void)fillsize;
446 1 return GATE_RESULT_NOTSUPPORTED;
447 }
448
449 static gate_result_t gate_memstream_reserve_static_impl(void* self, gate_size_t space)
450 {
451 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
452 if (strm->priv_memoffset != 0)
453 {
454 gate_mem_copy(&strm->priv_membuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
455 strm->priv_memoffset = 0;
456 }
457 return (space > strm->priv_memcapacity) ? GATE_RESULT_OUTOFMEMORY : GATE_RESULT_OK;
458 }
459 1 static gate_result_t gate_memstream_fill_static_impl(void* self, char fillitem, gate_size_t fillsize)
460 {
461 1 gate_result_t ret = GATE_RESULT_OK;
462
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (fillsize != 0)
463 {
464 1 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
465 gate_size_t avail;
466 gate_size_t index;
467 char* ptr;
468
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (strm->priv_memoffset != 0)
469 {
470 1 gate_mem_copy(&strm->priv_membuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
471 1 strm->priv_memoffset = 0;
472 }
473 1 avail = strm->priv_memcapacity - strm->priv_memlength;
474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (fillsize > avail)
475 {
476 if (fillsize >= strm->priv_memcapacity)
477 {
478 ptr = &strm->priv_membuffer[0];
479 fillsize = strm->priv_memcapacity;
480 strm->priv_memoffset = 0;
481 strm->priv_memlength = 0;
482 }
483 else
484 {
485 gate_size_t preserve = strm->priv_memcapacity - fillsize;
486 gate_mem_copy(&strm->priv_membuffer[0], &strm->priv_membuffer[strm->priv_memoffset + strm->priv_memlength - preserve], preserve);
487 strm->priv_memoffset = 0;
488 strm->priv_memlength = preserve;
489 ptr = &strm->priv_membuffer[preserve];
490 }
491 }
492 else
493 {
494 1 ptr = &strm->priv_membuffer[strm->priv_memoffset + strm->priv_memlength];
495 }
496
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (index = 0; index != fillsize; ++index)
497 {
498 1 *ptr = fillitem;
499 1 ++ptr;
500 }
501 1 strm->priv_memlength += fillsize;
502 }
503 1 return ret;
504 }
505
506
507 9 static void gate_memstream_release_static_unmanaged_impl(void* self)
508 {
509 9 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
510 9 if (0 == gate_atomic_int_dec(&strm->ref_counter))
511 {
512 /* do nothing */
513 }
514 9 }
515
516 static GATE_INTERFACE_VTBL(gate_memstream) gate_memstream_static_unmanaged_vtbl;
517
518 1 void gate_init_memstream_static_unmanaged_vtbl()
519 {
520
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!gate_memstream_static_unmanaged_vtbl.get_interface_name)
521 {
522 GATE_INTERFACE_VTBL(gate_memstream) const local_vtbl =
523 {
524 &gate_memstream_interface_name_impl,
525 &gate_memstream_release_static_unmanaged_impl,
526 &gate_memstream_retain_static_impl,
527
528 &gate_memstream_read_impl,
529 &gate_memstream_peek_impl,
530 &gate_memstream_write_static_impl,
531 &gate_memstream_flush_impl,
532
533 &gate_memstream_get_data_impl,
534 &gate_memstream_size_impl,
535 &gate_memstream_reserve_static_impl,
536 &gate_memstream_fill_static_impl,
537 &gate_memstream_discard_impl,
538 &gate_memstream_discard_back_impl,
539 &gate_memstream_reset_impl
540 };
541 1 gate_memstream_static_unmanaged_vtbl = local_vtbl;
542 }
543 1 }
544
545 1 gate_memstream_t* gate_memstream_create_static_unmanaged(gate_memstream_impl_t* impl, void* buffer, gate_size_t capacity, gate_size_t used)
546 {
547 1 gate_init_memstream_static_unmanaged_vtbl();
548 1 impl->vtbl = &gate_memstream_static_unmanaged_vtbl;
549 1 gate_atomic_int_init(&impl->ref_counter, 1);
550 1 impl->priv_memoffset = 0;
551 1 impl->priv_membuffer = (char*)buffer;
552 1 impl->priv_memcapacity = capacity;
553 1 impl->priv_memlength = used;
554 1 return (gate_memstream_t*)impl;
555 }
556
557 static GATE_INTERFACE_VTBL(gate_memstream) gate_memstream_static_vtbl;
558 3 void gate_init_memstream_static_vtbl()
559 {
560
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (!gate_memstream_static_vtbl.get_interface_name)
561 {
562 GATE_INTERFACE_VTBL(gate_memstream) const local_vtbl =
563 {
564 &gate_memstream_interface_name_impl,
565 &gate_memstream_release_static_impl,
566 &gate_memstream_retain_static_impl,
567
568 &gate_memstream_read_impl,
569 &gate_memstream_peek_impl,
570 &gate_memstream_write_static_impl,
571 &gate_memstream_flush_impl,
572
573 &gate_memstream_get_data_impl,
574 &gate_memstream_size_impl,
575 &gate_memstream_reserve_static_impl,
576 &gate_memstream_fill_static_impl,
577 &gate_memstream_discard_impl,
578 &gate_memstream_discard_back_impl,
579 &gate_memstream_reset_impl
580 };
581 1 gate_memstream_static_vtbl = local_vtbl;
582 }
583 3 }
584
585 3 gate_memstream_t* gate_memstream_create_static(void* buffer, gate_size_t capacity, gate_size_t used)
586 {
587 3 gate_memstream_impl_t* impl = (gate_memstream_impl_t*)gate_mem_alloc(sizeof(gate_memstream_impl_t));
588
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (impl != NULL)
589 {
590 3 gate_init_memstream_static_vtbl();
591 3 impl->vtbl = &gate_memstream_static_vtbl;
592 3 gate_atomic_int_init(&impl->ref_counter, 1);
593 3 impl->priv_memoffset = 0;
594 3 impl->priv_membuffer = (char*)buffer;
595 3 impl->priv_memcapacity = capacity;
596 3 impl->priv_memlength = used;
597 }
598 3 return (gate_memstream_t*)impl;
599 }
600
601 10 gate_memstream_t* gate_memstream_create_static_unmanaged_readonly(gate_memstream_impl_t* impl, void const* buffer, gate_size_t capacity, gate_size_t used)
602 {
603 10 gate_init_memstream_static_unmanaged_readonly_vtbl();
604 10 impl->vtbl = &gate_memstream_static_unmanaged_readonly_vtbl;
605 10 gate_atomic_int_init(&impl->ref_counter, 1);
606 10 impl->priv_memoffset = 0;
607 10 impl->priv_membuffer = (char*)buffer;
608 10 impl->priv_memcapacity = capacity;
609 10 impl->priv_memlength = used;
610 10 return (gate_memstream_t*)impl;
611 }
612
613
614
615 /*****************************************
616 * control-memstream-view implementation *
617 *****************************************/
618
619 typedef struct memview_class
620 {
621 GATE_INTERFACE_VTBL(gate_controlstream)* vtbl;
622
623 gate_atomic_int_t ref_counter;
624 char const* ptr_buffer;
625 gate_size_t buffer_len;
626 gate_size_t buffer_offset;
627 gate_bool_t closed; /* true, when stream is closed */
628 gate_object_t* ptr_container; /* container holding mem-allocation, released on close*/
629 } memview_t;
630
631 1 static void memview_destroy(memview_t* self)
632 {
633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (self->ptr_container)
634 {
635 gate_object_release(self->ptr_container);
636 }
637 1 gate_mem_dealloc(self);
638 1 }
639
640 static char const* memview_get_interface_name(void* obj)
641 {
642 GATE_UNUSED_ARG(obj);
643 return GATE_INTERFACE_NAME_CONTROLSTREAM;
644 }
645 1 static void memview_release(void* obj)
646 {
647 1 memview_t* const self = (memview_t*)obj;
648
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (0 == gate_atomic_int_dec(&self->ref_counter))
649 {
650 1 memview_destroy(self);
651 }
652 1 }
653 static int memview_retain(void* obj)
654 {
655 memview_t* const self = (memview_t*)obj;
656 return (int)gate_atomic_int_inc(&self->ref_counter);
657 }
658
659 4 static gate_result_t memview_peek(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
660 {
661 4 memview_t* const self = (memview_t*)obj;
662 4 gate_result_t result = GATE_RESULT_FAILED;
663 4 gate_size_t copied = 0;
664 gate_size_t available;
665
666 do
667 {
668
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (!buffer || !obj)
669 {
670 result = GATE_RESULT_NULLPOINTER;
671 break;
672 }
673
674 4 available = self->buffer_len - self->buffer_offset;
675
676
3/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
4 if (self->closed || (available == 0))
677 {
678 /* react as end of stream */
679 2 result = GATE_RESULT_OK;
680 2 break;
681 }
682
683 2 copied = (bufferlength > available) ? available : bufferlength;
684 2 gate_mem_copy(buffer, &self->ptr_buffer[self->buffer_offset], copied);
685 2 result = GATE_RESULT_OK;
686 } while (0);
687
688
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (returned)
689 {
690 4 *returned = copied;
691 }
692
693 4 return result;
694 }
695
696 4 static gate_result_t memview_read(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
697 {
698 4 memview_t* const self = (memview_t*)obj;
699 4 gate_result_t result = GATE_RESULT_FAILED;
700 4 gate_size_t copied = 0;
701
702 4 result = memview_peek(obj, buffer, bufferlength, &copied);
703
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(result))
704 {
705 4 self->buffer_offset += copied;
706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (self->buffer_offset > self->buffer_len)
707 {
708 self->buffer_offset = self->buffer_len;
709 }
710 }
711
712
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (returned)
713 {
714 4 *returned = copied;
715 }
716
717 4 return result;
718 }
719
720 static gate_result_t memview_write(void* obj, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
721 {
722 GATE_UNUSED_ARG(obj);
723 GATE_UNUSED_ARG(buffer);
724 GATE_UNUSED_ARG(bufferlength);
725 GATE_UNUSED_ARG(written);
726 return GATE_RESULT_NOTSUPPORTED;
727 }
728 static gate_result_t memview_flush(void* obj)
729 {
730 GATE_UNUSED_ARG(obj);
731 return GATE_RESULT_NOTSUPPORTED;
732 }
733
734 1 static gate_result_t memview_get_resource(void* obj, gate_enumint_t resource_type, gate_uintptr_t* resource)
735 {
736 1 memview_t* const self = (memview_t*)obj;
737
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 switch (resource_type)
738 {
739 1 case GATE_STREAM_RESOURCE_INPUT:
740 case GATE_STREAM_RESOURCE_DEFAULT:
741
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (resource)
742 {
743 1 *resource = (gate_uintptr_t)self->ptr_buffer;
744 }
745 1 return GATE_RESULT_OK;
746 default:
747 {
748 return GATE_RESULT_NOTAVAILABLE;
749 }
750 }
751 }
752
753 1 static gate_result_t memview_can_read(void* obj, gate_bool_t* return_value)
754 {
755 1 memview_t* const self = (memview_t*)obj;
756
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (return_value)
757 {
758 1 *return_value = !self->closed;
759 }
760 1 return GATE_RESULT_OK;
761 }
762 1 static gate_result_t memview_can_write(void* obj, gate_bool_t* return_value)
763 {
764 GATE_UNUSED_ARG(obj);
765
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (return_value)
766 {
767 1 *return_value = false;
768 }
769 1 return GATE_RESULT_OK;
770 }
771 1 static gate_result_t memview_get_size(void* obj, gate_int64_t* return_value)
772 {
773 1 memview_t* const self = (memview_t*)obj;
774
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (return_value)
775 {
776 1 *return_value = self->buffer_len;
777 }
778 1 return GATE_RESULT_OK;
779 }
780 1 static gate_result_t memview_get_available(void* obj, gate_int64_t* return_value)
781 {
782 1 memview_t* const self = (memview_t*)obj;
783
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (return_value)
784 {
785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 *return_value = self->closed ? 0 : (gate_int64_t)(self->buffer_len - self->buffer_offset);
786 }
787 1 return GATE_RESULT_OK;
788 }
789 3 static gate_result_t memview_seek(void* obj, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position)
790 {
791 3 memview_t* const self = (memview_t*)obj;
792 3 gate_result_t result = GATE_RESULT_FAILED;
793 gate_size_t shift;
794
795
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (self->closed)
796 {
797 return GATE_RESULT_NOTAVAILABLE;
798 }
799
800
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
3 switch (origin)
801 {
802 1 case GATE_STREAM_SEEK_BEGIN:
803 {
804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (position < 0)
805 {
806 result = GATE_RESULT_INVALIDARG;
807 break;
808 }
809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (position > (gate_int64_t)self->buffer_len)
810 {
811 result = GATE_RESULT_NOTSUPPORTED;
812 break;
813 }
814 1 self->buffer_offset = (gate_size_t)(gate_uint64_t)position;
815 1 result = GATE_RESULT_OK;
816 1 break;
817 }
818 1 case GATE_STREAM_SEEK_CURRENT:
819 {
820
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (position < 0)
821 {
822 shift = (gate_size_t)(gate_uint64_t)(-position);
823 if (shift > self->buffer_offset)
824 {
825 result = GATE_RESULT_NOTSUPPORTED;
826 break;
827 }
828 self->buffer_offset -= shift;
829 }
830 else
831 {
832 1 shift = (gate_size_t)(gate_uint64_t)position;
833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (self->buffer_offset + shift > self->buffer_len)
834 {
835 result = GATE_RESULT_NOTSUPPORTED;
836 break;
837 }
838 1 self->buffer_offset += shift;
839 }
840 1 result = GATE_RESULT_OK;
841 1 break;
842 }
843 1 case GATE_STREAM_SEEK_END:
844 {
845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (position > 0)
846 {
847 result = GATE_RESULT_NOTSUPPORTED;
848 break;
849 }
850 1 shift = (gate_size_t)(-position);
851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (shift > self->buffer_len)
852 {
853 result = GATE_RESULT_INVALIDARG;
854 break;
855 }
856 1 self->buffer_offset = self->buffer_len - shift;
857 1 result = GATE_RESULT_OK;
858 1 break;
859 }
860 default:
861 {
862 result = GATE_RESULT_INVALIDARG;
863 break;
864 }
865 }
866
867
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (final_position)
868 {
869 3 *final_position = (gate_int64_t)(gate_uint64_t)self->buffer_offset;
870 }
871 3 return result;
872 }
873 1 static gate_result_t memview_reset(void* obj)
874 {
875 1 memview_t* const self = (memview_t*)obj;
876 1 self->buffer_offset = 0;
877 1 return GATE_RESULT_OK;
878 }
879 2 static gate_result_t memview_close(void* obj, gate_enumint_t close_type)
880 {
881 2 memview_t* const self = (memview_t*)obj;
882
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 switch (close_type)
883 {
884 1 case GATE_STREAM_CLOSE_DEFAULT:
885 case GATE_STREAM_CLOSE_INPUT:
886 1 self->closed = true;
887 1 return GATE_RESULT_OK;
888 1 default:
889 1 return GATE_RESULT_NOTSUPPORTED;
890 }
891 }
892
893 static GATE_INTERFACE_VTBL(gate_controlstream) memview_vtbl;
894
895 1 static void init_memview_vtbl()
896 {
897
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (memview_vtbl.get_interface_name == NULL)
898 {
899 1 GATE_INTERFACE_VTBL(gate_controlstream) local_vtbl =
900 {
901 &memview_get_interface_name,
902 &memview_release,
903 &memview_retain,
904
905 &memview_read,
906 &memview_peek,
907 &memview_write,
908 &memview_flush,
909
910 &memview_get_resource,
911
912 &memview_can_read,
913 &memview_can_write,
914 &memview_get_size,
915 &memview_get_available,
916 &memview_seek,
917 &memview_reset,
918 &memview_close
919 };
920 1 memview_vtbl = local_vtbl;
921 }
922 1 }
923
924 1 gate_controlstream_t* gate_memstream_create_view(void const* buffer, gate_size_t length, gate_size_t offset, gate_object_t* ptr_container)
925 {
926 1 gate_controlstream_t* ret = NULL;
927 1 memview_t* newstrm = NULL;
928
929 do
930 {
931 1 newstrm = (memview_t*)gate_mem_alloc(sizeof(memview_t));
932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!newstrm)
933 {
934 break;
935 }
936 1 gate_mem_clear(newstrm, sizeof(memview_t));
937 1 init_memview_vtbl();
938 1 newstrm->vtbl = &memview_vtbl;
939 1 gate_atomic_int_init(&newstrm->ref_counter, 1);
940 1 newstrm->closed = false;
941 1 newstrm->ptr_buffer = (char const*)buffer;
942 1 newstrm->buffer_len = length;
943 1 newstrm->buffer_offset = (offset > length) ? length : offset;
944 1 newstrm->ptr_container = ptr_container;
945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (newstrm->ptr_container)
946 {
947 gate_object_retain(newstrm->ptr_container);
948 }
949 /* success case */
950 1 ret = (gate_controlstream_t*)newstrm;
951 1 newstrm = NULL;
952 } while (0);
953
954
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (newstrm)
955 {
956 memview_destroy(newstrm);
957 }
958 1 return ret;
959 }
960
961
962
963 /*****************************************
964 * control-memstream-file implementation *
965 *****************************************/
966
967 typedef struct memfile_class
968 {
969 GATE_INTERFACE_VTBL(gate_controlstream)* vtbl;
970
971 gate_atomic_int_t ref_counter;
972 gate_arraylist_t storage;
973 gate_size_t storage_offset; /* current read/write position */
974 gate_bool_t closed; /* true, when stream is closed */
975 } memfile_t;
976
977 12 static void memfile_destroy(memfile_t* self)
978 {
979 12 gate_arraylist_release(self->storage);
980 12 gate_mem_dealloc(self);
981 12 }
982
983 23 static char const* memfile_get_interface_name(void* obj)
984 {
985 GATE_UNUSED_ARG(obj);
986 23 return GATE_INTERFACE_NAME_MEMFILE;
987 }
988 25 static void memfile_release(void* obj)
989 {
990 25 memfile_t* const self = (memfile_t*)obj;
991
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 13 times.
25 if (0 == gate_atomic_int_dec(&self->ref_counter))
992 {
993 12 memfile_destroy(self);
994 }
995 25 }
996 13 static int memfile_retain(void* obj)
997 {
998 13 memfile_t* const self = (memfile_t*)obj;
999 13 return (int)gate_atomic_int_inc(&self->ref_counter);
1000 }
1001
1002 621 static gate_result_t memfile_peek(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1003 {
1004 621 memfile_t* const self = (memfile_t*)obj;
1005 621 gate_result_t result = GATE_RESULT_FAILED;
1006 621 gate_size_t copied = 0;
1007 gate_size_t available;
1008 gate_size_t storage_length;
1009 621 char const* ptr_storage_data = NULL;
1010
1011 do
1012 {
1013
2/4
✓ Branch 0 taken 621 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 621 times.
621 if (!buffer || !obj)
1014 {
1015 result = GATE_RESULT_NULLPOINTER;
1016 break;
1017 }
1018
1019 621 storage_length = gate_arraylist_length(self->storage);
1020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 621 times.
621 GATE_DEBUG_ASSERT(self->storage_offset <= storage_length);
1021 621 available = storage_length - self->storage_offset;
1022
1023
3/4
✓ Branch 0 taken 621 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 615 times.
621 if (self->closed || (available == 0))
1024 {
1025 /* react as end of stream */
1026 6 result = GATE_RESULT_OK;
1027 6 break;
1028 }
1029
1030 615 ptr_storage_data = (char const*)gate_arraylist_get(self->storage, self->storage_offset);
1031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 615 times.
615 if (!ptr_storage_data)
1032 {
1033 result = GATE_RESULT_NOTAVAILABLE;
1034 break;
1035 }
1036 615 copied = (bufferlength > available) ? available : bufferlength;
1037 615 gate_mem_copy(buffer, ptr_storage_data, copied);
1038 615 result = GATE_RESULT_OK;
1039 } while (0);
1040
1041
2/2
✓ Branch 0 taken 619 times.
✓ Branch 1 taken 2 times.
621 if (returned)
1042 {
1043 619 *returned = copied;
1044 }
1045
1046 621 return result;
1047 }
1048
1049 418 static gate_result_t memfile_read(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1050 {
1051 418 memfile_t* const self = (memfile_t*)obj;
1052 418 gate_result_t result = GATE_RESULT_FAILED;
1053 418 gate_size_t copied = 0;
1054
1055 418 result = memfile_peek(obj, buffer, bufferlength, &copied);
1056
1/2
✓ Branch 0 taken 418 times.
✗ Branch 1 not taken.
418 if (GATE_SUCCEEDED(result))
1057 {
1058 418 self->storage_offset += copied;
1059 }
1060
1061
1/2
✓ Branch 0 taken 418 times.
✗ Branch 1 not taken.
418 if (returned)
1062 {
1063 418 *returned = copied;
1064 }
1065
1066 418 return result;
1067 }
1068
1069 166 static gate_result_t memfile_write(void* obj, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1070 {
1071 166 memfile_t* const self = (memfile_t*)obj;
1072 166 gate_result_t ret = GATE_RESULT_FAILED;
1073 166 gate_size_t stored_bytes = 0;
1074 gate_size_t storage_length;
1075 gate_size_t available;
1076 char* ptr_storage_data;
1077
1078 do
1079 {
1080 166 storage_length = gate_arraylist_length(self->storage);
1081
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 166 times.
166 GATE_DEBUG_ASSERT(self->storage_offset <= storage_length);
1082 166 available = storage_length - self->storage_offset;
1083
1084
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 160 times.
166 if (available > 0)
1085 {
1086 6 ptr_storage_data = (char*)gate_arraylist_get(self->storage, self->storage_offset);
1087
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (!ptr_storage_data)
1088 {
1089 ret = GATE_RESULT_NOTAVAILABLE;
1090 break;
1091 }
1092 6 stored_bytes = (bufferlength <= available) ? bufferlength : available;
1093 6 gate_mem_copy(ptr_storage_data, buffer, stored_bytes);
1094 6 self->storage_offset += stored_bytes;
1095 6 bufferlength -= stored_bytes;
1096 6 buffer += stored_bytes;
1097 }
1098
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 6 times.
166 if (bufferlength > 0)
1099 {
1100
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 160 times.
160 if (NULL == gate_arraylist_insert(self->storage, storage_length, buffer, bufferlength))
1101 {
1102 ret = (stored_bytes > 0) ? GATE_RESULT_OK : GATE_RESULT_OUTOFMEMORY;
1103 break;
1104 }
1105 160 self->storage_offset += bufferlength;
1106 160 stored_bytes += bufferlength;
1107 }
1108 166 ret = GATE_RESULT_OK;
1109 } while (0);
1110
1111
1/2
✓ Branch 0 taken 166 times.
✗ Branch 1 not taken.
166 if (written)
1112 {
1113 166 *written = stored_bytes;
1114 }
1115 166 return ret;
1116 }
1117 107 static gate_result_t memfile_flush(void* obj)
1118 {
1119 GATE_UNUSED_ARG(obj);
1120 107 return GATE_RESULT_OK;
1121 }
1122
1123 1 static gate_result_t memfile_get_resource(void* obj, gate_enumint_t resource_type, gate_uintptr_t* resource)
1124 {
1125 1 memfile_t* const self = (memfile_t*)obj;
1126
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 switch (resource_type)
1127 {
1128 1 case GATE_STREAM_RESOURCE_INPUT:
1129 case GATE_STREAM_RESOURCE_OUTPUT:
1130 case GATE_STREAM_RESOURCE_DEFAULT:
1131
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (resource)
1132 {
1133 1 *resource = (gate_uintptr_t)gate_arraylist_get(self->storage, 0);
1134 }
1135 1 return GATE_RESULT_OK;
1136 default:
1137 {
1138 return GATE_RESULT_NOTAVAILABLE;
1139 }
1140 }
1141 }
1142 3 static gate_result_t memfile_can_read(void* obj, gate_bool_t* return_value)
1143 {
1144 3 memfile_t* const self = (memfile_t*)obj;
1145
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (return_value)
1146 {
1147 3 *return_value = !self->closed;
1148 }
1149 3 return GATE_RESULT_OK;
1150 }
1151 1 static gate_result_t memfile_can_write(void* obj, gate_bool_t* return_value)
1152 {
1153 1 memfile_t* const self = (memfile_t*)obj;
1154
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (return_value)
1155 {
1156 1 *return_value = !self->closed;
1157 }
1158 1 return GATE_RESULT_OK;
1159 }
1160 1 static gate_result_t memfile_get_size(void* obj, gate_int64_t* return_value)
1161 {
1162 1 memfile_t* const self = (memfile_t*)obj;
1163
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (return_value)
1164 {
1165 1 *return_value = (gate_int64_t)gate_arraylist_length(self->storage);
1166 }
1167 1 return GATE_RESULT_OK;
1168 }
1169 2 static gate_result_t memfile_get_available(void* obj, gate_int64_t* return_value)
1170 {
1171 2 memfile_t* const self = (memfile_t*)obj;
1172
1173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (self->closed)
1174 {
1175 return GATE_RESULT_INVALIDSTATE;
1176 }
1177
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 else if (return_value)
1178 {
1179 2 gate_size_t storage_length = gate_arraylist_length(self->storage);
1180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(self->storage_offset <= storage_length);
1181 2 *return_value = (gate_int64_t)(storage_length - self->storage_offset);
1182 }
1183 2 return GATE_RESULT_OK;
1184 }
1185 63 static gate_result_t memfile_seek(void* obj, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position)
1186 {
1187 63 memfile_t* const self = (memfile_t*)obj;
1188 63 gate_result_t result = GATE_RESULT_FAILED;
1189 gate_size_t shift;
1190 gate_size_t storage_length;
1191
1192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (self->closed)
1193 {
1194 return GATE_RESULT_NOTAVAILABLE;
1195 }
1196
1197 63 storage_length = gate_arraylist_length(self->storage);
1198
1199
3/4
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
63 switch (origin)
1200 {
1201 44 case GATE_STREAM_SEEK_BEGIN:
1202 {
1203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (position < 0)
1204 {
1205 result = GATE_RESULT_INVALIDARG;
1206 break;
1207 }
1208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (position > (gate_int64_t)storage_length)
1209 {
1210 result = GATE_RESULT_NOTSUPPORTED;
1211 break;
1212 }
1213 44 self->storage_offset = (gate_size_t)(gate_uint64_t)position;
1214 44 result = GATE_RESULT_OK;
1215 44 break;
1216 }
1217 13 case GATE_STREAM_SEEK_CURRENT:
1218 {
1219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (position < 0)
1220 {
1221 shift = (gate_size_t)(gate_uint64_t)(-position);
1222 if (shift > self->storage_offset)
1223 {
1224 result = GATE_RESULT_NOTSUPPORTED;
1225 break;
1226 }
1227 self->storage_offset -= shift;
1228 }
1229 else
1230 {
1231 13 shift = (gate_size_t)(gate_uint64_t)position;
1232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (self->storage_offset + shift > storage_length)
1233 {
1234 result = GATE_RESULT_NOTSUPPORTED;
1235 break;
1236 }
1237 13 self->storage_offset += shift;
1238 }
1239 13 result = GATE_RESULT_OK;
1240 13 break;
1241 }
1242 6 case GATE_STREAM_SEEK_END:
1243 {
1244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (position > 0)
1245 {
1246 result = GATE_RESULT_NOTSUPPORTED;
1247 break;
1248 }
1249 6 shift = (gate_size_t)(-position);
1250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (shift > storage_length)
1251 {
1252 result = GATE_RESULT_INVALIDARG;
1253 break;
1254 }
1255 6 self->storage_offset = storage_length - shift;
1256 6 result = GATE_RESULT_OK;
1257 6 break;
1258 }
1259 default:
1260 {
1261 result = GATE_RESULT_INVALIDARG;
1262 break;
1263 }
1264 }
1265
1266
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 4 times.
63 if (final_position)
1267 {
1268 59 *final_position = (gate_int64_t)(gate_uint64_t)self->storage_offset;
1269 }
1270 63 return result;
1271 }
1272 1 static gate_result_t memfile_reset(void* obj)
1273 {
1274 1 memfile_t* const self = (memfile_t*)obj;
1275 1 self->storage_offset = 0;
1276 1 return GATE_RESULT_OK;
1277 }
1278 4 static gate_result_t memfile_close(void* obj, gate_enumint_t close_type)
1279 {
1280 4 memfile_t* const self = (memfile_t*)obj;
1281
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 switch (close_type)
1282 {
1283 4 case GATE_STREAM_CLOSE_DEFAULT:
1284 case GATE_STREAM_CLOSE_INPUT:
1285 case GATE_STREAM_CLOSE_OUTPUT:
1286 4 self->closed = true;
1287 4 return GATE_RESULT_OK;
1288 default:
1289 return GATE_RESULT_NOTSUPPORTED;
1290 }
1291 }
1292
1293 static GATE_INTERFACE_VTBL(gate_controlstream) memfile_vtbl;
1294
1295 12 static void init_memfile_vtbl()
1296 {
1297
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if (memfile_vtbl.get_interface_name == NULL)
1298 {
1299 3 GATE_INTERFACE_VTBL(gate_controlstream) local_vtbl =
1300 {
1301 &memfile_get_interface_name,
1302 &memfile_release,
1303 &memfile_retain,
1304
1305 &memfile_read,
1306 &memfile_peek,
1307 &memfile_write,
1308 &memfile_flush,
1309
1310 &memfile_get_resource,
1311
1312 &memfile_can_read,
1313 &memfile_can_write,
1314 &memfile_get_size,
1315 &memfile_get_available,
1316 &memfile_seek,
1317 &memfile_reset,
1318 &memfile_close
1319 };
1320 3 memfile_vtbl = local_vtbl;
1321 }
1322 12 }
1323
1324 8 gate_controlstream_t* gate_memfilestream_create(gate_size_t prealloc)
1325 {
1326 8 gate_controlstream_t* ret = NULL;
1327 8 memfile_t* newstrm = NULL;
1328
1329 do
1330 {
1331 8 newstrm = (memfile_t*)gate_mem_alloc(sizeof(memfile_t));
1332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!newstrm)
1333 {
1334 break;
1335 }
1336 8 gate_mem_clear(newstrm, sizeof(memfile_t));
1337 8 init_memfile_vtbl();
1338 8 newstrm->vtbl = &memfile_vtbl;
1339 8 gate_atomic_int_init(&newstrm->ref_counter, 1);
1340 8 newstrm->storage = gate_arraylist_create(sizeof(char), NULL, prealloc, NULL, NULL);
1341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (!newstrm->storage)
1342 {
1343 break;
1344 }
1345 8 newstrm->closed = false;
1346 8 newstrm->storage_offset = 0;
1347
1348 /* success case */
1349 8 ret = (gate_controlstream_t*)newstrm;
1350 8 newstrm = NULL;
1351 } while (0);
1352
1353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (newstrm)
1354 {
1355 memfile_destroy(newstrm);
1356 }
1357 8 return ret;
1358 }
1359
1360 4 gate_controlstream_t* gate_memfilestream_share(gate_controlstream_t* ptr_memfile)
1361 {
1362 4 gate_controlstream_t* ret = NULL;
1363 4 memfile_t* other_memfile = NULL;
1364 4 memfile_t* newstrm = NULL;
1365
1366 do
1367 {
1368
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (!gate_object_implements_interface((gate_object_t*)ptr_memfile, GATE_INTERFACE_NAME_MEMFILE))
1369 {
1370 /* given stream is not a mem-file */
1371 break;
1372 }
1373 4 other_memfile = (memfile_t*)ptr_memfile;
1374
1375 4 newstrm = (memfile_t*)gate_mem_alloc(sizeof(memfile_t));
1376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!newstrm)
1377 {
1378 break;
1379 }
1380 4 gate_mem_clear(newstrm, sizeof(memfile_t));
1381 4 init_memfile_vtbl();
1382 4 newstrm->vtbl = &memfile_vtbl;
1383 4 gate_atomic_int_init(&newstrm->ref_counter, 1);
1384 4 newstrm->storage = other_memfile->storage;
1385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!newstrm->storage)
1386 {
1387 break;
1388 }
1389 4 gate_arraylist_retain(newstrm->storage);
1390 4 newstrm->closed = false;
1391 4 newstrm->storage_offset = 0;
1392
1393 /* success case */
1394 4 ret = (gate_controlstream_t*)newstrm;
1395 4 newstrm = NULL;
1396 } while (0);
1397
1398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (newstrm)
1399 {
1400 memfile_destroy(newstrm);
1401 }
1402 4 return ret;
1403 }
1404
1405
1406
1407 /********************************
1408 * string stream implementation *
1409 ********************************/
1410
1411 static void gate_stringstream_release_impl(void* thisptr);
1412 static int gate_stringstream_retain_impl(void* thisptr);
1413 static char const* gate_stringstream_get_interface_name_impl(void* thisptr);
1414 static gate_result_t gate_stringstream_read_impl(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
1415 static gate_result_t gate_stringstream_peek_impl(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
1416 static gate_result_t gate_stringstream_write_impl(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
1417 static gate_result_t gate_stringstream_flush_impl(void* thisptr);
1418
1419 static char const* gate_stringstream_get_data_impl(void* thisptr);
1420 static gate_size_t gate_stringstream_size_impl(void* thisptr);
1421
1422 static gate_result_t gate_stringstream_get_current_view_impl(void*, gate_string_t* ptr_output);
1423 static gate_result_t gate_stringstream_to_string_impl(void*, gate_string_t* ptr_output);
1424
1425
1426 static GATE_INTERFACE_VTBL(gate_stringstream) gate_stringstream_vtbl;
1427 147 static void gate_init_stringstream_vtbl()
1428 {
1429
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 138 times.
147 if (!gate_stringstream_vtbl.get_interface_name)
1430 {
1431 9 GATE_INTERFACE_VTBL(gate_stringstream) local_vtbl =
1432 {
1433 &gate_stringstream_get_interface_name_impl,
1434 &gate_stringstream_release_impl,
1435 &gate_stringstream_retain_impl,
1436
1437 &gate_stringstream_read_impl,
1438 &gate_stringstream_peek_impl,
1439 &gate_stringstream_write_impl,
1440 &gate_stringstream_flush_impl,
1441
1442 &gate_stringstream_get_data_impl,
1443 &gate_stringstream_size_impl,
1444 &gate_stringstream_get_current_view_impl,
1445 &gate_stringstream_to_string_impl
1446 };
1447 9 gate_stringstream_vtbl = local_vtbl;
1448 }
1449 147 }
1450
1451 typedef struct gate_stringstream_impl
1452 {
1453 GATE_INTERFACE_VTBL(gate_stringstream)* vtbl;
1454
1455 gate_atomic_int_t ref_counter;
1456 gate_strbuilder_t* ptr_builder;
1457 gate_strbuilder_t str_builder;
1458 } gate_stringstream_impl_t;
1459
1460
1461 146 gate_stringstream_t* gate_stringstream_create(gate_size_t capacity)
1462 {
1463 146 gate_stringstream_impl_t* ret = gate_mem_alloc(sizeof(gate_stringstream_impl_t));
1464
1/2
✓ Branch 0 taken 146 times.
✗ Branch 1 not taken.
146 if (ret != NULL)
1465 {
1466 146 gate_mem_clear(ret, sizeof(gate_stringstream_impl_t));
1467 146 gate_init_stringstream_vtbl();
1468 146 ret->vtbl = &gate_stringstream_vtbl;
1469 146 gate_atomic_int_init(&ret->ref_counter, 1);
1470 146 gate_strbuilder_create(&ret->str_builder, capacity);
1471 146 ret->ptr_builder = &ret->str_builder;
1472 }
1473 146 return (gate_stringstream_t*)ret;
1474 }
1475
1476 1 gate_stringstream_t* gate_stringstream_create_builder(gate_strbuilder_t* external_strbuilder)
1477 {
1478 1 gate_stringstream_impl_t* ret = gate_mem_alloc(sizeof(gate_stringstream_impl_t));
1479
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ret != NULL)
1480 {
1481 1 gate_mem_clear(ret, sizeof(gate_stringstream_impl_t));
1482 1 gate_init_stringstream_vtbl();
1483 1 ret->vtbl = &gate_stringstream_vtbl;
1484 1 gate_atomic_int_init(&ret->ref_counter, 1);
1485 1 ret->ptr_builder = external_strbuilder;
1486 }
1487 1 return (gate_stringstream_t*)ret;
1488 }
1489
1490
1491 148 static void gate_stringstream_release_impl(void* ptr)
1492 {
1493 148 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1494
2/2
✓ Branch 1 taken 147 times.
✓ Branch 2 taken 1 times.
148 if (gate_atomic_int_dec(&thisptr->ref_counter) == 0)
1495 {
1496
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 1 times.
147 if (&thisptr->str_builder == thisptr->ptr_builder)
1497 {
1498 146 gate_strbuilder_release(thisptr->ptr_builder);
1499 }
1500 147 gate_mem_dealloc(thisptr);
1501 }
1502 148 }
1503 1 static int gate_stringstream_retain_impl(void* ptr)
1504 {
1505 1 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1506 1 return (int)gate_atomic_int_inc(&thisptr->ref_counter);
1507 }
1508 2 static char const* gate_stringstream_get_interface_name_impl(void* ptr)
1509 {
1510 (void)ptr;
1511 2 return GATE_INTERFACE_NAME_STRINGSTREAM;
1512 }
1513 490 static gate_result_t gate_stringstream_read_impl(void* ptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1514 {
1515 490 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1516 490 gate_size_t bytesread = 0;
1517 490 gate_result_t result = gate_stringstream_peek_impl(ptr, buffer, bufferlength, &bytesread);
1518
1519
1/2
✓ Branch 0 taken 490 times.
✗ Branch 1 not taken.
490 if (GATE_SUCCEEDED(result))
1520 {
1521 490 gate_strbuilder_discard(thisptr->ptr_builder, bytesread);
1522
1/2
✓ Branch 0 taken 490 times.
✗ Branch 1 not taken.
490 if (returned != NULL)
1523 {
1524 490 *returned = bytesread;
1525 }
1526 }
1527 490 return result;
1528 }
1529 741 static gate_result_t gate_stringstream_peek_impl(void* ptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1530 {
1531 741 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1532 741 char const* dataptr = gate_strbuilder_ptr(thisptr->ptr_builder, 0);
1533 741 gate_size_t datalen = gate_strbuilder_length(thisptr->ptr_builder);
1534
2/4
✓ Branch 0 taken 741 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 741 times.
741 if ((bufferlength > 0) && (buffer == NULL))
1535 {
1536 return GATE_RESULT_INVALIDARG;
1537 }
1538
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 631 times.
741 if (bufferlength > datalen)
1539 {
1540 110 bufferlength = datalen;
1541 }
1542
2/2
✓ Branch 0 taken 677 times.
✓ Branch 1 taken 64 times.
741 if (bufferlength > 0)
1543 {
1544
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 677 times.
677 if (NULL == gate_mem_copy(buffer, dataptr, bufferlength))
1545 {
1546 return GATE_RESULT_FAILED;
1547 }
1548 }
1549
1/2
✓ Branch 0 taken 741 times.
✗ Branch 1 not taken.
741 if (returned != NULL)
1550 {
1551 741 *returned = bufferlength;
1552 }
1553 741 return GATE_RESULT_OK;
1554 }
1555 695 static gate_result_t gate_stringstream_write_impl(void* ptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1556 {
1557 695 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1558 gate_size_t lenwritten;
1559 gate_result_t ret;
1560 695 lenwritten = gate_strbuilder_append_text(thisptr->ptr_builder, buffer, bufferlength);
1561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 695 times.
695 ret = (lenwritten == 0) ? GATE_RESULT_FAILED : GATE_RESULT_OK;
1562
1563
1/2
✓ Branch 0 taken 695 times.
✗ Branch 1 not taken.
695 if (written != NULL)
1564 {
1565 695 *written = lenwritten;
1566 }
1567 695 return ret;
1568 }
1569 104 static gate_result_t gate_stringstream_flush_impl(void* ptr)
1570 {
1571 (void)ptr;
1572 104 return GATE_RESULT_OK;
1573 }
1574
1575 3 static char const* gate_stringstream_get_data_impl(void* ptr)
1576 {
1577 3 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1578 3 return gate_strbuilder_ptr(thisptr->ptr_builder, 0);
1579 }
1580 3 static gate_size_t gate_stringstream_size_impl(void* ptr)
1581 {
1582 3 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1583 3 return gate_strbuilder_length(thisptr->ptr_builder);
1584 }
1585 27 static gate_result_t gate_stringstream_get_current_view_impl(void* ptr, gate_string_t* ptr_output)
1586 {
1587 27 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1588
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 if (NULL != gate_string_create_static_len(ptr_output,
1589 27 gate_strbuilder_ptr(thisptr->ptr_builder, 0), gate_strbuilder_length(thisptr->ptr_builder)))
1590 {
1591 27 return GATE_RESULT_OK;
1592 }
1593 else
1594 {
1595 return GATE_RESULT_OUTOFMEMORY;
1596 }
1597 }
1598 62 static gate_result_t gate_stringstream_to_string_impl(void* ptr, gate_string_t* ptr_output)
1599 {
1600 62 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1601
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 62 times.
62 if (NULL == gate_strbuilder_to_string(thisptr->ptr_builder, ptr_output))
1602 {
1603 return GATE_RESULT_FAILED;
1604 }
1605 else
1606 {
1607 62 return GATE_RESULT_OK;
1608 }
1609 }
1610
1611
1612
1613 /********************************
1614 * null stream implementation *
1615 ********************************/
1616
1617 25 static void gate_nullstream_release_impl(void* self)
1618 {
1619 (void)self;
1620 25 }
1621 12 static int gate_nullstream_retain_impl(void* self)
1622 {
1623 (void)self;
1624 12 return 1;
1625 }
1626 1 static char const* gate_nullstream_get_interface_name_impl(void* self)
1627 {
1628 (void)self;
1629 1 return GATE_INTERFACE_NAME_STREAM;
1630 }
1631 1 static gate_result_t gate_nullstream_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1632 {
1633 (void)self;
1634 (void)buffer;
1635 (void)bufferlength;
1636
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (returned != NULL)
1637 {
1638 1 *returned = 0;
1639 }
1640 1 return GATE_RESULT_OK;
1641 }
1642 1 static gate_result_t gate_nullstream_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1643 {
1644 (void)self;
1645 (void)buffer;
1646 (void)bufferlength;
1647
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (returned != NULL)
1648 {
1649 1 *returned = 0;
1650 }
1651 1 return GATE_RESULT_OK;
1652 }
1653 1 static gate_result_t gate_nullstream_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1654 {
1655 (void)self;
1656 (void)buffer;
1657
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (written != NULL)
1658 {
1659 1 *written = bufferlength;
1660 }
1661 1 return GATE_RESULT_OK;
1662 }
1663 1 static gate_result_t gate_nullstream_flush_impl(void* self)
1664 {
1665 (void)self;
1666 1 return GATE_RESULT_OK;
1667 }
1668
1669 static GATE_INTERFACE_VTBL(gate_stream) gate_nullstream_vtbl;
1670 static gate_stream_t global_null_stream =
1671 {
1672 &gate_nullstream_vtbl
1673 };
1674 13 static void gate_nullstream_vtbl_init()
1675 {
1676
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
13 if (!gate_nullstream_vtbl.get_interface_name)
1677 {
1678
1679 3 GATE_INTERFACE_VTBL(gate_stream) local_vtbl =
1680 {
1681 &gate_nullstream_get_interface_name_impl,
1682 &gate_nullstream_release_impl,
1683 &gate_nullstream_retain_impl,
1684 &gate_nullstream_read_impl,
1685 &gate_nullstream_peek_impl,
1686 &gate_nullstream_write_impl,
1687 &gate_nullstream_flush_impl
1688 };
1689 3 gate_nullstream_vtbl = local_vtbl;
1690 }
1691 13 }
1692
1693 #define GATE_INTERFACE_VTBL_INIT(ifname, vtbl_instance, vtbl_block) \
1694 if(! ( vtbl_instance . get_interface_name ) ) { \
1695 GATE_INTERFACE_VTBL(gate_stream) local_vtbl = { GATE_STRIP_PARENTHESES vtbl_block }; \
1696 vtbl_instance = local_vtbl; \
1697 }
1698
1699
1700 13 gate_stream_t* gate_nullstream()
1701 {
1702 13 gate_nullstream_vtbl_init();
1703
1704 13 return &global_null_stream;
1705 }
1706
1707
1708
1709 10412 gate_result_t gate_stream_read_block(gate_stream_t* stream, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1710 {
1711 10412 gate_result_t result = GATE_RESULT_OK;
1712 10412 gate_size_t totalread = 0;
1713 gate_size_t blockread;
1714
2/2
✓ Branch 0 taken 10445 times.
✓ Branch 1 taken 10352 times.
20797 while (totalread < bufferlength)
1715 {
1716 10445 blockread = 0;
1717 10445 result = gate_stream_read(stream, &buffer[totalread], bufferlength - totalread, &blockread);
1718
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10444 times.
10445 if (GATE_FAILED(result))
1719 {
1720 1 break;
1721 }
1722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10444 times.
10444 GATE_DEBUG_ASSERT(blockread <= (bufferlength - totalread));
1723
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 10385 times.
10444 if (blockread == 0)
1724 {
1725 59 break;
1726 }
1727 10385 totalread += blockread;
1728 }
1729
1/2
✓ Branch 0 taken 10412 times.
✗ Branch 1 not taken.
10412 if (returned != NULL)
1730 {
1731 10412 *returned = totalread;
1732 }
1733 10412 return result;
1734 }
1735
1736 2171 gate_result_t gate_stream_read_line(gate_stream_t* stream, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1737 {
1738 2171 gate_result_t ret = GATE_RESULT_OK;
1739 2171 gate_size_t pos = 0;
1740 gate_size_t lenread;
1741
1742
1/2
✓ Branch 0 taken 117688 times.
✗ Branch 1 not taken.
117688 while (pos != bufferlength)
1743 {
1744 117688 ret = gate_stream_read(stream, &buffer[pos], 1, &lenread);
1745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117688 times.
117688 GATE_BREAK_IF_FAILED(ret);
1746
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 117653 times.
117688 if (lenread == 0)
1747 {
1748 /* end of stream */
1749 35 break;
1750 }
1751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117653 times.
117653 if (buffer[pos] == '\b')
1752 {
1753 if (pos > 0)
1754 {
1755 --pos;
1756 }
1757 continue;
1758 }
1759
1760
2/2
✓ Branch 0 taken 2136 times.
✓ Branch 1 taken 115517 times.
117653 if (buffer[pos] == '\n')
1761 {
1762 /* end of line */
1763 2136 ++pos;
1764 2136 break;
1765 }
1766 115517 ++pos;
1767 }
1768
1/2
✓ Branch 0 taken 2171 times.
✗ Branch 1 not taken.
2171 if (returned != NULL)
1769 {
1770 2171 *returned = pos;
1771 }
1772 2171 return ret;
1773 }
1774
1775
1776 230301 gate_result_t gate_stream_write_block(gate_stream_t* stream, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1777 {
1778 230301 gate_result_t result = GATE_RESULT_OK;
1779 230301 gate_size_t totalwritten = 0;
1780 gate_size_t blockwritten;
1781
2/2
✓ Branch 0 taken 193506 times.
✓ Branch 1 taken 230300 times.
423806 while (totalwritten < bufferlength)
1782 {
1783 193506 blockwritten = 0;
1784 193506 result = gate_stream_write(stream, &buffer[totalwritten], bufferlength - totalwritten, &blockwritten);
1785 /*result = stream->vtbl->write(stream, &buffer[totalwritten], bufferlength - totalwritten, &blockwritten);*/
1786
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 193505 times.
193506 if (GATE_FAILED(result))
1787 {
1788 1 break;
1789 }
1790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193505 times.
193505 GATE_DEBUG_ASSERT(blockwritten <= (bufferlength - totalwritten));
1791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 193505 times.
193505 if (blockwritten == 0)
1792 {
1793 result = GATE_RESULT_CANCELED;
1794 break;
1795 }
1796 193505 totalwritten += blockwritten;
1797 }
1798
2/2
✓ Branch 0 taken 230300 times.
✓ Branch 1 taken 1 times.
230301 if (GATE_SUCCEEDED(result))
1799 {
1800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 230300 times.
230300 GATE_DEBUG_ASSERT(bufferlength == totalwritten);
1801 }
1802
2/2
✓ Branch 0 taken 225942 times.
✓ Branch 1 taken 4359 times.
230301 if (written != NULL)
1803 {
1804 225942 *written = totalwritten;
1805 }
1806 230301 return result;
1807 }
1808
1809
1810 3171 gate_result_t gate_stream_print_cstr(gate_stream_t* stream, gate_cstr_t text)
1811 {
1812 3171 gate_size_t textlength = gate_str_length(text);
1813 gate_size_t written;
1814 3171 return gate_stream_write_block(stream, text, textlength, &written);
1815 }
1816 gate_result_t gate_stream_print_wstr(gate_stream_t* stream, gate_wstr_t wstr, gate_size_t wstr_len)
1817 {
1818 gate_result_t ret;
1819 gate_localbuffer_t buffer;
1820 gate_size_t const max_utf8_length = wstr_len * 3 + 1;
1821 char* const ptr_buffer = gate_localbuffer_create(&buffer, max_utf8_length);
1822 if (ptr_buffer == NULL)
1823 {
1824 ret = GATE_RESULT_OUTOFMEMORY;
1825 }
1826 else
1827 {
1828 gate_string_t tmp = GATE_STRING_INIT_EMPTY;
1829 gate_size_t buffer_used = gate_wstr_to_cstr(wstr, wstr_len, ptr_buffer, max_utf8_length);
1830 gate_string_create_static_len(&tmp, ptr_buffer, buffer_used);
1831 ret = gate_stream_print_string(stream, &tmp);
1832 }
1833 gate_localbuffer_destroy(&buffer);
1834 return ret;
1835 }
1836
1837 2217 gate_result_t gate_stream_println_cstr(gate_stream_t* stream, char const* text)
1838 {
1839 2217 gate_size_t textlength = gate_str_length(text);
1840 2217 gate_result_t result = GATE_RESULT_OK;
1841
2/2
✓ Branch 0 taken 1123 times.
✓ Branch 1 taken 1094 times.
2217 if (textlength > 0)
1842 {
1843 1123 result = gate_stream_write_block(stream, text, textlength, NULL);
1844 }
1845
1/2
✓ Branch 0 taken 2217 times.
✗ Branch 1 not taken.
2217 if (GATE_SUCCEEDED(result))
1846 {
1847 2217 result = gate_stream_write_block(stream, GATE_STR_NEWLINE, GATE_STR_NEWLINE_LENGTH, NULL);
1848 }
1849 2217 return result;
1850 }
1851 20 gate_result_t gate_stream_print_int(gate_stream_t* stream, gate_int32_t num)
1852 {
1853 gate_char8_t buffer[24];
1854 20 gate_size_t bufferlength = gate_str_print_int32(buffer, sizeof(buffer), num);
1855 20 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1856 }
1857 623 gate_result_t gate_stream_print_uint(gate_stream_t* stream, gate_uint32_t num)
1858 {
1859 gate_char8_t buffer[24];
1860 623 gate_size_t bufferlength = gate_str_print_uint32(buffer, sizeof(buffer), num);
1861 623 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1862 }
1863 19 gate_result_t gate_stream_print_int64(gate_stream_t* stream, gate_int64_t num)
1864 {
1865 gate_char8_t buffer[48];
1866 19 gate_size_t bufferlength = gate_str_print_int64(buffer, sizeof(buffer), num);
1867 19 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1868 }
1869 7 gate_result_t gate_stream_print_uint64(gate_stream_t* stream, gate_uint64_t num)
1870 {
1871 gate_char8_t buffer[48];
1872 7 gate_size_t bufferlength = gate_str_print_uint64(buffer, sizeof(buffer), num);
1873 7 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1874 }
1875 302 gate_result_t gate_stream_print_real(gate_stream_t* stream, gate_real64_t num, unsigned intlen, unsigned decimallen, unsigned grouplen)
1876 {
1877 gate_char8_t buffer[64];
1878 302 gate_size_t bufferlength = gate_str_print_real(buffer, sizeof(buffer), num, intlen, decimallen, grouplen);
1879 302 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1880 }
1881 46 gate_result_t gate_stream_print_string(gate_stream_t* stream, gate_string_t const* text)
1882 {
1883
1/2
✓ Branch 0 taken 46 times.
✗ Branch 1 not taken.
46 if (text != NULL)
1884 {
1885 46 return gate_stream_write_block(stream, text->str, text->length, NULL);
1886 }
1887 else
1888 {
1889 return GATE_RESULT_OK;
1890 }
1891 }
1892
1893
1894 36738 gate_result_t gate_stream_print(gate_stream_t* stream, ...)
1895 {
1896 36738 gate_result_t ret = GATE_RESULT_OK;
1897 36738 gate_bool_t continue_loop = true;
1898 char buffer[512];
1899 va_list vl;
1900 36738 va_start(vl, stream);
1901
1902 /* INFO: types small than [int] are converted to [int]
1903 https://stackoverflow.com/questions/23983471/char-is-promoted-to-int-when-passed-through-in-c
1904 */
1905
1906
2/2
✓ Branch 0 taken 110920 times.
✓ Branch 1 taken 36738 times.
147658 while (continue_loop)
1907 {
1908 110920 gate_size_t text_len = 0;
1909 110920 char const* ptr_text = NULL;
1910 110920 int print_type = va_arg(vl, int);
1911
1912
23/25
✓ Branch 0 taken 36738 times.
✓ Branch 1 taken 69755 times.
✓ Branch 2 taken 688 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2986 times.
✓ Branch 7 taken 149 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 298 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 266 times.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 1 times.
✓ Branch 17 taken 25 times.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 1 times.
✓ Branch 21 taken 1 times.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
110920 switch (print_type)
1913 {
1914 36738 case GATE_PRINT_END:
1915 {
1916 36738 text_len = 0;
1917 36738 continue_loop = false;
1918 36738 break;
1919 }
1920 69755 case GATE_PRINT_CHAR:
1921 {
1922 69755 buffer[0] = (char)va_arg(vl, int);
1923 69755 ptr_text = &buffer[0];
1924 69755 text_len = 1;
1925 69755 break;
1926 }
1927 688 case GATE_PRINT_NEWLINE:
1928 {
1929 688 ptr_text = GATE_STR_NEWLINE;
1930 688 text_len = GATE_STR_NEWLINE_LENGTH;
1931 688 break;
1932 }
1933 1 case GATE_PRINT_CR:
1934 {
1935 1 ptr_text = GATE_STR_CR;
1936 1 text_len = 1;
1937 1 break;
1938 }
1939 1 case GATE_PRINT_LF:
1940 {
1941 1 ptr_text = GATE_STR_LF;
1942 1 text_len = 1;
1943 1 break;
1944 }
1945 1 case GATE_PRINT_CRLF:
1946 {
1947 1 ptr_text = GATE_STR_CRLF;
1948 1 text_len = 2;
1949 1 break;
1950 }
1951 2986 case GATE_PRINT_CSTR:
1952 {
1953 2986 char const* val_cstr = va_arg(vl, char const*);
1954 2986 ptr_text = val_cstr;
1955 2986 text_len = gate_str_length(val_cstr);
1956 2986 break;
1957 }
1958 149 case GATE_PRINT_STRING:
1959 {
1960 149 gate_string_t const* val_str = va_arg(vl, gate_string_t const*);
1961 149 ptr_text = val_str->str;
1962 149 text_len = val_str->length;
1963 149 break;
1964 }
1965 1 case GATE_PRINT_BOOL:
1966 {
1967 1 gate_bool_t val_bool = (gate_bool_t)va_arg(vl, int);
1968
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 ptr_text = val_bool ? "true" : "false";
1969
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 text_len = val_bool ? 4 : 5;
1970 1 break;
1971 }
1972 1 case GATE_PRINT_I8:
1973 {
1974 1 gate_int8_t val_i8 = (gate_int8_t)va_arg(vl, int);
1975 1 text_len = gate_str_print_int16(buffer, sizeof(buffer), val_i8);
1976 1 ptr_text = buffer;
1977 1 break;
1978 }
1979 1 case GATE_PRINT_UI8:
1980 {
1981 1 gate_uint8_t val_ui8 = (gate_uint8_t)va_arg(vl, int);
1982 1 text_len = gate_str_print_uint16(buffer, sizeof(buffer), val_ui8);
1983 1 ptr_text = buffer;
1984 1 break;
1985 }
1986 1 case GATE_PRINT_I16:
1987 {
1988 1 gate_int16_t val_i16 = (gate_int16_t)va_arg(vl, int);
1989 1 text_len = gate_str_print_int16(buffer, sizeof(buffer), val_i16);
1990 1 ptr_text = buffer;
1991 1 break;
1992 }
1993 298 case GATE_PRINT_UI16:
1994 {
1995 298 gate_uint16_t val_ui16 = (gate_uint16_t)va_arg(vl, int);
1996 298 text_len = gate_str_print_uint16(buffer, sizeof(buffer), val_ui16);
1997 298 ptr_text = buffer;
1998 298 break;
1999 }
2000 1 case GATE_PRINT_I32:
2001 {
2002 1 gate_int32_t val_i32 = va_arg(vl, gate_int32_t);
2003 1 text_len = gate_str_print_int32(buffer, sizeof(buffer), val_i32);
2004 1 ptr_text = buffer;
2005 1 break;
2006 }
2007 266 case GATE_PRINT_UI32:
2008 {
2009 266 gate_uint32_t val_ui32 = va_arg(vl, gate_uint32_t);
2010 266 text_len = gate_str_print_uint32(buffer, sizeof(buffer), val_ui32);
2011 266 ptr_text = buffer;
2012 266 break;
2013 }
2014 1 case GATE_PRINT_I64:
2015 {
2016 1 gate_int64_t val_i64 = va_arg(vl, gate_int64_t);
2017 1 text_len = gate_str_print_int64(buffer, sizeof(buffer), val_i64);
2018 1 ptr_text = buffer;
2019 1 break;
2020 }
2021 1 case GATE_PRINT_UI64:
2022 {
2023 1 gate_uint64_t val_ui64 = va_arg(vl, gate_uint64_t);
2024 1 text_len = gate_str_print_uint64(buffer, sizeof(buffer), val_ui64);
2025 1 ptr_text = buffer;
2026 1 break;
2027 }
2028 25 case GATE_PRINT_H8:
2029 {
2030 25 gate_uint8_t val_ui8 = (gate_uint8_t)va_arg(vl, unsigned int);
2031 25 text_len = gate_str_print_hex(buffer, sizeof(buffer), val_ui8, 1, false);
2032 25 ptr_text = buffer;
2033 25 break;
2034 }
2035 1 case GATE_PRINT_H16:
2036 {
2037 1 gate_uint16_t val_ui16 = (gate_uint16_t)va_arg(vl, unsigned int);
2038 1 text_len = gate_str_print_hex(buffer, sizeof(buffer), val_ui16, 2, false);
2039 1 ptr_text = buffer;
2040 1 break;
2041 }
2042 1 case GATE_PRINT_H32:
2043 {
2044 1 gate_uint32_t val_ui32 = (gate_uint32_t)va_arg(vl, gate_uint32_t);
2045 1 text_len = gate_str_print_hex(buffer, sizeof(buffer), val_ui32, 4, false);
2046 1 ptr_text = buffer;
2047 1 break;
2048 }
2049 1 case GATE_PRINT_H64:
2050 {
2051 1 gate_uint64_t val_ui64 = (gate_uint64_t)va_arg(vl, gate_uint64_t);
2052 1 text_len = gate_str_print_hex(buffer, sizeof(buffer), val_ui64, 8, false);
2053 1 ptr_text = buffer;
2054 1 break;
2055 }
2056 1 case GATE_PRINT_R32:
2057 {
2058 1 gate_real32_t val_r32 = (gate_real32_t)va_arg(vl, double);
2059 1 text_len = gate_str_print_real(buffer, sizeof(buffer), val_r32, 0, 6, 0);
2060 1 ptr_text = buffer;
2061 1 break;
2062 }
2063 1 case GATE_PRINT_R64:
2064 {
2065 1 gate_real64_t val_r64 = va_arg(vl, gate_real64_t);
2066 1 text_len = gate_str_print_real(buffer, sizeof(buffer), val_r64, 0, 6, 0);
2067 1 ptr_text = buffer;
2068 1 break;
2069 }
2070 case GATE_PRINT_ADDRESS:
2071 {
2072 static gate_bool_t const ptr_is_16bit = sizeof(void*) == 2;
2073 static gate_bool_t const ptr_is_32bit = sizeof(void*) == 4;
2074 void* val_ptr = va_arg(vl, void*);
2075 if (ptr_is_16bit)
2076 {
2077 text_len = gate_str_print_hex_uint16(buffer, sizeof(buffer), (gate_uint16_t)(gate_uintptr_t)val_ptr, true);
2078 }
2079 else if (ptr_is_32bit)
2080 {
2081 text_len = gate_str_print_hex_uint32(buffer, sizeof(buffer), (gate_uint32_t)(gate_uintptr_t)val_ptr, true);
2082 }
2083 else
2084 {
2085 text_len = gate_str_print_hex_uint64(buffer, sizeof(buffer), (gate_uint64_t)(gate_uintptr_t)val_ptr, true);
2086 }
2087 ptr_text = buffer;
2088 break;
2089 }
2090 default:
2091 {
2092 ret = GATE_RESULT_INVALIDARG;
2093 continue_loop = false;
2094 break;
2095 }
2096 }
2097
2098 110920 ret = gate_stream_write_block(stream, ptr_text, text_len, &text_len);
2099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110920 times.
110920 GATE_BREAK_IF_FAILED(ret);
2100 }
2101 36738 va_end(vl);
2102 36738 return ret;
2103 }
2104
2105 static gate_result_t gate_stream_peek_utf8_char(gate_stream_t* stream, gate_char32_t* chr, gate_size_t* decoded)
2106 {
2107 char utf8_buffer[16];
2108 gate_size_t bytes_returned = 0;
2109 gate_size_t bytes_decoded = 0;
2110 gate_result_t ret = GATE_RESULT_FAILED;
2111
2112 ret = gate_stream_peek(stream, utf8_buffer, sizeof(utf8_buffer), &bytes_returned);
2113 if (GATE_SUCCEEDED(ret))
2114 {
2115 if (bytes_returned == 0)
2116 {
2117 /* end of stream reached */
2118 *chr = 0;
2119 *decoded = 0;
2120 }
2121 else
2122 {
2123 bytes_decoded = gate_char_read_utf8(utf8_buffer, bytes_returned, chr);
2124 if (bytes_decoded == 0)
2125 {
2126 /* utf8 error, return byte value instead */
2127 *chr = (gate_char32_t)(gate_uint8_t)utf8_buffer[0];
2128 *decoded = 1;
2129 }
2130 else
2131 {
2132 *decoded = bytes_decoded;
2133 }
2134 }
2135 }
2136 return ret;
2137 }
2138
2139 static gate_uint16_t const UNICODE_REPLACEMENT_CHAR = 0xfffd;
2140
2141 2 gate_size_t gate_stream_scan_char32(gate_stream_t* stream, gate_char32_t* out_chr)
2142 {
2143 2 gate_size_t char_count = 0;
2144 gate_result_t result;
2145 2 gate_size_t chars_retrieved = 0;
2146 2 gate_size_t utf_chars_required = 0;
2147 2 char c[4] = GATE_INIT_EMPTY;
2148
2149 2 result = gate_stream_read(stream, &c[0], 1, &chars_retrieved);
2150
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (GATE_FAILED(result) || (chars_retrieved != 1))
2151 {
2152 /* failed to read from stream */
2153 return 0;
2154 }
2155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((c[0] & 0x80) == 0)
2156 {
2157 /* we have an ANSI char -> done */
2158 *out_chr = (gate_char32_t)c[0];
2159 return 1;
2160 }
2161 /* we have multiple UTF chars */
2162
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if ((c[0] & 0xE0) == 0xC0)
2163 {
2164 1 utf_chars_required = 2;
2165 1 result = gate_stream_read(stream, &c[1], 1, &chars_retrieved);
2166 }
2167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if ((c[0] & 0xF0) == 0xE0)
2168 {
2169 utf_chars_required = 3;
2170 result = gate_stream_read_block(stream, &c[1], 2, &chars_retrieved);
2171 }
2172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if ((c[0] & 0xF8) == 0xF0)
2173 {
2174 utf_chars_required = 4;
2175 result = gate_stream_read_block(stream, &c[1], 3, &chars_retrieved);
2176 }
2177 else
2178 {
2179 /* 1st char is not UTF-8 encoded */
2180 1 *out_chr = UNICODE_REPLACEMENT_CHAR; /* invalid/replacement char */
2181 1 return 1; /* one char was read and interpreted*/
2182 }
2183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
2184 {
2185 /* reading of following UTF8 chars failed */
2186 *out_chr = UNICODE_REPLACEMENT_CHAR; /* invalid/replacement char */
2187 return 1; /* one char was read and parsed */
2188 }
2189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (chars_retrieved + 1 != utf_chars_required)
2190 {
2191 /* not all required UTF-8 bytes could be retrieved */
2192 *out_chr = UNICODE_REPLACEMENT_CHAR; /* invalid/replacement char */
2193 return 1 + chars_retrieved; /* one char was read and parsed */
2194 }
2195 1 chars_retrieved = gate_char_read_utf8(c, utf_chars_required, out_chr);
2196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (chars_retrieved == 0)
2197 {
2198 /* failed to decode UTF8 bytes */
2199 *out_chr = UNICODE_REPLACEMENT_CHAR; /* invalid/replacement char */
2200 }
2201 1 return utf_chars_required; /* return parsed bytes */
2202 }
2203 1 gate_size_t gate_stream_scan_char16(gate_stream_t* stream, gate_char16_t* out_chr)
2204 {
2205 gate_size_t bytes_parsed;
2206 gate_char32_t chr32;
2207
2208 1 bytes_parsed = gate_stream_scan_char32(stream, &chr32);
2209
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (bytes_parsed != 0)
2210 {
2211 gate_char16_t chr16[2];
2212 1 gate_size_t parsed16 = gate_char_write_utf16(chr32, &chr16[0], 2);
2213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (parsed16 != 1)
2214 {
2215 /* UTF16 not parsable, or more then one UTF16 char required */
2216 *out_chr = UNICODE_REPLACEMENT_CHAR;
2217 }
2218 else
2219 {
2220 /* return one decoded UTF16 character */
2221 1 *out_chr = chr16[0];
2222 }
2223 }
2224 1 return bytes_parsed;
2225 }
2226 1 gate_size_t gate_stream_scan_char8(gate_stream_t* stream, gate_char8_t* chr)
2227 {
2228 1 gate_size_t received = 0;
2229 1 gate_result_t result = gate_stream_read(stream, chr, 1, &received);
2230
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (GATE_FAILED(result) || (received != 1))
2231 {
2232 return 0;
2233 }
2234 1 return 1;
2235 }
2236
2237 42 static gate_bool_t is_char_int_valid(char c, gate_bool_t is_first)
2238 {
2239
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 34 times.
42 if (is_first)
2240 {
2241
4/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
8 if ((c == '+') || (c == '-') || gate_char_is_whitespace(c))
2242 {
2243 8 return true;
2244 }
2245 }
2246
3/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
34 return (c >= '0') && (c <= '9');
2247 }
2248
2249 2 gate_size_t gate_stream_scan_int64(gate_stream_t* stream, gate_int64_t* out_num)
2250 {
2251 char buffer[128];
2252 2 gate_size_t buffer_used = 0;
2253 gate_result_t result;
2254 2 gate_size_t returned = 0;
2255
2256
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 while(buffer_used < sizeof(buffer))
2257 {
2258 22 const gate_bool_t is_first = (buffer_used == 0);
2259 22 char c = 0;
2260 22 result = gate_stream_peek(stream, &c, 1, &returned);
2261
2/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
22 if (GATE_SUCCEEDED(result) && (returned == 1))
2262 {
2263
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
22 if (!is_char_int_valid(c, is_first))
2264 {
2265 // non-int-char detected
2266 2 break;
2267 }
2268 }
2269 20 result = gate_stream_read(stream, &c, 1, &returned);
2270
2/4
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 if (GATE_FAILED(result) || returned != 1)
2271 {
2272 /* failed to read next char */
2273 break;
2274 }
2275
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if (!is_char_int_valid(c, is_first))
2276 {
2277 // non-int-char detected
2278 break;
2279 }
2280
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
20 if (is_first && gate_char_is_whitespace(c))
2281 {
2282 /* ignore leading whitespace chars */
2283 2 continue;
2284 }
2285 18 buffer[buffer_used] = c;
2286 18 ++buffer_used;
2287 }
2288 2 gate_str_parse_int64(buffer, buffer_used, out_num);
2289 2 return buffer_used;
2290 }
2291
2292 36 static gate_bool_t is_char_uint_valid(char c, gate_bool_t is_first)
2293 {
2294
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 30 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 4 times.
36 if (is_first && (gate_char_is_whitespace(c)))
2295 {
2296 2 return true;
2297 }
2298
3/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
34 return (c >= '0') && (c <= '9');
2299 }
2300
2301 2 gate_size_t gate_stream_scan_uint64(gate_stream_t* stream, gate_uint64_t* out_num)
2302 {
2303 char buffer[128];
2304 2 gate_size_t buffer_used = 0;
2305 gate_result_t result;
2306 2 gate_size_t returned = 0;
2307
2308
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 while(buffer_used < sizeof(buffer))
2309 {
2310 19 const gate_bool_t is_first = (buffer_used == 0);
2311 19 char c = 0;
2312 19 result = gate_stream_peek(stream, &c, 1, &returned);
2313
2/4
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
19 if (GATE_SUCCEEDED(result) && (returned == 1))
2314 {
2315
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 17 times.
19 if (!is_char_uint_valid(c, is_first))
2316 {
2317 // non-digit detected
2318 2 break;
2319 }
2320 }
2321 17 result = gate_stream_read(stream, &c, 1, &returned);
2322
2/4
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
17 if (GATE_FAILED(result) || returned != 1)
2323 {
2324 /* failed to read next char */
2325 break;
2326 }
2327
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if (!is_char_uint_valid(c, is_first))
2328 {
2329 // non-digit detected
2330 break;
2331 }
2332
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 14 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
17 if (is_first && gate_char_is_whitespace(c))
2333 {
2334 1 continue; // skip leading whitespace chars
2335 }
2336 16 buffer[buffer_used] = c;
2337 16 ++buffer_used;
2338 }
2339 2 gate_str_parse_uint64(buffer, buffer_used, out_num);
2340 2 return buffer_used;
2341 }
2342
2343 1 gate_size_t gate_stream_scan_int(gate_stream_t* stream, gate_int32_t* out_num)
2344 {
2345 1 gate_int64_t i64 = 0;
2346 1 gate_size_t parsed_chars = gate_stream_scan_int64(stream, &i64);
2347 1 *out_num = (gate_int32_t)i64;
2348 1 return parsed_chars;
2349 }
2350
2351 1 gate_size_t gate_stream_scan_uint(gate_stream_t* stream, gate_uint32_t* out_num)
2352 {
2353 1 gate_uint64_t u64 = 0;
2354 1 gate_size_t parsed_chars = gate_stream_scan_uint64(stream, &u64);
2355 1 *out_num = (gate_uint32_t)u64;
2356 1 return parsed_chars;
2357 }
2358
2359 19 static gate_bool_t is_char_float_valid(char c, gate_bool_t is_first, gate_bool_t dot_allowed)
2360 {
2361
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (is_first)
2362 {
2363
4/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
4 if ((c == '+') || (c == '-') || gate_char_is_whitespace(c))
2364 {
2365 4 return true;
2366 }
2367 }
2368
6/8
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
15 return (c >= '0') && (c <= '9') || (dot_allowed && (c == '.'));
2369 }
2370
2371 1 gate_size_t gate_stream_scan_real(gate_stream_t* stream, gate_real64_t* out_num)
2372 {
2373 char buffer[128];
2374 1 gate_size_t buffer_used = 0;
2375 gate_result_t result;
2376 1 gate_size_t returned = 0;
2377 1 gate_bool_t dot_allowed = true;
2378
2379
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 while(buffer_used < sizeof(buffer))
2380 {
2381 10 const gate_bool_t is_first = (buffer_used == 0);
2382 10 char c = 0;
2383 10 result = gate_stream_peek(stream, &c, 1, &returned);
2384
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 if (GATE_SUCCEEDED(result) && (returned == 1))
2385 {
2386
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 9 times.
10 if (!is_char_float_valid(c, is_first, dot_allowed))
2387 {
2388 // non-int-char detected
2389 1 break;
2390 }
2391 }
2392 9 result = gate_stream_read(stream, &c, 1, &returned);
2393
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 if (GATE_FAILED(result) || returned != 1)
2394 {
2395 /* failed to read next char */
2396 break;
2397 }
2398
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (!is_char_float_valid(c, is_first, dot_allowed))
2399 {
2400 // non-int-char detected
2401 break;
2402 }
2403
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
9 if (is_first && gate_char_is_whitespace(c))
2404 {
2405 /* ignore leading whitespace chars */
2406 1 continue;
2407 }
2408
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (c == '.')
2409 {
2410
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (dot_allowed)
2411 {
2412 /* one dot is OK ...*/
2413 1 dot_allowed =false;
2414 }
2415 else
2416 {
2417 /* more dots are an error */
2418 break;
2419 }
2420 }
2421
2422 8 buffer[buffer_used] = c;
2423 8 ++buffer_used;
2424 }
2425 1 gate_str_parse_real(buffer, buffer_used, out_num);
2426 1 return buffer_used;
2427 }
2428 1 gate_size_t gate_stream_scan_string(gate_stream_t* stream, gate_string_t* out_text)
2429 {
2430 1 gate_size_t chars_processed = 0;
2431 1 gate_strbuilder_t builder = GATE_INIT_EMPTY;
2432
2433 1 gate_strbuilder_create(&builder, 0);
2434
2435 do
2436 6 {
2437 gate_result_t result;
2438 7 gate_size_t received = 0;
2439 7 char c = 0;
2440 7 result = gate_stream_read(stream, &c, 1, &received);
2441
3/4
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1 times.
7 if (GATE_FAILED(result) || (received != 1))
2442 {
2443 // stream error or end of stream
2444 break;
2445 }
2446 6 ++chars_processed;
2447
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
6 if (gate_char_is_whitespace(c))
2448 {
2449
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_strbuilder_length(&builder) == 0)
2450 {
2451 /* leading whitespaces are skipped */
2452 1 continue;
2453 }
2454 else
2455 {
2456 /* token completed */
2457 break;
2458 }
2459 }
2460 5 received = gate_strbuilder_append_chars(&builder, 1, c);
2461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (received == 0)
2462 {
2463 /* allocation error in strbuilder -> cancel */
2464 break;
2465 }
2466 } while(true);
2467
2468
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_strbuilder_to_string(&builder, out_text))
2469 {
2470 // string creating failed -> clear it
2471 gate_string_create_empty(out_text);
2472 }
2473
2474 1 return chars_processed;
2475 }
2476
2477
2478
2479
2480 40198 gate_result_t gate_stream_transfer_buffer(gate_stream_t* src, gate_stream_t* dst, char* buffer, gate_size_t buffersize)
2481 {
2482 gate_size_t bytes_read;
2483 gate_size_t bytes_written;
2484 gate_result_t result;
2485 for (;;)
2486 {
2487 40198 result = gate_stream_read(src, buffer, buffersize, &bytes_read);
2488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40198 times.
40198 if (GATE_FAILED(result))
2489 {
2490 break;
2491 }
2492
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 40152 times.
40198 if (bytes_read == 0)
2493 {
2494 /* end of stream reached */
2495 46 break;
2496 }
2497 40152 result = gate_stream_write_block(dst, buffer, bytes_read, &bytes_written);
2498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40152 times.
40152 if (GATE_FAILED(result))
2499 {
2500 break;
2501 }
2502 }
2503 46 return result;
2504 }
2505
2506 7 gate_result_t gate_stream_transfer_limit(gate_stream_t* src, gate_uint64_t limit, gate_stream_t* dst, gate_uint64_t* transferred)
2507 {
2508 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
2509 static gate_size_t const buffer_size = sizeof(buffer);
2510 gate_size_t next_size;
2511 gate_size_t bytes_read;
2512 gate_size_t bytes_written;
2513 7 gate_result_t result = GATE_RESULT_OK;
2514 7 gate_uint64_t counter = 0;
2515
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 while (limit > 0)
2516 {
2517 7 next_size = (limit > buffer_size) ? buffer_size : (gate_size_t)limit;
2518 7 result = gate_stream_read(src, buffer, next_size, &bytes_read);
2519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (GATE_FAILED(result))
2520 {
2521 break;
2522 }
2523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (bytes_read == 0)
2524 {
2525 /* end of stream reached */
2526 break;
2527 }
2528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 GATE_DEBUG_ASSERT(limit >= bytes_read);
2529 7 limit -= bytes_read;
2530 7 result = gate_stream_write_block(dst, buffer, bytes_read, &bytes_written);
2531
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (GATE_FAILED(result))
2532 {
2533 break;
2534 }
2535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 GATE_DEBUG_ASSERT(bytes_read == bytes_written);
2536 7 counter += bytes_written;
2537 }
2538
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (transferred)
2539 {
2540 7 *transferred = counter;
2541 }
2542 7 return result;
2543 }
2544
2545
2546 35 gate_result_t gate_stream_transfer(gate_stream_t* src, gate_stream_t* dst)
2547 {
2548 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
2549 35 return gate_stream_transfer_buffer(src, dst, buffer, sizeof(buffer));
2550 }
2551
2552 5 gate_result_t gate_stream_skip(gate_stream_t* src, gate_uint64_t count, gate_uint64_t* bytes_skipped)
2553 {
2554 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
2555 gate_size_t nextlen;
2556 5 gate_size_t returned = 1;
2557 5 gate_result_t result = GATE_RESULT_OK;
2558 5 gate_uint64_t actual_skipped = 0;
2559
2560
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
10 while ((count != 0) && (returned != 0))
2561 {
2562 5 nextlen = (count > GATE_MAX_COPYBUFFER_LENGTH) ? GATE_MAX_COPYBUFFER_LENGTH : (gate_size_t)count;
2563 5 result = gate_stream_read_block(src, buffer, nextlen, &returned);
2564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 GATE_BREAK_IF_FAILED(result);
2565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 GATE_DEBUG_ASSERT(returned <= nextlen);
2566 5 actual_skipped += returned;
2567 5 count -= returned;
2568 }
2569
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (bytes_skipped)
2570 {
2571 2 *bytes_skipped = actual_skipped;
2572 }
2573 5 return result;
2574 }
2575
2576