GCC Code Coverage Report


Directory: src/gate/
File: src/gate/streams.c
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 984 1180 83.4%
Functions: 113 121 93.4%
Branches: 335 531 63.1%

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 162 static void gate_memstream_release_impl(void* self)
113 {
114 162 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
115
2/2
✓ Branch 1 taken 143 times.
✓ Branch 2 taken 19 times.
162 if (gate_atomic_int_dec(&strm->ref_counter) == 0)
116 {
117 /* release memstream */
118
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 3 times.
143 if (strm->priv_membuffer != NULL)
119 {
120 140 gate_mem_dealloc(strm->priv_membuffer);
121 140 strm->priv_membuffer = NULL;
122 }
123 143 gate_mem_dealloc(strm);
124 }
125 162 }
126 19 static int gate_memstream_retain_impl(void* self)
127 {
128 19 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
129 19 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 122175 gate_result_t gate_memstream_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
138 {
139 122175 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
140
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 122065 times.
122175 if (bufferlength > strm->priv_memlength)
141 {
142 110 bufferlength = strm->priv_memlength;
143 }
144
2/2
✓ Branch 0 taken 122114 times.
✓ Branch 1 taken 61 times.
122175 if (bufferlength != 0)
145 {
146 122114 gate_mem_copy(buffer, &strm->priv_membuffer[strm->priv_memoffset], bufferlength);
147 122114 strm->priv_memlength -= bufferlength;
148
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 122019 times.
122114 if (strm->priv_memlength == 0)
149 {
150 95 strm->priv_memoffset = 0;
151 }
152 else
153 {
154 122019 strm->priv_memoffset += bufferlength;
155 }
156 }
157
1/2
✓ Branch 0 taken 122175 times.
✗ Branch 1 not taken.
122175 if (returned != NULL)
158 {
159 122175 *returned = bufferlength;
160 }
161 122175 return GATE_RESULT_OK;
162 }
163 602 gate_result_t gate_memstream_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
164 {
165 602 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
166
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 600 times.
602 if (bufferlength > strm->priv_memlength)
167 {
168 2 bufferlength = strm->priv_memlength;
169 }
170
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 2 times.
602 if (bufferlength != 0)
171 {
172 600 gate_mem_copy(buffer, strm->priv_membuffer, bufferlength);
173 }
174
1/2
✓ Branch 0 taken 602 times.
✗ Branch 1 not taken.
602 if (returned != NULL)
175 {
176 602 *returned = bufferlength;
177 }
178 602 return GATE_RESULT_OK;
179 }
180 182555 gate_result_t gate_memstream_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
181 {
182 182555 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
183 182555 gate_result_t result = strm->vtbl->reserve(strm, bufferlength);
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182555 times.
182555 if (GATE_FAILED(result))
185 {
186 return result;
187 }
188
189 182555 gate_mem_copy(&strm->priv_membuffer[strm->priv_memoffset + strm->priv_memlength], buffer, bufferlength);
190 182555 strm->priv_memlength += bufferlength;
191
192
1/2
✓ Branch 0 taken 182555 times.
✗ Branch 1 not taken.
182555 if (written != NULL)
193 {
194 182555 *written = bufferlength;
195 }
196 182555 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 182609 static gate_result_t gate_memstream_reserve_impl(void* self, gate_size_t space)
204 {
205 182609 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
206 182609 gate_size_t unusedspace = strm->priv_memcapacity - strm->priv_memlength;
207 182609 gate_size_t freespace = unusedspace - strm->priv_memoffset;
208
2/2
✓ Branch 0 taken 711 times.
✓ Branch 1 taken 181898 times.
182609 if (space > freespace)
209 {
210
1/2
✓ Branch 0 taken 711 times.
✗ Branch 1 not taken.
711 if (space > unusedspace)
211 {
212 /* reallocation is required */
213 711 gate_size_t newcapacity = (strm->priv_memcapacity + space) + (strm->priv_memcapacity / 2);
214 711 char* newbuffer = (char*)gate_mem_alloc(newcapacity);
215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 711 times.
711 if (newbuffer == NULL)
216 {
217 return GATE_RESULT_OUTOFMEMORY;
218 }
219
2/2
✓ Branch 0 taken 569 times.
✓ Branch 1 taken 142 times.
711 if (strm->priv_memlength != 0)
220 {
221 569 gate_mem_copy(&newbuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
222 }
223
2/2
✓ Branch 0 taken 571 times.
✓ Branch 1 taken 140 times.
711 if (strm->priv_membuffer != NULL)
224 {
225 571 gate_mem_dealloc(strm->priv_membuffer);
226 }
227 711 strm->priv_membuffer = newbuffer;
228 711 strm->priv_memoffset = 0;
229 711 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 182609 return GATE_RESULT_OK;
239 }
240 54 static gate_size_t gate_memstream_size_impl(void* self)
241 {
242 54 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
243 54 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 7 static gate_size_t gate_memstream_discard_impl(void* self, gate_size_t bytestodiscard)
266 {
267 7 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
268 gate_size_t ret;
269
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 if (bytestodiscard >= strm->priv_memlength)
270 {
271 2 ret = strm->priv_memlength;
272 2 strm->priv_memoffset = 0;
273 2 strm->priv_memlength = 0;
274 }
275 else
276 {
277 5 ret = bytestodiscard;
278 5 strm->priv_memoffset += bytestodiscard;
279 5 strm->priv_memlength -= bytestodiscard;
280 }
281 7 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 48 static char const* gate_memstream_get_data_impl(void* self)
301 {
302 48 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
303 48 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 143 void gate_init_memstream_vtbl()
317 {
318
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 134 times.
143 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 9 gate_memstream_vtbl = local_vtbl;
340 }
341 143 }
342
343 143 gate_memstream_t* gate_memstream_create(gate_size_t capacity)
344 {
345 gate_result_t result;
346 143 gate_memstream_impl_t* ret = (gate_memstream_impl_t*)gate_mem_alloc(sizeof(gate_memstream_impl_t));
347
1/2
✓ Branch 0 taken 143 times.
✗ Branch 1 not taken.
143 if (ret != NULL)
348 {
349 143 gate_init_memstream_vtbl();
350 143 ret->vtbl = &gate_memstream_vtbl;
351 143 gate_atomic_int_set(&ret->ref_counter, 1);
352 143 ret->priv_membuffer = NULL;
353 143 ret->priv_memcapacity = 0;
354 143 ret->priv_memoffset = 0;
355 143 ret->priv_memlength = 0;
356
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 91 times.
143 if (capacity > 0)
357 {
358 52 result = ret->vtbl->reserve(ret, capacity);
359 (void)result;
360 }
361
362 }
363 143 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 158 static GATE_INTERFACE_VTBL(gate_stringstream)* gate_init_stringstream_vtbl()
1427 {
1428 static GATE_INTERFACE_VTBL(gate_stringstream) gate_stringstream_vtbl;
1429
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 149 times.
158 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 158 return &gate_stringstream_vtbl;
1450 }
1451
1452 typedef struct gate_stringstream_impl
1453 {
1454 GATE_INTERFACE_VTBL(gate_stringstream)* vtbl;
1455
1456 gate_atomic_int_t ref_counter;
1457 gate_strbuilder_t* ptr_builder;
1458 gate_strbuilder_t str_builder;
1459 } gate_stringstream_impl_t;
1460
1461
1462 157 gate_stringstream_t* gate_stringstream_create(gate_size_t capacity)
1463 {
1464 157 gate_stringstream_impl_t* ret = gate_mem_alloc(sizeof(gate_stringstream_impl_t));
1465
1/2
✓ Branch 0 taken 157 times.
✗ Branch 1 not taken.
157 if (ret != NULL)
1466 {
1467 157 gate_mem_clear(ret, sizeof(gate_stringstream_impl_t));
1468 157 ret->vtbl = gate_init_stringstream_vtbl();
1469 157 gate_atomic_int_init(&ret->ref_counter, 1);
1470 157 gate_strbuilder_create(&ret->str_builder, capacity);
1471 157 ret->ptr_builder = &ret->str_builder;
1472 }
1473 157 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 ret->vtbl = gate_init_stringstream_vtbl();
1483 1 gate_atomic_int_init(&ret->ref_counter, 1);
1484 1 ret->ptr_builder = external_strbuilder;
1485 }
1486 1 return (gate_stringstream_t*)ret;
1487 }
1488
1489
1490 161 static void gate_stringstream_release_impl(void* ptr)
1491 {
1492 161 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1493
2/2
✓ Branch 1 taken 158 times.
✓ Branch 2 taken 3 times.
161 if (gate_atomic_int_dec(&thisptr->ref_counter) == 0)
1494 {
1495
2/2
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 1 times.
158 if (&thisptr->str_builder == thisptr->ptr_builder)
1496 {
1497 157 gate_strbuilder_release(&thisptr->str_builder);
1498 }
1499 158 gate_mem_dealloc(thisptr);
1500 }
1501 161 }
1502 3 static int gate_stringstream_retain_impl(void* ptr)
1503 {
1504 3 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1505 3 return (int)gate_atomic_int_inc(&thisptr->ref_counter);
1506 }
1507 3 static char const* gate_stringstream_get_interface_name_impl(void* ptr)
1508 {
1509 (void)ptr;
1510 3 return GATE_INTERFACE_NAME_STRINGSTREAM;
1511 }
1512 504 static gate_result_t gate_stringstream_read_impl(void* ptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1513 {
1514 504 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1515 504 gate_size_t bytesread = 0;
1516 504 gate_result_t result = gate_stringstream_peek_impl(ptr, buffer, bufferlength, &bytesread);
1517
1518
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (GATE_SUCCEEDED(result))
1519 {
1520 504 gate_strbuilder_discard(thisptr->ptr_builder, bytesread);
1521
1/2
✓ Branch 0 taken 504 times.
✗ Branch 1 not taken.
504 if (returned != NULL)
1522 {
1523 504 *returned = bytesread;
1524 }
1525 }
1526 504 return result;
1527 }
1528 755 static gate_result_t gate_stringstream_peek_impl(void* ptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1529 {
1530 755 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1531 755 char const* dataptr = gate_strbuilder_ptr(thisptr->ptr_builder, 0);
1532 755 gate_size_t datalen = gate_strbuilder_length(thisptr->ptr_builder);
1533
2/4
✓ Branch 0 taken 755 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 755 times.
755 if ((bufferlength > 0) && (buffer == NULL))
1534 {
1535 return GATE_RESULT_INVALIDARG;
1536 }
1537
2/2
✓ Branch 0 taken 115 times.
✓ Branch 1 taken 640 times.
755 if (bufferlength > datalen)
1538 {
1539 115 bufferlength = datalen;
1540 }
1541
2/2
✓ Branch 0 taken 688 times.
✓ Branch 1 taken 67 times.
755 if (bufferlength > 0)
1542 {
1543
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 688 times.
688 if (NULL == gate_mem_copy(buffer, dataptr, bufferlength))
1544 {
1545 return GATE_RESULT_FAILED;
1546 }
1547 }
1548
1/2
✓ Branch 0 taken 755 times.
✗ Branch 1 not taken.
755 if (returned != NULL)
1549 {
1550 755 *returned = bufferlength;
1551 }
1552 755 return GATE_RESULT_OK;
1553 }
1554 787 static gate_result_t gate_stringstream_write_impl(void* ptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1555 {
1556 787 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1557 gate_size_t lenwritten;
1558 gate_result_t ret;
1559 787 lenwritten = gate_strbuilder_append_text(thisptr->ptr_builder, buffer, bufferlength);
1560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 787 times.
787 ret = (lenwritten == 0) ? GATE_RESULT_FAILED : GATE_RESULT_OK;
1561
1562
1/2
✓ Branch 0 taken 787 times.
✗ Branch 1 not taken.
787 if (written != NULL)
1563 {
1564 787 *written = lenwritten;
1565 }
1566 787 return ret;
1567 }
1568 104 static gate_result_t gate_stringstream_flush_impl(void* ptr)
1569 {
1570 (void)ptr;
1571 104 return GATE_RESULT_OK;
1572 }
1573
1574 3 static char const* gate_stringstream_get_data_impl(void* ptr)
1575 {
1576 3 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1577 3 return gate_strbuilder_ptr(thisptr->ptr_builder, 0);
1578 }
1579 3 static gate_size_t gate_stringstream_size_impl(void* ptr)
1580 {
1581 3 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1582 3 return gate_strbuilder_length(thisptr->ptr_builder);
1583 }
1584 32 static gate_result_t gate_stringstream_get_current_view_impl(void* ptr, gate_string_t* ptr_output)
1585 {
1586 32 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1587 32 char const* const txt = gate_strbuilder_ptr(thisptr->ptr_builder, 0);
1588 32 gate_size_t const txtlen = gate_strbuilder_length(thisptr->ptr_builder);
1589
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 if (NULL != gate_string_create_static_len(ptr_output, txt, txtlen))
1590 {
1591 32 return GATE_RESULT_OK;
1592 }
1593 else
1594 {
1595 return GATE_RESULT_OUTOFMEMORY;
1596 }
1597 }
1598 65 static gate_result_t gate_stringstream_to_string_impl(void* ptr, gate_string_t* ptr_output)
1599 {
1600 65 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1601
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
65 if (NULL == gate_strbuilder_to_string(thisptr->ptr_builder, ptr_output))
1602 {
1603 return GATE_RESULT_FAILED;
1604 }
1605 else
1606 {
1607 65 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 231176 gate_result_t gate_stream_write_block(gate_stream_t* stream, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1777 {
1778 231176 gate_result_t result = GATE_RESULT_OK;
1779 231176 gate_size_t totalwritten = 0;
1780 gate_size_t blockwritten;
1781
2/2
✓ Branch 0 taken 194300 times.
✓ Branch 1 taken 231175 times.
425475 while (totalwritten < bufferlength)
1782 {
1783 194300 blockwritten = 0;
1784 194300 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 194299 times.
194300 if (GATE_FAILED(result))
1787 {
1788 1 break;
1789 }
1790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194299 times.
194299 GATE_DEBUG_ASSERT(blockwritten <= (bufferlength - totalwritten));
1791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194299 times.
194299 if (blockwritten == 0)
1792 {
1793 result = GATE_RESULT_CANCELED;
1794 break;
1795 }
1796 194299 totalwritten += blockwritten;
1797 }
1798
2/2
✓ Branch 0 taken 231175 times.
✓ Branch 1 taken 1 times.
231176 if (GATE_SUCCEEDED(result))
1799 {
1800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 231175 times.
231175 GATE_DEBUG_ASSERT(bufferlength == totalwritten);
1801 }
1802
2/2
✓ Branch 0 taken 226629 times.
✓ Branch 1 taken 4547 times.
231176 if (written != NULL)
1803 {
1804 226629 *written = totalwritten;
1805 }
1806 231176 return result;
1807 }
1808
1809
1810 3351 gate_result_t gate_stream_print_cstr(gate_stream_t* stream, gate_cstr_t text)
1811 {
1812 3351 gate_size_t textlength = gate_str_length(text);
1813 gate_size_t written;
1814 3351 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 2283 gate_result_t gate_stream_println_cstr(gate_stream_t* stream, char const* text)
1838 {
1839 2283 gate_size_t textlength = gate_str_length(text);
1840 2283 gate_result_t result = GATE_RESULT_OK;
1841
2/2
✓ Branch 0 taken 1189 times.
✓ Branch 1 taken 1094 times.
2283 if (textlength > 0)
1842 {
1843 1189 result = gate_stream_write_block(stream, text, textlength, NULL);
1844 }
1845
1/2
✓ Branch 0 taken 2283 times.
✗ Branch 1 not taken.
2283 if (GATE_SUCCEEDED(result))
1846 {
1847 2283 result = gate_stream_write_block(stream, GATE_STR_NEWLINE, GATE_STR_NEWLINE_LENGTH, NULL);
1848 }
1849 2283 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 661 gate_result_t gate_stream_print_uint(gate_stream_t* stream, gate_uint32_t num)
1858 {
1859 gate_char8_t buffer[24];
1860 661 gate_size_t bufferlength = gate_str_print_uint32(buffer, sizeof(buffer), num);
1861 661 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 319 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 319 gate_size_t bufferlength = gate_str_print_real(buffer, sizeof(buffer), num, intlen, decimallen, grouplen);
1879 319 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1880 }
1881 47 gate_result_t gate_stream_print_string(gate_stream_t* stream, gate_string_t const* text)
1882 {
1883
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 if (text != NULL)
1884 {
1885 47 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 36819 gate_result_t gate_stream_print(gate_stream_t* stream, ...)
1895 {
1896 36819 gate_result_t ret = GATE_RESULT_OK;
1897 36819 gate_bool_t continue_loop = true;
1898 char buffer[512];
1899 va_list vl;
1900 36819 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 111257 times.
✓ Branch 1 taken 36819 times.
148076 while (continue_loop)
1907 {
1908 111257 gate_size_t text_len = 0;
1909 111257 char const* ptr_text = NULL;
1910 111257 int print_type = va_arg(vl, int);
1911
1912
23/25
✓ Branch 0 taken 36819 times.
✓ Branch 1 taken 69755 times.
✓ Branch 2 taken 722 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 3140 times.
✓ Branch 7 taken 167 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 315 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 281 times.
✓ Branch 15 taken 2 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.
111257 switch (print_type)
1913 {
1914 36819 case GATE_PRINT_END:
1915 {
1916 36819 text_len = 0;
1917 36819 continue_loop = false;
1918 36819 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 722 case GATE_PRINT_NEWLINE:
1928 {
1929 722 ptr_text = GATE_STR_NEWLINE;
1930 722 text_len = GATE_STR_NEWLINE_LENGTH;
1931 722 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 18 case GATE_PRINT_CRLF:
1946 {
1947 18 ptr_text = GATE_STR_CRLF;
1948 18 text_len = 2;
1949 18 break;
1950 }
1951 3140 case GATE_PRINT_CSTR:
1952 {
1953 3140 char const* val_cstr = va_arg(vl, char const*);
1954 3140 ptr_text = val_cstr;
1955 3140 text_len = gate_str_length(val_cstr);
1956 3140 break;
1957 }
1958 167 case GATE_PRINT_STRING:
1959 {
1960 167 gate_string_t const* val_str = va_arg(vl, gate_string_t const*);
1961 167 ptr_text = val_str->str;
1962 167 text_len = val_str->length;
1963 167 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 315 case GATE_PRINT_UI16:
1994 {
1995 315 gate_uint16_t val_ui16 = (gate_uint16_t)va_arg(vl, int);
1996 315 text_len = gate_str_print_uint16(buffer, sizeof(buffer), val_ui16);
1997 315 ptr_text = buffer;
1998 315 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 281 case GATE_PRINT_UI32:
2008 {
2009 281 gate_uint32_t val_ui32 = va_arg(vl, gate_uint32_t);
2010 281 text_len = gate_str_print_uint32(buffer, sizeof(buffer), val_ui32);
2011 281 ptr_text = buffer;
2012 281 break;
2013 }
2014 2 case GATE_PRINT_I64:
2015 {
2016 2 gate_int64_t val_i64 = va_arg(vl, gate_int64_t);
2017 2 text_len = gate_str_print_int64(buffer, sizeof(buffer), val_i64);
2018 2 ptr_text = buffer;
2019 2 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 111257 ret = gate_stream_write_block(stream, ptr_text, text_len, &text_len);
2099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111257 times.
111257 GATE_BREAK_IF_FAILED(ret);
2100 }
2101 36819 va_end(vl);
2102 36819 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 gate_result_t result;
2144 2 gate_size_t chars_retrieved = 0;
2145 2 gate_size_t utf_chars_required = 0;
2146 2 char c[4] = GATE_INIT_EMPTY;
2147
2148 2 result = gate_stream_read(stream, &c[0], 1, &chars_retrieved);
2149
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))
2150 {
2151 /* failed to read from stream */
2152 return 0;
2153 }
2154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if ((c[0] & 0x80) == 0)
2155 {
2156 /* we have an ANSI char -> done */
2157 *out_chr = (gate_char32_t)c[0];
2158 return 1;
2159 }
2160 /* we have multiple UTF chars */
2161
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if ((c[0] & 0xE0) == 0xC0)
2162 {
2163 1 utf_chars_required = 2;
2164 1 result = gate_stream_read(stream, &c[1], 1, &chars_retrieved);
2165 }
2166
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if ((c[0] & 0xF0) == 0xE0)
2167 {
2168 utf_chars_required = 3;
2169 result = gate_stream_read_block(stream, &c[1], 2, &chars_retrieved);
2170 }
2171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if ((c[0] & 0xF8) == 0xF0)
2172 {
2173 utf_chars_required = 4;
2174 result = gate_stream_read_block(stream, &c[1], 3, &chars_retrieved);
2175 }
2176 else
2177 {
2178 /* 1st char is not UTF-8 encoded */
2179 1 *out_chr = UNICODE_REPLACEMENT_CHAR; /* invalid/replacement char */
2180 1 return 1; /* one char was read and interpreted*/
2181 }
2182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
2183 {
2184 /* reading of following UTF8 chars failed */
2185 *out_chr = UNICODE_REPLACEMENT_CHAR; /* invalid/replacement char */
2186 return 1; /* one char was read and parsed */
2187 }
2188
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (chars_retrieved + 1 != utf_chars_required)
2189 {
2190 /* not all required UTF-8 bytes could be retrieved */
2191 *out_chr = UNICODE_REPLACEMENT_CHAR; /* invalid/replacement char */
2192 return 1 + chars_retrieved; /* one char was read and parsed */
2193 }
2194 1 chars_retrieved = gate_char_read_utf8(c, utf_chars_required, out_chr);
2195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (chars_retrieved == 0)
2196 {
2197 /* failed to decode UTF8 bytes */
2198 *out_chr = UNICODE_REPLACEMENT_CHAR; /* invalid/replacement char */
2199 }
2200 1 return utf_chars_required; /* return parsed bytes */
2201 }
2202 1 gate_size_t gate_stream_scan_char16(gate_stream_t* stream, gate_char16_t* out_chr)
2203 {
2204 gate_size_t bytes_parsed;
2205 gate_char32_t chr32;
2206
2207 1 bytes_parsed = gate_stream_scan_char32(stream, &chr32);
2208
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (bytes_parsed != 0)
2209 {
2210 gate_char16_t chr16[2];
2211 1 gate_size_t parsed16 = gate_char_write_utf16(chr32, &chr16[0], 2);
2212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (parsed16 != 1)
2213 {
2214 /* UTF16 not parsable, or more then one UTF16 char required */
2215 *out_chr = UNICODE_REPLACEMENT_CHAR;
2216 }
2217 else
2218 {
2219 /* return one decoded UTF16 character */
2220 1 *out_chr = chr16[0];
2221 }
2222 }
2223 1 return bytes_parsed;
2224 }
2225 1 gate_size_t gate_stream_scan_char8(gate_stream_t* stream, gate_char8_t* chr)
2226 {
2227 1 gate_size_t received = 0;
2228 1 gate_result_t result = gate_stream_read(stream, chr, 1, &received);
2229
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))
2230 {
2231 return 0;
2232 }
2233 1 return 1;
2234 }
2235
2236 42 static gate_bool_t is_char_int_valid(char c, gate_bool_t is_first)
2237 {
2238
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 34 times.
42 if (is_first)
2239 {
2240
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))
2241 {
2242 8 return true;
2243 }
2244 }
2245
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');
2246 }
2247
2248 2 gate_size_t gate_stream_scan_int64(gate_stream_t* stream, gate_int64_t* out_num)
2249 {
2250 char buffer[128];
2251 2 gate_size_t buffer_used = 0;
2252 gate_result_t result;
2253 2 gate_size_t returned = 0;
2254
2255
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 while(buffer_used < sizeof(buffer))
2256 {
2257 22 const gate_bool_t is_first = (buffer_used == 0);
2258 22 char c = 0;
2259 22 result = gate_stream_peek(stream, &c, 1, &returned);
2260
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))
2261 {
2262
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
22 if (!is_char_int_valid(c, is_first))
2263 {
2264 // non-int-char detected
2265 2 break;
2266 }
2267 }
2268 20 result = gate_stream_read(stream, &c, 1, &returned);
2269
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)
2270 {
2271 /* failed to read next char */
2272 break;
2273 }
2274
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if (!is_char_int_valid(c, is_first))
2275 {
2276 // non-int-char detected
2277 break;
2278 }
2279
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))
2280 {
2281 /* ignore leading whitespace chars */
2282 2 continue;
2283 }
2284 18 buffer[buffer_used] = c;
2285 18 ++buffer_used;
2286 }
2287 2 gate_str_parse_int64(buffer, buffer_used, out_num);
2288 2 return buffer_used;
2289 }
2290
2291 36 static gate_bool_t is_char_uint_valid(char c, gate_bool_t is_first)
2292 {
2293
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)))
2294 {
2295 2 return true;
2296 }
2297
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');
2298 }
2299
2300 2 gate_size_t gate_stream_scan_uint64(gate_stream_t* stream, gate_uint64_t* out_num)
2301 {
2302 char buffer[128];
2303 2 gate_size_t buffer_used = 0;
2304 gate_result_t result;
2305 2 gate_size_t returned = 0;
2306
2307
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 while(buffer_used < sizeof(buffer))
2308 {
2309 19 const gate_bool_t is_first = (buffer_used == 0);
2310 19 char c = 0;
2311 19 result = gate_stream_peek(stream, &c, 1, &returned);
2312
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))
2313 {
2314
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 17 times.
19 if (!is_char_uint_valid(c, is_first))
2315 {
2316 // non-digit detected
2317 2 break;
2318 }
2319 }
2320 17 result = gate_stream_read(stream, &c, 1, &returned);
2321
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)
2322 {
2323 /* failed to read next char */
2324 break;
2325 }
2326
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 if (!is_char_uint_valid(c, is_first))
2327 {
2328 // non-digit detected
2329 break;
2330 }
2331
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))
2332 {
2333 1 continue; // skip leading whitespace chars
2334 }
2335 16 buffer[buffer_used] = c;
2336 16 ++buffer_used;
2337 }
2338 2 gate_str_parse_uint64(buffer, buffer_used, out_num);
2339 2 return buffer_used;
2340 }
2341
2342 1 gate_size_t gate_stream_scan_int(gate_stream_t* stream, gate_int32_t* out_num)
2343 {
2344 1 gate_int64_t i64 = 0;
2345 1 gate_size_t parsed_chars = gate_stream_scan_int64(stream, &i64);
2346 1 *out_num = (gate_int32_t)i64;
2347 1 return parsed_chars;
2348 }
2349
2350 1 gate_size_t gate_stream_scan_uint(gate_stream_t* stream, gate_uint32_t* out_num)
2351 {
2352 1 gate_uint64_t u64 = 0;
2353 1 gate_size_t parsed_chars = gate_stream_scan_uint64(stream, &u64);
2354 1 *out_num = (gate_uint32_t)u64;
2355 1 return parsed_chars;
2356 }
2357
2358 19 static gate_bool_t is_char_float_valid(char c, gate_bool_t is_first, gate_bool_t dot_allowed)
2359 {
2360
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (is_first)
2361 {
2362
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))
2363 {
2364 4 return true;
2365 }
2366 }
2367
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 == '.'));
2368 }
2369
2370 1 gate_size_t gate_stream_scan_real(gate_stream_t* stream, gate_real64_t* out_num)
2371 {
2372 char buffer[128];
2373 1 gate_size_t buffer_used = 0;
2374 gate_result_t result;
2375 1 gate_size_t returned = 0;
2376 1 gate_bool_t dot_allowed = true;
2377
2378
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 while(buffer_used < sizeof(buffer))
2379 {
2380 10 const gate_bool_t is_first = (buffer_used == 0);
2381 10 char c = 0;
2382 10 result = gate_stream_peek(stream, &c, 1, &returned);
2383
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))
2384 {
2385
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 9 times.
10 if (!is_char_float_valid(c, is_first, dot_allowed))
2386 {
2387 // non-int-char detected
2388 1 break;
2389 }
2390 }
2391 9 result = gate_stream_read(stream, &c, 1, &returned);
2392
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)
2393 {
2394 /* failed to read next char */
2395 break;
2396 }
2397
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (!is_char_float_valid(c, is_first, dot_allowed))
2398 {
2399 // non-int-char detected
2400 break;
2401 }
2402
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))
2403 {
2404 /* ignore leading whitespace chars */
2405 1 continue;
2406 }
2407
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (c == '.')
2408 {
2409
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (dot_allowed)
2410 {
2411 /* one dot is OK ...*/
2412 1 dot_allowed =false;
2413 }
2414 else
2415 {
2416 /* more dots are an error */
2417 break;
2418 }
2419 }
2420
2421 8 buffer[buffer_used] = c;
2422 8 ++buffer_used;
2423 }
2424 1 gate_str_parse_real(buffer, buffer_used, out_num);
2425 1 return buffer_used;
2426 }
2427 1 gate_size_t gate_stream_scan_string(gate_stream_t* stream, gate_string_t* out_text)
2428 {
2429 1 gate_size_t chars_processed = 0;
2430 1 gate_strbuilder_t builder = GATE_INIT_EMPTY;
2431
2432 1 gate_strbuilder_create(&builder, 0);
2433
2434 do
2435 6 {
2436 gate_result_t result;
2437 7 gate_size_t received = 0;
2438 7 char c = 0;
2439 7 result = gate_stream_read(stream, &c, 1, &received);
2440
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))
2441 {
2442 // stream error or end of stream
2443 break;
2444 }
2445 6 ++chars_processed;
2446
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
6 if (gate_char_is_whitespace(c))
2447 {
2448
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_strbuilder_length(&builder) == 0)
2449 {
2450 /* leading whitespaces are skipped */
2451 1 continue;
2452 }
2453 else
2454 {
2455 /* token completed */
2456 break;
2457 }
2458 }
2459 5 received = gate_strbuilder_append_chars(&builder, 1, c);
2460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (received == 0)
2461 {
2462 /* allocation error in strbuilder -> cancel */
2463 break;
2464 }
2465 } while(true);
2466
2467
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_strbuilder_to_string(&builder, out_text))
2468 {
2469 // string creating failed -> clear it
2470 gate_string_create_empty(out_text);
2471 }
2472
2473 1 return chars_processed;
2474 }
2475
2476
2477
2478
2479 40246 gate_result_t gate_stream_transfer_buffer(gate_stream_t* src, gate_stream_t* dst, char* buffer, gate_size_t buffersize)
2480 {
2481 gate_size_t bytes_read;
2482 gate_size_t bytes_written;
2483 gate_result_t result;
2484 for (;;)
2485 {
2486 40246 result = gate_stream_read(src, buffer, buffersize, &bytes_read);
2487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40246 times.
40246 if (GATE_FAILED(result))
2488 {
2489 break;
2490 }
2491
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 40191 times.
40246 if (bytes_read == 0)
2492 {
2493 /* end of stream reached */
2494 55 break;
2495 }
2496 40191 result = gate_stream_write_block(dst, buffer, bytes_read, &bytes_written);
2497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40191 times.
40191 if (GATE_FAILED(result))
2498 {
2499 break;
2500 }
2501 }
2502 55 return result;
2503 }
2504
2505 9 gate_result_t gate_stream_transfer_limit(gate_stream_t* src, gate_uint64_t limit, gate_stream_t* dst, gate_uint64_t* transferred)
2506 {
2507 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
2508 static gate_size_t const buffer_size = sizeof(buffer);
2509 gate_size_t next_size;
2510 gate_size_t bytes_read;
2511 gate_size_t bytes_written;
2512 9 gate_result_t result = GATE_RESULT_OK;
2513 9 gate_uint64_t counter = 0;
2514
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 while (limit > 0)
2515 {
2516 10 next_size = (limit > buffer_size) ? buffer_size : (gate_size_t)limit;
2517 10 result = gate_stream_read(src, buffer, next_size, &bytes_read);
2518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (GATE_FAILED(result))
2519 {
2520 break;
2521 }
2522
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (bytes_read == 0)
2523 {
2524 /* end of stream reached */
2525 2 break;
2526 }
2527
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_DEBUG_ASSERT(limit >= bytes_read);
2528 8 limit -= bytes_read;
2529 8 result = gate_stream_write_block(dst, buffer, bytes_read, &bytes_written);
2530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (GATE_FAILED(result))
2531 {
2532 break;
2533 }
2534
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_DEBUG_ASSERT(bytes_read == bytes_written);
2535 8 counter += bytes_written;
2536 }
2537
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (transferred)
2538 {
2539 9 *transferred = counter;
2540 }
2541 9 return result;
2542 }
2543
2544
2545 44 gate_result_t gate_stream_transfer(gate_stream_t* src, gate_stream_t* dst)
2546 {
2547 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
2548 44 return gate_stream_transfer_buffer(src, dst, buffer, sizeof(buffer));
2549 }
2550
2551 5 gate_result_t gate_stream_skip(gate_stream_t* src, gate_uint64_t count, gate_uint64_t* bytes_skipped)
2552 {
2553 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
2554 gate_size_t nextlen;
2555 5 gate_size_t returned = 1;
2556 5 gate_result_t result = GATE_RESULT_OK;
2557 5 gate_uint64_t actual_skipped = 0;
2558
2559
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))
2560 {
2561 5 nextlen = (count > GATE_MAX_COPYBUFFER_LENGTH) ? GATE_MAX_COPYBUFFER_LENGTH : (gate_size_t)count;
2562 5 result = gate_stream_read_block(src, buffer, nextlen, &returned);
2563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 GATE_BREAK_IF_FAILED(result);
2564
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 GATE_DEBUG_ASSERT(returned <= nextlen);
2565 5 actual_skipped += returned;
2566 5 count -= returned;
2567 }
2568
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (bytes_skipped)
2569 {
2570 2 *bytes_skipped = actual_skipped;
2571 }
2572 5 return result;
2573 }
2574
2575