GCC Code Coverage Report


Directory: src/gate/
File: src/gate/streams.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 599 1048 57.2%
Functions: 75 118 63.6%
Branches: 165 383 43.1%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/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
37 #include <stdarg.h>
38
39 #if defined(GATE_SYS_WIN)
40 # define GATE_CORE_STREAMS_WINAPI 1
41 #elif defined(GATE_SYS_DOS)
42 # define GATE_CORE_STREAMS_POSIX 1
43 #elif defined(GATE_SYS_POSIX)
44 # define GATE_CORE_STREAMS_POSIX 1
45 #endif
46
47
48
49 /********************************
50 * memory stream implementation *
51 ********************************/
52
53 static void gate_memstream_release_impl(void* self);
54 static int gate_memstream_retain_impl(void* self);
55 static char const* gate_memstream_interface_name_impl(void* self);
56 static gate_result_t gate_memstream_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
57 static gate_result_t gate_memstream_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned);
58 static gate_result_t gate_memstream_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
59 static gate_result_t gate_memstream_flush_impl(void* self);
60 static gate_result_t gate_memstream_reserve_impl(void* self, gate_size_t space);
61 static gate_size_t gate_memstream_size_impl(void* self);
62 static gate_result_t gate_memstream_fill_impl(void* self, char fillitem, gate_size_t fillsize);
63 static gate_size_t gate_memstream_discard_impl(void* self, gate_size_t bytestodiscard);
64 static gate_size_t gate_memstream_discard_back_impl(void* self, gate_size_t bytestodiscard);
65 static char const* gate_memstream_get_data_impl(void* self);
66 static gate_result_t gate_memstream_reset_impl(void* self);
67
68
69 static void gate_memstream_release_static_impl(void* self);
70 static int gate_memstream_retain_static_impl(void* self);
71 static gate_result_t gate_memstream_write_static_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
72 static gate_result_t gate_memstream_reserve_static_impl(void* self, gate_size_t space);
73 static gate_result_t gate_memstream_fill_static_impl(void* self, char fillitem, gate_size_t fillsize);
74 static gate_result_t gate_memstream_write_disabled_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written);
75 static gate_result_t gate_memstream_reserve_disabled_impl(void* self, gate_size_t space);
76 static gate_result_t gate_memstream_fill_disabled_impl(void* self, char fillitem, gate_size_t fillsize);
77
78 static void gate_memstream_release_static_unmanaged_impl(void* self);
79
80 static GATE_INTERFACE_VTBL(gate_memstream) gate_memstream_static_unmanaged_readonly_vtbl;
81
82 4 static void gate_init_memstream_static_unmanaged_readonly_vtbl()
83 {
84
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (!gate_memstream_static_unmanaged_readonly_vtbl.get_interface_name)
85 {
86 GATE_INTERFACE_VTBL(gate_memstream) const local_vtbl =
87 {
88 &gate_memstream_interface_name_impl,
89 &gate_memstream_release_static_unmanaged_impl,
90 &gate_memstream_retain_static_impl,
91
92 &gate_memstream_read_impl,
93 &gate_memstream_peek_impl,
94 &gate_memstream_write_disabled_impl,
95 &gate_memstream_flush_impl,
96
97 &gate_memstream_get_data_impl,
98 &gate_memstream_size_impl,
99 &gate_memstream_reserve_disabled_impl,
100 &gate_memstream_fill_disabled_impl,
101 &gate_memstream_discard_impl,
102 &gate_memstream_discard_back_impl,
103 &gate_memstream_reset_impl
104 };
105 2 gate_memstream_static_unmanaged_readonly_vtbl = local_vtbl;
106 }
107 4 }
108
109
110
111 40 static void gate_memstream_release_impl(void* self)
112 {
113 40 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
114
2/2
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 6 times.
40 if (gate_atomic_int_dec(&strm->ref_counter) == 0)
115 {
116 /* release memstream */
117
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if (strm->priv_membuffer != NULL)
118 {
119 34 gate_mem_dealloc(strm->priv_membuffer);
120 34 strm->priv_membuffer = NULL;
121 }
122 34 gate_mem_dealloc(strm);
123 }
124 40 }
125 6 static int gate_memstream_retain_impl(void* self)
126 {
127 6 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
128 6 return gate_atomic_int_inc(&strm->ref_counter);
129 }
130 6 static char const* gate_memstream_interface_name_impl(void* self)
131 {
132 (void)self;
133 6 return GATE_INTERFACE_NAME_MEMSTREAM;
134 }
135
136 6358 gate_result_t gate_memstream_read_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
137 {
138 6358 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
139
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 6326 times.
6358 if (bufferlength > strm->priv_memlength)
140 {
141 32 bufferlength = strm->priv_memlength;
142 }
143
2/2
✓ Branch 0 taken 6337 times.
✓ Branch 1 taken 21 times.
6358 if (bufferlength != 0)
144 {
145 6337 gate_mem_copy(buffer, &strm->priv_membuffer[strm->priv_memoffset], bufferlength);
146 6337 strm->priv_memlength -= bufferlength;
147
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 6313 times.
6337 if (strm->priv_memlength == 0)
148 {
149 24 strm->priv_memoffset = 0;
150 }
151 else
152 {
153 6313 strm->priv_memoffset += bufferlength;
154 }
155 }
156
1/2
✓ Branch 0 taken 6358 times.
✗ Branch 1 not taken.
6358 if (returned != NULL)
157 {
158 6358 *returned = bufferlength;
159 }
160 6358 return GATE_RESULT_OK;
161 }
162 301 gate_result_t gate_memstream_peek_impl(void* self, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
163 {
164 301 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
165
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 300 times.
301 if (bufferlength > strm->priv_memlength)
166 {
167 1 bufferlength = strm->priv_memlength;
168 }
169
2/2
✓ Branch 0 taken 300 times.
✓ Branch 1 taken 1 times.
301 if (bufferlength != 0)
170 {
171 300 gate_mem_copy(buffer, strm->priv_membuffer, bufferlength);
172 }
173
1/2
✓ Branch 0 taken 301 times.
✗ Branch 1 not taken.
301 if (returned != NULL)
174 {
175 301 *returned = bufferlength;
176 }
177 301 return GATE_RESULT_OK;
178 }
179 5091 gate_result_t gate_memstream_write_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
180 {
181 5091 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
182 5091 gate_result_t result = strm->vtbl->reserve(strm, bufferlength);
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5091 times.
5091 if (GATE_FAILED(result))
184 {
185 return result;
186 }
187
188 5091 gate_mem_copy(&strm->priv_membuffer[strm->priv_memoffset + strm->priv_memlength], buffer, bufferlength);
189 5091 strm->priv_memlength += bufferlength;
190
191
1/2
✓ Branch 0 taken 5091 times.
✗ Branch 1 not taken.
5091 if (written != NULL)
192 {
193 5091 *written = bufferlength;
194 }
195 5091 return GATE_RESULT_OK;
196 }
197 304 gate_result_t gate_memstream_flush_impl(void* self)
198 {
199 (void)self;
200 304 return GATE_RESULT_OK;
201 }
202 5109 static gate_result_t gate_memstream_reserve_impl(void* self, gate_size_t space)
203 {
204 5109 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
205 5109 gate_size_t unusedspace = strm->priv_memcapacity - strm->priv_memlength;
206 5109 gate_size_t freespace = unusedspace - strm->priv_memoffset;
207
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 5007 times.
5109 if (space > freespace)
208 {
209
1/2
✓ Branch 0 taken 102 times.
✗ Branch 1 not taken.
102 if (space > unusedspace)
210 {
211 /* reallocation is required */
212 102 gate_size_t newcapacity = (strm->priv_memcapacity + space) + (strm->priv_memcapacity / 2);
213 102 char* newbuffer = (char*)gate_mem_alloc(newcapacity);
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102 times.
102 if (newbuffer == NULL)
215 {
216 return GATE_RESULT_OUTOFMEMORY;
217 }
218
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 36 times.
102 if (strm->priv_memlength != 0)
219 {
220 66 gate_mem_copy(&newbuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
221 }
222
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 34 times.
102 if (strm->priv_membuffer != NULL)
223 {
224 68 gate_mem_dealloc(strm->priv_membuffer);
225 }
226 102 strm->priv_membuffer = newbuffer;
227 102 strm->priv_memoffset = 0;
228 102 strm->priv_memcapacity = newcapacity;
229 }
230 else
231 {
232 /* moving bytes to origin of buffer */
233 gate_mem_copy(&strm->priv_membuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
234 strm->priv_memoffset = 0;
235 }
236 }
237 5109 return GATE_RESULT_OK;
238 }
239 22 static gate_size_t gate_memstream_size_impl(void* self)
240 {
241 22 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
242 22 return strm->priv_memlength;
243 }
244 1 static gate_result_t gate_memstream_fill_impl(void* self, char fillitem, gate_size_t fillsize)
245 {
246 1 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
247 gate_size_t ndx;
248 char* ptr;
249 1 gate_result_t result = strm->vtbl->reserve(strm, fillsize);
250
251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
252 {
253 return result;
254 }
255
256 1 ptr = &strm->priv_membuffer[strm->priv_memoffset + strm->priv_memlength];
257
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 for (ndx = 0; ndx < fillsize; ++ndx, ++ptr)
258 {
259 5 *ptr = fillitem;
260 }
261 1 strm->priv_memlength += fillsize;
262 1 return GATE_RESULT_OK;
263 }
264 3 static gate_size_t gate_memstream_discard_impl(void* self, gate_size_t bytestodiscard)
265 {
266 3 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
267 gate_size_t ret;
268
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (bytestodiscard >= strm->priv_memlength)
269 {
270 1 ret = strm->priv_memlength;
271 1 strm->priv_memoffset = 0;
272 1 strm->priv_memlength = 0;
273 }
274 else
275 {
276 2 ret = bytestodiscard;
277 2 strm->priv_memoffset += bytestodiscard;
278 2 strm->priv_memlength -= bytestodiscard;
279 }
280 3 return ret;
281 }
282 1 static gate_size_t gate_memstream_discard_back_impl(void* self, gate_size_t bytestodiscard)
283 {
284 1 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
285 gate_size_t ret;
286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (bytestodiscard >= strm->priv_memlength)
287 {
288 ret = strm->priv_memlength;
289 strm->priv_memoffset = 0;
290 strm->priv_memlength = 0;
291 }
292 else
293 {
294 1 ret = bytestodiscard;
295 1 strm->priv_memlength -= bytestodiscard;
296 }
297 1 return ret;
298 }
299 17 static char const* gate_memstream_get_data_impl(void* self)
300 {
301 17 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
302 17 return &strm->priv_membuffer[strm->priv_memoffset];
303 }
304
305 static gate_result_t gate_memstream_reset_impl(void* self)
306 {
307 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
308 strm->priv_memoffset = 0;
309 strm->priv_memlength = 0;
310 return GATE_RESULT_OK;
311 }
312
313 static GATE_INTERFACE_VTBL(gate_memstream) gate_memstream_vtbl;
314
315 34 void gate_init_memstream_vtbl()
316 {
317
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 28 times.
34 if (!gate_memstream_vtbl.get_interface_name)
318 {
319 GATE_INTERFACE_VTBL(gate_memstream) const local_vtbl =
320 {
321 &gate_memstream_interface_name_impl,
322 &gate_memstream_release_impl,
323 &gate_memstream_retain_impl,
324
325 &gate_memstream_read_impl,
326 &gate_memstream_peek_impl,
327 &gate_memstream_write_impl,
328 &gate_memstream_flush_impl,
329
330 &gate_memstream_get_data_impl,
331 &gate_memstream_size_impl,
332 &gate_memstream_reserve_impl,
333 &gate_memstream_fill_impl,
334 &gate_memstream_discard_impl,
335 &gate_memstream_discard_back_impl,
336 &gate_memstream_reset_impl
337 };
338 6 gate_memstream_vtbl = local_vtbl;
339 }
340 34 }
341
342 34 gate_memstream_t* gate_memstream_create(gate_size_t capacity)
343 {
344 gate_result_t result;
345 34 gate_memstream_impl_t* ret = (gate_memstream_impl_t*)gate_mem_alloc(sizeof(gate_memstream_impl_t));
346
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if (ret != NULL)
347 {
348 34 gate_init_memstream_vtbl();
349 34 ret->vtbl = &gate_memstream_vtbl;
350 34 gate_atomic_int_set(&ret->ref_counter, 1);
351 34 ret->priv_membuffer = NULL;
352 34 ret->priv_memcapacity = 0;
353 34 ret->priv_memoffset = 0;
354 34 ret->priv_memlength = 0;
355
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 17 times.
34 if (capacity > 0)
356 {
357 17 result = ret->vtbl->reserve(ret, capacity);
358 (void)result;
359 }
360
361 }
362 34 return (gate_memstream_t*)ret;
363 }
364
365
366 1 static void gate_memstream_release_static_impl(void* self)
367 {
368 1 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
369
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (0 == gate_atomic_int_dec(&strm->ref_counter))
370 {
371 1 gate_mem_dealloc(self);
372 }
373 1 }
374 1 static int gate_memstream_retain_static_impl(void* self)
375 {
376 1 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
377 1 return (int)gate_atomic_int_inc(&strm->ref_counter);
378 }
379 228 static gate_result_t gate_memstream_write_static_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
380 {
381 228 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
382 228 gate_result_t ret = GATE_RESULT_OK;
383 gate_size_t avail;
384
1/2
✓ Branch 0 taken 228 times.
✗ Branch 1 not taken.
228 if (bufferlength > 0)
385 {
386 228 avail = strm->priv_memcapacity - strm->priv_memlength;
387
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
228 if (bufferlength > avail)
388 {
389 if (bufferlength < strm->priv_memcapacity)
390 {
391 avail = strm->priv_memcapacity - bufferlength;
392 if (avail > strm->priv_memlength) avail = strm->priv_memlength;
393 gate_mem_copy(
394 &strm->priv_membuffer[0],
395 &strm->priv_membuffer[strm->priv_memoffset + strm->priv_memlength - avail],
396 avail);
397 strm->priv_memoffset = 0;
398 strm->priv_memlength = avail;
399 gate_mem_copy(&strm->priv_membuffer[strm->priv_memlength], buffer, bufferlength);
400 strm->priv_memlength += bufferlength;
401 }
402 else
403 {
404 gate_mem_copy(
405 &strm->priv_membuffer[0],
406 &buffer[bufferlength - strm->priv_memcapacity],
407 strm->priv_memcapacity);
408 strm->priv_memoffset = 0;
409 strm->priv_memlength = strm->priv_memcapacity;
410 }
411 }
412 else
413 {
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
228 if (strm->priv_memoffset != 0)
415 {
416 gate_mem_copy(&strm->priv_membuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
417 strm->priv_memoffset = 0;
418 }
419 228 gate_mem_copy(&strm->priv_membuffer[strm->priv_memlength], buffer, bufferlength);
420 228 strm->priv_memlength += bufferlength;
421 }
422 }
423
1/2
✓ Branch 0 taken 228 times.
✗ Branch 1 not taken.
228 if (written != NULL) *written = bufferlength;
424 228 return ret;
425 }
426 static gate_result_t gate_memstream_write_disabled_impl(void* self, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
427 {
428 (void)self;
429 (void)buffer;
430 (void)bufferlength;
431 (void)written;
432 return GATE_RESULT_NOTSUPPORTED;
433 }
434 static gate_result_t gate_memstream_reserve_disabled_impl(void* self, gate_size_t space)
435 {
436 (void)self;
437 (void)space;
438 return GATE_RESULT_NOTSUPPORTED;
439 }
440 static gate_result_t gate_memstream_fill_disabled_impl(void* self, char fillitem, gate_size_t fillsize)
441 {
442 (void)self;
443 (void)fillitem;
444 (void)fillsize;
445 return GATE_RESULT_NOTSUPPORTED;
446 }
447
448 static gate_result_t gate_memstream_reserve_static_impl(void* self, gate_size_t space)
449 {
450 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
451 if (strm->priv_memoffset != 0)
452 {
453 gate_mem_copy(&strm->priv_membuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
454 strm->priv_memoffset = 0;
455 }
456 return (space > strm->priv_memcapacity) ? GATE_RESULT_OUTOFMEMORY : GATE_RESULT_OK;
457 }
458 static gate_result_t gate_memstream_fill_static_impl(void* self, char fillitem, gate_size_t fillsize)
459 {
460 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
461 gate_result_t ret = GATE_RESULT_OK;
462 gate_size_t avail;
463 char* ptr;
464 gate_size_t index;
465 gate_size_t preserve;
466 if (fillsize != 0)
467 {
468 if (strm->priv_memoffset != 0)
469 {
470 gate_mem_copy(&strm->priv_membuffer[0], &strm->priv_membuffer[strm->priv_memoffset], strm->priv_memlength);
471 strm->priv_memoffset = 0;
472 }
473 avail = strm->priv_memcapacity - strm->priv_memlength;
474 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 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 ptr = &strm->priv_membuffer[strm->priv_memoffset + strm->priv_memlength];
495 }
496 for (index = 0; index != fillsize; ++index)
497 {
498 *ptr = fillitem;
499 ++ptr;
500 }
501 strm->priv_memlength += fillsize;
502 }
503 return ret;
504 }
505
506
507 4 static void gate_memstream_release_static_unmanaged_impl(void* self)
508 {
509 4 gate_memstream_impl_t* strm = (gate_memstream_impl_t*)self;
510 4 if (0 == gate_atomic_int_dec(&strm->ref_counter))
511 {
512 /* do nothing */
513 }
514 4 }
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 1 void gate_init_memstream_static_vtbl()
559 {
560
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 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 1 }
584
585 1 gate_memstream_t* gate_memstream_create_static(void* buffer, gate_size_t capacity, gate_size_t used)
586 {
587 1 gate_memstream_impl_t* impl = (gate_memstream_impl_t*)gate_mem_alloc(sizeof(gate_memstream_impl_t));
588
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (impl != NULL)
589 {
590 1 gate_init_memstream_static_vtbl();
591 1 impl->vtbl = &gate_memstream_static_vtbl;
592 1 gate_atomic_int_init(&impl->ref_counter, 1);
593 1 impl->priv_memoffset = 0;
594 1 impl->priv_membuffer = (char*)buffer;
595 1 impl->priv_memcapacity = capacity;
596 1 impl->priv_memlength = used;
597 }
598 1 return (gate_memstream_t*)impl;
599 }
600
601 4 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 4 gate_init_memstream_static_unmanaged_readonly_vtbl();
604 4 impl->vtbl = &gate_memstream_static_unmanaged_readonly_vtbl;
605 4 gate_atomic_int_init(&impl->ref_counter, 1);
606 4 impl->priv_memoffset = 0;
607 4 impl->priv_membuffer = (char*)buffer;
608 4 impl->priv_memcapacity = capacity;
609 4 impl->priv_memlength = used;
610 4 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 static void memview_destroy(memview_t* self)
632 {
633 if (self->ptr_container)
634 {
635 gate_object_release(self->ptr_container);
636 }
637 gate_mem_dealloc(self);
638 }
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 static void memview_release(void* obj)
646 {
647 memview_t* const self = (memview_t*)obj;
648 if (0 == gate_atomic_int_dec(&self->ref_counter))
649 {
650 memview_destroy(self);
651 }
652 }
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 static gate_result_t memview_peek(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
660 {
661 memview_t* const self = (memview_t*)obj;
662 gate_result_t result = GATE_RESULT_FAILED;
663 gate_size_t copied = 0;
664 gate_size_t available;
665
666 do
667 {
668 if (!buffer || !obj)
669 {
670 result = GATE_RESULT_NULLPOINTER;
671 break;
672 }
673
674 available = self->buffer_len - self->buffer_offset;
675
676 if (self->closed || (available == 0))
677 {
678 /* react as end of stream */
679 result = GATE_RESULT_OK;
680 break;
681 }
682
683 copied = (bufferlength > available) ? available : bufferlength;
684 gate_mem_copy(buffer, &self->ptr_buffer[self->buffer_offset], copied);
685 result = GATE_RESULT_OK;
686 } while (0);
687
688 if (returned)
689 {
690 *returned = copied;
691 }
692
693 return result;
694 }
695
696 static gate_result_t memview_read(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
697 {
698 memview_t* const self = (memview_t*)obj;
699 gate_result_t result = GATE_RESULT_FAILED;
700 gate_size_t copied = 0;
701
702 result = memview_peek(obj, buffer, bufferlength, &copied);
703 if (GATE_SUCCEEDED(result))
704 {
705 self->buffer_offset += copied;
706 if (self->buffer_offset > self->buffer_len)
707 {
708 self->buffer_offset = self->buffer_len;
709 }
710 }
711
712 if (returned)
713 {
714 *returned = copied;
715 }
716
717 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 static gate_result_t memview_get_resource(void* obj, gate_enumint_t resource_type, gate_uintptr_t* resource)
735 {
736 memview_t* const self = (memview_t*)obj;
737 switch (resource_type)
738 {
739 case GATE_STREAM_RESOURCE_INPUT:
740 case GATE_STREAM_RESOURCE_DEFAULT:
741 if (resource)
742 {
743 *resource = (gate_uintptr_t)self->ptr_buffer;
744 }
745 return GATE_RESULT_OK;
746 default:
747 {
748 return GATE_RESULT_NOTAVAILABLE;
749 }
750 }
751 }
752
753 static gate_result_t memview_can_read(void* obj, gate_bool_t* return_value)
754 {
755 memview_t* const self = (memview_t*)obj;
756 if (return_value)
757 {
758 *return_value = !self->closed;
759 }
760 return GATE_RESULT_OK;
761 }
762 static gate_result_t memview_can_write(void* obj, gate_bool_t* return_value)
763 {
764 GATE_UNUSED_ARG(obj);
765 if (return_value)
766 {
767 *return_value = false;
768 }
769 return GATE_RESULT_OK;
770 }
771 static gate_result_t memview_get_size(void* obj, gate_int64_t* return_value)
772 {
773 memview_t* const self = (memview_t*)obj;
774 if (return_value)
775 {
776 *return_value = self->buffer_len;
777 }
778 return GATE_RESULT_OK;
779 }
780 static gate_result_t memview_get_available(void* obj, gate_int64_t* return_value)
781 {
782 memview_t* const self = (memview_t*)obj;
783 if (return_value)
784 {
785 *return_value = self->closed ? 0 : (gate_int64_t)(self->buffer_len - self->buffer_offset);
786 }
787 return GATE_RESULT_OK;
788 }
789 static gate_result_t memview_seek(void* obj, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position)
790 {
791 memview_t* const self = (memview_t*)obj;
792 gate_result_t result = GATE_RESULT_FAILED;
793 gate_size_t shift;
794
795 if (self->closed)
796 {
797 return GATE_RESULT_NOTAVAILABLE;
798 }
799
800 switch (origin)
801 {
802 case GATE_STREAM_SEEK_BEGIN:
803 {
804 if (position < 0)
805 {
806 result = GATE_RESULT_INVALIDARG;
807 break;
808 }
809 if (position > (gate_int64_t)self->buffer_len)
810 {
811 result = GATE_RESULT_NOTSUPPORTED;
812 break;
813 }
814 self->buffer_offset = (gate_size_t)(gate_uint64_t)position;
815 result = GATE_RESULT_OK;
816 break;
817 }
818 case GATE_STREAM_SEEK_CURRENT:
819 {
820 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 shift = (gate_size_t)(gate_uint64_t)position;
833 if (self->buffer_offset + shift > self->buffer_len)
834 {
835 result = GATE_RESULT_NOTSUPPORTED;
836 break;
837 }
838 self->buffer_offset += shift;
839 }
840 result = GATE_RESULT_OK;
841 break;
842 }
843 case GATE_STREAM_SEEK_END:
844 {
845 if (position > 0)
846 {
847 result = GATE_RESULT_NOTSUPPORTED;
848 break;
849 }
850 shift = (gate_size_t)(-position);
851 if (shift > self->buffer_len)
852 {
853 result = GATE_RESULT_INVALIDARG;
854 break;
855 }
856 self->buffer_offset = self->buffer_len - shift;
857 result = GATE_RESULT_OK;
858 break;
859 }
860 default:
861 {
862 result = GATE_RESULT_INVALIDARG;
863 break;
864 }
865 }
866
867 if (final_position)
868 {
869 *final_position = (gate_int64_t)(gate_uint64_t)self->buffer_offset;
870 }
871 return result;
872 }
873 static gate_result_t memview_reset(void* obj)
874 {
875 memview_t* const self = (memview_t*)obj;
876 self->buffer_offset = 0;
877 return GATE_RESULT_OK;
878 }
879 static gate_result_t memview_close(void* obj, gate_enumint_t close_type)
880 {
881 memview_t* const self = (memview_t*)obj;
882 switch (close_type)
883 {
884 case GATE_STREAM_CLOSE_DEFAULT:
885 case GATE_STREAM_CLOSE_INPUT:
886 self->closed = true;
887 return GATE_RESULT_OK;
888 default:
889 return GATE_RESULT_NOTSUPPORTED;
890 }
891 }
892
893 static GATE_INTERFACE_VTBL(gate_controlstream) memview_vtbl;
894
895 static void init_memview_vtbl()
896 {
897 if (memview_vtbl.get_interface_name == NULL)
898 {
899 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 memview_vtbl = local_vtbl;
921 }
922 }
923
924 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 gate_controlstream_t* ret = NULL;
927 memview_t* newstrm = NULL;
928
929 do
930 {
931 newstrm = (memview_t*)gate_mem_alloc(sizeof(memview_t));
932 if (!newstrm)
933 {
934 break;
935 }
936 gate_mem_clear(newstrm, sizeof(memview_t));
937 init_memview_vtbl();
938 newstrm->vtbl = &memview_vtbl;
939 gate_atomic_int_init(&newstrm->ref_counter, 1);
940 newstrm->closed = false;
941 newstrm->ptr_buffer = (char const*)buffer;
942 newstrm->buffer_len = length;
943 newstrm->buffer_offset = (offset > length) ? length : offset;
944 newstrm->ptr_container = ptr_container;
945 if (newstrm->ptr_container)
946 {
947 gate_object_retain(newstrm->ptr_container);
948 }
949 /* success case */
950 ret = (gate_controlstream_t*)newstrm;
951 newstrm = NULL;
952 } while (0);
953
954 if (newstrm)
955 {
956 memview_destroy(newstrm);
957 }
958 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 7 static void memfile_destroy(memfile_t* self)
978 {
979 7 gate_arraylist_release(self->storage);
980 7 gate_mem_dealloc(self);
981 7 }
982
983 10 static char const* memfile_get_interface_name(void* obj)
984 {
985 GATE_UNUSED_ARG(obj);
986 10 return GATE_INTERFACE_NAME_MEMFILE;
987 }
988 11 static void memfile_release(void* obj)
989 {
990 11 memfile_t* const self = (memfile_t*)obj;
991
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 4 times.
11 if (0 == gate_atomic_int_dec(&self->ref_counter))
992 {
993 7 memfile_destroy(self);
994 }
995 11 }
996 4 static int memfile_retain(void* obj)
997 {
998 4 memfile_t* const self = (memfile_t*)obj;
999 4 return (int)gate_atomic_int_inc(&self->ref_counter);
1000 }
1001
1002 505 static gate_result_t memfile_peek(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1003 {
1004 505 memfile_t* const self = (memfile_t*)obj;
1005 505 gate_result_t result = GATE_RESULT_FAILED;
1006 505 gate_size_t copied = 0;
1007 gate_size_t available;
1008 gate_size_t storage_length;
1009 505 char const* ptr_storage_data = NULL;
1010
1011 do
1012 {
1013
2/4
✓ Branch 0 taken 505 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 505 times.
505 if (!buffer || !obj)
1014 {
1015 result = GATE_RESULT_NULLPOINTER;
1016 break;
1017 }
1018
1019 505 storage_length = gate_arraylist_length(self->storage);
1020 505 GATE_DEBUG_ASSERT(self->storage_offset <= storage_length);
1021 505 available = storage_length - self->storage_offset;
1022
1023
3/4
✓ Branch 0 taken 505 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 503 times.
505 if (self->closed || (available == 0))
1024 {
1025 /* react as end of stream */
1026 2 result = GATE_RESULT_OK;
1027 2 break;
1028 }
1029
1030 503 ptr_storage_data = (char const*)gate_arraylist_get(self->storage, self->storage_offset);
1031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 503 times.
503 if (!ptr_storage_data)
1032 {
1033 result = GATE_RESULT_NOTAVAILABLE;
1034 break;
1035 }
1036 503 copied = (bufferlength > available) ? available : bufferlength;
1037 503 gate_mem_copy(buffer, ptr_storage_data, copied);
1038 503 result = GATE_RESULT_OK;
1039 } while (0);
1040
1041
1/2
✓ Branch 0 taken 505 times.
✗ Branch 1 not taken.
505 if (returned)
1042 {
1043 505 *returned = copied;
1044 }
1045
1046 505 return result;
1047 }
1048
1049 405 static gate_result_t memfile_read(void* obj, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1050 {
1051 405 memfile_t* const self = (memfile_t*)obj;
1052 405 gate_result_t result = GATE_RESULT_FAILED;
1053 405 gate_size_t copied = 0;
1054
1055 405 result = memfile_peek(obj, buffer, bufferlength, &copied);
1056
1/2
✓ Branch 0 taken 405 times.
✗ Branch 1 not taken.
405 if (GATE_SUCCEEDED(result))
1057 {
1058 405 self->storage_offset += copied;
1059 }
1060
1061
1/2
✓ Branch 0 taken 405 times.
✗ Branch 1 not taken.
405 if (returned)
1062 {
1063 405 *returned = copied;
1064 }
1065
1066 405 return result;
1067 }
1068
1069 154 static gate_result_t memfile_write(void* obj, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1070 {
1071 154 memfile_t* const self = (memfile_t*)obj;
1072 154 gate_result_t ret = GATE_RESULT_FAILED;
1073 154 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 154 storage_length = gate_arraylist_length(self->storage);
1081 154 GATE_DEBUG_ASSERT(self->storage_offset <= storage_length);
1082 154 available = storage_length - self->storage_offset;
1083
1084
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 148 times.
154 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 148 times.
✓ Branch 1 taken 6 times.
154 if (bufferlength > 0)
1099 {
1100
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 148 times.
148 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 148 self->storage_offset += bufferlength;
1106 148 stored_bytes += bufferlength;
1107 }
1108 154 ret = GATE_RESULT_OK;
1109 } while (0);
1110
1111
1/2
✓ Branch 0 taken 154 times.
✗ Branch 1 not taken.
154 if (written)
1112 {
1113 154 *written = stored_bytes;
1114 }
1115 154 return ret;
1116 }
1117 102 static gate_result_t memfile_flush(void* obj)
1118 {
1119 GATE_UNUSED_ARG(obj);
1120 102 return GATE_RESULT_OK;
1121 }
1122
1123 static gate_result_t memfile_get_resource(void* obj, gate_enumint_t resource_type, gate_uintptr_t* resource)
1124 {
1125 memfile_t* const self = (memfile_t*)obj;
1126 switch (resource_type)
1127 {
1128 case GATE_STREAM_RESOURCE_INPUT:
1129 case GATE_STREAM_RESOURCE_OUTPUT:
1130 case GATE_STREAM_RESOURCE_DEFAULT:
1131 if (resource)
1132 {
1133 *resource = (gate_uintptr_t)gate_arraylist_get(self->storage, 0);
1134 }
1135 return GATE_RESULT_OK;
1136 default:
1137 {
1138 return GATE_RESULT_NOTAVAILABLE;
1139 }
1140 }
1141 }
1142 1 static gate_result_t memfile_can_read(void* obj, gate_bool_t* return_value)
1143 {
1144 1 memfile_t* const self = (memfile_t*)obj;
1145
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (return_value)
1146 {
1147 1 *return_value = !self->closed;
1148 }
1149 1 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 1 static gate_result_t memfile_get_available(void* obj, gate_int64_t* return_value)
1170 {
1171 1 memfile_t* const self = (memfile_t*)obj;
1172
1173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (self->closed)
1174 {
1175 return GATE_RESULT_INVALIDSTATE;
1176 }
1177
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (return_value)
1178 {
1179 1 gate_size_t storage_length = gate_arraylist_length(self->storage);
1180 1 GATE_DEBUG_ASSERT(self->storage_offset <= storage_length);
1181 1 *return_value = (gate_int64_t)(storage_length - self->storage_offset);
1182 }
1183 1 return GATE_RESULT_OK;
1184 }
1185 55 static gate_result_t memfile_seek(void* obj, gate_int64_t position, gate_enumint_t origin, gate_int64_t* final_position)
1186 {
1187 55 memfile_t* const self = (memfile_t*)obj;
1188 55 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 55 times.
55 if (self->closed)
1193 {
1194 return GATE_RESULT_NOTAVAILABLE;
1195 }
1196
1197 55 storage_length = gate_arraylist_length(self->storage);
1198
1199
3/4
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
55 switch (origin)
1200 {
1201 37 case GATE_STREAM_SEEK_BEGIN:
1202 {
1203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (position < 0)
1204 {
1205 result = GATE_RESULT_INVALIDARG;
1206 break;
1207 }
1208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if (position > (gate_int64_t)storage_length)
1209 {
1210 result = GATE_RESULT_NOTSUPPORTED;
1211 break;
1212 }
1213 37 self->storage_offset = (gate_size_t)(gate_uint64_t)position;
1214 37 result = GATE_RESULT_OK;
1215 37 break;
1216 }
1217 12 case GATE_STREAM_SEEK_CURRENT:
1218 {
1219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 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 12 shift = (gate_size_t)(gate_uint64_t)position;
1232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (self->storage_offset + shift > storage_length)
1233 {
1234 result = GATE_RESULT_NOTSUPPORTED;
1235 break;
1236 }
1237 12 self->storage_offset += shift;
1238 }
1239 12 result = GATE_RESULT_OK;
1240 12 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 54 times.
✓ Branch 1 taken 1 times.
55 if (final_position)
1267 {
1268 54 *final_position = (gate_int64_t)(gate_uint64_t)self->storage_offset;
1269 }
1270 55 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 7 static void init_memfile_vtbl()
1296 {
1297
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 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 7 }
1323
1324 3 gate_controlstream_t* gate_memfilestream_create(gate_size_t prealloc)
1325 {
1326 3 gate_controlstream_t* ret = NULL;
1327 3 memfile_t* newstrm = NULL;
1328
1329 do
1330 {
1331 3 newstrm = (memfile_t*)gate_mem_alloc(sizeof(memfile_t));
1332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!newstrm)
1333 {
1334 break;
1335 }
1336 3 gate_mem_clear(newstrm, sizeof(memfile_t));
1337 3 init_memfile_vtbl();
1338 3 newstrm->vtbl = &memfile_vtbl;
1339 3 gate_atomic_int_init(&newstrm->ref_counter, 1);
1340 3 newstrm->storage = gate_arraylist_create(sizeof(char), NULL, prealloc, NULL, NULL);
1341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!newstrm->storage)
1342 {
1343 break;
1344 }
1345 3 newstrm->closed = false;
1346 3 newstrm->storage_offset = 0;
1347
1348 /* success case */
1349 3 ret = (gate_controlstream_t*)newstrm;
1350 3 newstrm = NULL;
1351 } while (0);
1352
1353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (newstrm)
1354 {
1355 memfile_destroy(newstrm);
1356 }
1357 3 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 62 static void gate_init_stringstream_vtbl()
1428 {
1429
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 56 times.
62 if (!gate_stringstream_vtbl.get_interface_name)
1430 {
1431 6 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 6 gate_stringstream_vtbl = local_vtbl;
1448 }
1449 62 }
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 62 gate_stringstream_t* gate_stringstream_create(gate_size_t capacity)
1462 {
1463 62 gate_stringstream_impl_t* ret = gate_mem_alloc(sizeof(gate_stringstream_impl_t));
1464
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if (ret != NULL)
1465 {
1466 62 gate_mem_clear(ret, sizeof(gate_stringstream_impl_t));
1467 62 gate_init_stringstream_vtbl();
1468 62 ret->vtbl = &gate_stringstream_vtbl;
1469 62 gate_atomic_int_init(&ret->ref_counter, 1);
1470 62 gate_strbuilder_create(&ret->str_builder, capacity);
1471 62 ret->ptr_builder = &ret->str_builder;
1472 }
1473 62 return (gate_stringstream_t*)ret;
1474 }
1475
1476 gate_stringstream_t* gate_stringstream_create_builder(gate_strbuilder_t* external_strbuilder)
1477 {
1478 gate_stringstream_impl_t* ret = gate_mem_alloc(sizeof(gate_stringstream_impl_t));
1479 if (ret != NULL)
1480 {
1481 gate_mem_clear(ret, sizeof(gate_stringstream_impl_t));
1482 gate_init_stringstream_vtbl();
1483 ret->vtbl = &gate_stringstream_vtbl;
1484 gate_atomic_int_init(&ret->ref_counter, 1);
1485 ret->ptr_builder = external_strbuilder;
1486 }
1487 return (gate_stringstream_t*)ret;
1488 }
1489
1490
1491 69 static void gate_stringstream_release_impl(void* ptr)
1492 {
1493 69 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1494
2/2
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 7 times.
69 if (gate_atomic_int_dec(&thisptr->ref_counter) == 0)
1495 {
1496
1/2
✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
62 if (&thisptr->str_builder == thisptr->ptr_builder)
1497 {
1498 62 gate_strbuilder_release(thisptr->ptr_builder);
1499 }
1500 62 gate_mem_dealloc(thisptr);
1501 }
1502 69 }
1503 7 static int gate_stringstream_retain_impl(void* ptr)
1504 {
1505 7 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1506 7 return (int)gate_atomic_int_inc(&thisptr->ref_counter);
1507 }
1508 4 static char const* gate_stringstream_get_interface_name_impl(void* ptr)
1509 {
1510 (void)ptr;
1511 4 return GATE_INTERFACE_NAME_STRINGSTREAM;
1512 }
1513 294 static gate_result_t gate_stringstream_read_impl(void* ptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1514 {
1515 294 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1516 294 gate_size_t bytesread = 0;
1517 294 gate_result_t result = gate_stringstream_peek_impl(ptr, buffer, bufferlength, &bytesread);
1518
1519
1/2
✓ Branch 0 taken 294 times.
✗ Branch 1 not taken.
294 if (GATE_SUCCEEDED(result))
1520 {
1521 294 gate_strbuilder_discard(thisptr->ptr_builder, bytesread);
1522
1/2
✓ Branch 0 taken 294 times.
✗ Branch 1 not taken.
294 if (returned != NULL)
1523 {
1524 294 *returned = bytesread;
1525 }
1526 }
1527 294 return result;
1528 }
1529 394 static gate_result_t gate_stringstream_peek_impl(void* ptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1530 {
1531 394 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1532 394 char const* dataptr = gate_strbuilder_ptr(thisptr->ptr_builder, 0);
1533 394 gate_size_t datalen = gate_strbuilder_length(thisptr->ptr_builder);
1534
2/4
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 394 times.
394 if ((bufferlength > 0) && (buffer == NULL))
1535 {
1536 return GATE_RESULT_INVALIDARG;
1537 }
1538
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 338 times.
394 if (bufferlength > datalen)
1539 {
1540 56 bufferlength = datalen;
1541 }
1542
2/2
✓ Branch 0 taken 362 times.
✓ Branch 1 taken 32 times.
394 if (bufferlength > 0)
1543 {
1544
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 362 times.
362 if (NULL == gate_mem_copy(buffer, dataptr, bufferlength))
1545 {
1546 return GATE_RESULT_FAILED;
1547 }
1548 }
1549
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 if (returned != NULL)
1550 {
1551 394 *returned = bufferlength;
1552 }
1553 394 return GATE_RESULT_OK;
1554 }
1555 252 static gate_result_t gate_stringstream_write_impl(void* ptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1556 {
1557 252 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1558 gate_size_t lenwritten;
1559 gate_result_t ret;
1560 252 lenwritten = gate_strbuilder_append_text(thisptr->ptr_builder, buffer, bufferlength);
1561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
252 ret = (lenwritten == 0) ? GATE_RESULT_FAILED : GATE_RESULT_OK;
1562
1563
1/2
✓ Branch 0 taken 252 times.
✗ Branch 1 not taken.
252 if (written != NULL)
1564 {
1565 252 *written = lenwritten;
1566 }
1567 252 return ret;
1568 }
1569 108 static gate_result_t gate_stringstream_flush_impl(void* ptr)
1570 {
1571 (void)ptr;
1572 108 return GATE_RESULT_OK;
1573 }
1574
1575 1 static char const* gate_stringstream_get_data_impl(void* ptr)
1576 {
1577 1 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1578 1 return gate_strbuilder_ptr(thisptr->ptr_builder, 0);
1579 }
1580 1 static gate_size_t gate_stringstream_size_impl(void* ptr)
1581 {
1582 1 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1583 1 return gate_strbuilder_length(thisptr->ptr_builder);
1584 }
1585 11 static gate_result_t gate_stringstream_get_current_view_impl(void* ptr, gate_string_t* ptr_output)
1586 {
1587 11 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1588
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 if (NULL != gate_string_create_static_len(ptr_output,
1589 11 gate_strbuilder_ptr(thisptr->ptr_builder, 0), gate_strbuilder_length(thisptr->ptr_builder)))
1590 {
1591 11 return GATE_RESULT_OK;
1592 }
1593 else
1594 {
1595 return GATE_RESULT_OUTOFMEMORY;
1596 }
1597 }
1598 22 static gate_result_t gate_stringstream_to_string_impl(void* ptr, gate_string_t* ptr_output)
1599 {
1600 22 gate_stringstream_impl_t* thisptr = (gate_stringstream_impl_t*)ptr;
1601
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if (NULL == gate_strbuilder_to_string(thisptr->ptr_builder, ptr_output))
1602 {
1603 return GATE_RESULT_FAILED;
1604 }
1605 else
1606 {
1607 22 return GATE_RESULT_OK;
1608 }
1609 }
1610
1611
1612
1613 /********************************
1614 * null stream implementation *
1615 ********************************/
1616
1617 4 static void gate_nullstream_release_impl(void* self)
1618 {
1619 (void)self;
1620 4 }
1621 2 static int gate_nullstream_retain_impl(void* self)
1622 {
1623 (void)self;
1624 2 return 1;
1625 }
1626 static char const* gate_nullstream_get_interface_name_impl(void* self)
1627 {
1628 (void)self;
1629 return GATE_INTERFACE_NAME_STREAM;
1630 }
1631 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 if (returned != NULL)
1637 {
1638 *returned = 0;
1639 }
1640 return GATE_RESULT_OK;
1641 }
1642 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 if (returned != NULL)
1648 {
1649 *returned = 0;
1650 }
1651 return GATE_RESULT_OK;
1652 }
1653 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 if (written != NULL)
1658 {
1659 *written = bufferlength;
1660 }
1661 return GATE_RESULT_OK;
1662 }
1663 static gate_result_t gate_nullstream_flush_impl(void* self)
1664 {
1665 (void)self;
1666 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 2 static void gate_nullstream_vtbl_init()
1675 {
1676
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (!gate_nullstream_vtbl.get_interface_name)
1677 {
1678
1679 1 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 1 gate_nullstream_vtbl = local_vtbl;
1690 }
1691 2 }
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 2 gate_stream_t* gate_nullstream()
1701 {
1702 2 gate_nullstream_vtbl_init();
1703
1704 2 return &global_null_stream;
1705 }
1706
1707
1708
1709 1453 gate_result_t gate_stream_read_block(gate_stream_t* stream, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1710 {
1711 1453 gate_result_t result = GATE_RESULT_OK;
1712 1453 gate_size_t totalread = 0;
1713 gate_size_t blockread;
1714
2/2
✓ Branch 0 taken 1459 times.
✓ Branch 1 taken 1429 times.
2888 while (totalread < bufferlength)
1715 {
1716 1459 blockread = 0;
1717 1459 result = gate_stream_read(stream, &buffer[totalread], bufferlength - totalread, &blockread);
1718
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1458 times.
1459 if (GATE_FAILED(result))
1719 {
1720 1 break;
1721 }
1722 1458 GATE_DEBUG_ASSERT(blockread <= (bufferlength - totalread));
1723
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1435 times.
1458 if (blockread == 0)
1724 {
1725 23 break;
1726 }
1727 1435 totalread += blockread;
1728 }
1729
1/2
✓ Branch 0 taken 1453 times.
✗ Branch 1 not taken.
1453 if (returned != NULL)
1730 {
1731 1453 *returned = totalread;
1732 }
1733 1453 return result;
1734 }
1735
1736 168 gate_result_t gate_stream_read_line(gate_stream_t* stream, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
1737 {
1738 168 gate_result_t ret = GATE_RESULT_OK;
1739 168 gate_size_t pos = 0;
1740 gate_size_t lenread;
1741
1742
1/2
✓ Branch 0 taken 7022 times.
✗ Branch 1 not taken.
7022 while (pos != bufferlength)
1743 {
1744 7022 ret = gate_stream_read(stream, &buffer[pos], 1, &lenread);
1745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7022 times.
7022 GATE_BREAK_IF_FAILED(ret);
1746
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 7003 times.
7022 if (lenread == 0)
1747 {
1748 /* end of stream */
1749 19 break;
1750 }
1751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7003 times.
7003 if (buffer[pos] == '\b')
1752 {
1753 if (pos > 0)
1754 {
1755 --pos;
1756 }
1757 continue;
1758 }
1759
1760
2/2
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 6854 times.
7003 if (buffer[pos] == '\n')
1761 {
1762 /* end of line */
1763 149 ++pos;
1764 149 break;
1765 }
1766 6854 ++pos;
1767 }
1768
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 if (returned != NULL)
1769 {
1770 168 *returned = pos;
1771 }
1772 168 return ret;
1773 }
1774
1775
1776 11673 gate_result_t gate_stream_write_block(gate_stream_t* stream, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1777 {
1778 11673 gate_result_t result = GATE_RESULT_OK;
1779 11673 gate_size_t totalwritten = 0;
1780 gate_size_t blockwritten;
1781
2/2
✓ Branch 0 taken 8617 times.
✓ Branch 1 taken 11673 times.
20290 while (totalwritten < bufferlength)
1782 {
1783 8617 blockwritten = 0;
1784 8617 result = gate_stream_write(stream, &buffer[totalwritten], bufferlength - totalwritten, &blockwritten);
1785 /*result = stream->vtbl->write(stream, &buffer[totalwritten], bufferlength - totalwritten, &blockwritten);*/
1786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8617 times.
8617 if (GATE_FAILED(result))
1787 {
1788 break;
1789 }
1790 8617 GATE_DEBUG_ASSERT(blockwritten <= (bufferlength - totalwritten));
1791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8617 times.
8617 if (blockwritten == 0)
1792 {
1793 result = GATE_RESULT_CANCELED;
1794 break;
1795 }
1796 8617 totalwritten += blockwritten;
1797 }
1798
1/2
✓ Branch 0 taken 11673 times.
✗ Branch 1 not taken.
11673 if (GATE_SUCCEEDED(result))
1799 {
1800 11673 GATE_DEBUG_ASSERT(bufferlength == totalwritten);
1801 }
1802
2/2
✓ Branch 0 taken 11618 times.
✓ Branch 1 taken 55 times.
11673 if (written != NULL)
1803 {
1804 11618 *written = totalwritten;
1805 }
1806 11673 return result;
1807 }
1808
1809
1810 209 gate_result_t gate_stream_print_cstr(gate_stream_t* stream, gate_cstr_t text)
1811 {
1812 209 gate_size_t textlength = gate_str_length(text);
1813 gate_size_t written;
1814 209 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 = GATE_RESULT_FAILED;
1819 char buffer[8192 + 4096];
1820 char* ptr_buffer = &buffer[0];
1821 gate_size_t max_utf8_length = wstr_len * 3 + 1;
1822 gate_size_t buffer_used;
1823 gate_string_t tmp = GATE_STRING_INIT_EMPTY;
1824
1825 do
1826 {
1827 if (max_utf8_length >= sizeof(buffer))
1828 {
1829 ptr_buffer = (char*)gate_mem_alloc(max_utf8_length);
1830 if (ptr_buffer == NULL)
1831 {
1832 ret = GATE_RESULT_OUTOFMEMORY;
1833 break;
1834 }
1835 }
1836
1837 buffer_used = gate_wstr_to_cstr(wstr, wstr_len, ptr_buffer, max_utf8_length);
1838 gate_string_create_static_len(&tmp, ptr_buffer, buffer_used);
1839 ret = gate_stream_print_string(stream, &tmp);
1840 } while (0);
1841
1842 if ((ptr_buffer != NULL) && (ptr_buffer != &buffer[0]))
1843 {
1844 gate_mem_dealloc(ptr_buffer);
1845 }
1846 return ret;
1847 }
1848
1849 14 gate_result_t gate_stream_println_cstr(gate_stream_t* stream, char const* text)
1850 {
1851 14 gate_size_t textlength = gate_str_length(text);
1852 14 gate_result_t result = GATE_RESULT_OK;
1853
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (textlength > 0)
1854 {
1855 2 result = gate_stream_write_block(stream, text, textlength, NULL);
1856 }
1857
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (GATE_SUCCEEDED(result))
1858 {
1859 14 result = gate_stream_write_block(stream, GATE_STR_NEWLINE, GATE_STR_NEWLINE_LENGTH, NULL);
1860 }
1861 14 return result;
1862 }
1863 12 gate_result_t gate_stream_print_int(gate_stream_t* stream, gate_int32_t num)
1864 {
1865 gate_char8_t buffer[24];
1866 12 gate_size_t bufferlength = gate_str_print_int32(buffer, sizeof(buffer), num);
1867 12 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1868 }
1869 8 gate_result_t gate_stream_print_uint(gate_stream_t* stream, gate_uint32_t num)
1870 {
1871 gate_char8_t buffer[24];
1872 8 gate_size_t bufferlength = gate_str_print_uint32(buffer, sizeof(buffer), num);
1873 8 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1874 }
1875 4 gate_result_t gate_stream_print_int64(gate_stream_t* stream, gate_int64_t num)
1876 {
1877 gate_char8_t buffer[48];
1878 4 gate_size_t bufferlength = gate_str_print_int64(buffer, sizeof(buffer), num);
1879 4 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1880 }
1881 4 gate_result_t gate_stream_print_uint64(gate_stream_t* stream, gate_uint64_t num)
1882 {
1883 gate_char8_t buffer[48];
1884 4 gate_size_t bufferlength = gate_str_print_uint64(buffer, sizeof(buffer), num);
1885 4 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1886 }
1887 9 gate_result_t gate_stream_print_real(gate_stream_t* stream, gate_real64_t num, unsigned intlen, unsigned decimallen, unsigned grouplen)
1888 {
1889 gate_char8_t buffer[64];
1890 9 gate_size_t bufferlength = gate_str_print_real(buffer, sizeof(buffer), num, intlen, decimallen, grouplen);
1891 9 return gate_stream_write_block(stream, buffer, bufferlength, NULL);
1892 }
1893 gate_result_t gate_stream_print_string(gate_stream_t* stream, gate_string_t const* text)
1894 {
1895 if (text != NULL)
1896 {
1897 return gate_stream_write_block(stream, text->str, text->length, NULL);
1898 }
1899 else
1900 {
1901 return GATE_RESULT_OK;
1902 }
1903 }
1904
1905
1906 3051 gate_result_t gate_stream_print(gate_stream_t* stream, ...)
1907 {
1908 3051 gate_result_t ret = GATE_RESULT_OK;
1909 int print_type;
1910 3051 gate_bool_t continue_loop = true;
1911 gate_bool_t val_bool;
1912 3051 char val_chr[2] = GATE_INIT_EMPTY;
1913 char const* val_cstr;
1914 gate_string_t const* val_str;
1915 gate_int8_t val_i8;
1916 gate_uint8_t val_ui8;
1917 gate_int16_t val_i16;
1918 gate_uint16_t val_ui16;
1919 gate_int32_t val_i32;
1920 gate_uint32_t val_ui32;
1921 gate_int64_t val_i64;
1922 gate_uint64_t val_ui64;
1923 gate_real32_t val_r32;
1924 gate_real64_t val_r64;
1925 void* val_ptr;
1926 3051 char const* ptr_text = NULL;
1927 char buffer[512];
1928 gate_size_t text_len;
1929 va_list vl;
1930 3051 va_start(vl, stream);
1931
1932 /* INFO: types small than [int] are converted to [int]
1933 https://stackoverflow.com/questions/23983471/char-is-promoted-to-int-when-passed-through-in-c
1934 */
1935
1936
2/2
✓ Branch 0 taken 9985 times.
✓ Branch 1 taken 3051 times.
13036 while (continue_loop)
1937 {
1938 9985 print_type = va_arg(vl, int);
1939 9985 ptr_text = NULL;
1940 9985 text_len = 0;
1941
8/25
✓ Branch 0 taken 3051 times.
✓ Branch 1 taken 4121 times.
✓ Branch 2 taken 497 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1819 times.
✓ Branch 7 taken 71 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 220 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 200 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 6 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
9985 switch (print_type)
1942 {
1943 3051 case GATE_PRINT_END:
1944 {
1945 3051 text_len = 0;
1946 3051 continue_loop = false;
1947 3051 break;
1948 }
1949 4121 case GATE_PRINT_CHAR:
1950 {
1951 4121 val_chr[0] = (char)va_arg(vl, int);
1952 4121 ptr_text = &val_chr[0];
1953 4121 text_len = 1;
1954 4121 break;
1955 }
1956 497 case GATE_PRINT_NEWLINE:
1957 {
1958 497 ptr_text = GATE_STR_NEWLINE;
1959 497 text_len = GATE_STR_NEWLINE_LENGTH;
1960 497 break;
1961 }
1962 case GATE_PRINT_CR:
1963 {
1964 ptr_text = GATE_STR_CR;
1965 text_len = 1;
1966 break;
1967 }
1968 case GATE_PRINT_LF:
1969 {
1970 ptr_text = GATE_STR_LF;
1971 text_len = 1;
1972 break;
1973 }
1974 case GATE_PRINT_CRLF:
1975 {
1976 ptr_text = GATE_STR_CRLF;
1977 text_len = 2;
1978 break;
1979 }
1980 1819 case GATE_PRINT_CSTR:
1981 {
1982 1819 val_cstr = va_arg(vl, char const*);
1983 1819 ptr_text = val_cstr;
1984 1819 text_len = gate_str_length(val_cstr);
1985 1819 break;
1986 }
1987 71 case GATE_PRINT_STRING:
1988 {
1989 71 val_str = va_arg(vl, gate_string_t const*);
1990 71 ptr_text = val_str->str;
1991 71 text_len = val_str->length;
1992 71 break;
1993 }
1994 case GATE_PRINT_BOOL:
1995 {
1996 val_bool = (gate_bool_t)va_arg(vl, int);
1997 ptr_text = val_bool ? "true" : "false";
1998 text_len = val_bool ? 4 : 5;
1999 break;
2000 }
2001 case GATE_PRINT_I8:
2002 {
2003 val_i8 = (gate_int8_t)va_arg(vl, int);
2004 text_len = gate_str_print_int16(buffer, sizeof(buffer), val_i8);
2005 ptr_text = buffer;
2006 break;
2007 }
2008 case GATE_PRINT_UI8:
2009 {
2010 val_ui8 = (gate_uint8_t)va_arg(vl, int);
2011 text_len = gate_str_print_uint16(buffer, sizeof(buffer), val_ui8);
2012 ptr_text = buffer;
2013 break;
2014 }
2015 case GATE_PRINT_I16:
2016 {
2017 val_i16 = (gate_int16_t)va_arg(vl, int);
2018 text_len = gate_str_print_int16(buffer, sizeof(buffer), val_i16);
2019 ptr_text = buffer;
2020 break;
2021 }
2022 220 case GATE_PRINT_UI16:
2023 {
2024 220 val_ui16 = (gate_uint16_t)va_arg(vl, int);
2025 220 text_len = gate_str_print_uint16(buffer, sizeof(buffer), val_ui16);
2026 220 ptr_text = buffer;
2027 220 break;
2028 }
2029 case GATE_PRINT_I32:
2030 {
2031 val_i32 = va_arg(vl, gate_int32_t);
2032 text_len = gate_str_print_int32(buffer, sizeof(buffer), val_i32);
2033 ptr_text = buffer;
2034 break;
2035 }
2036 200 case GATE_PRINT_UI32:
2037 {
2038 200 val_ui32 = va_arg(vl, gate_uint32_t);
2039 200 text_len = gate_str_print_uint32(buffer, sizeof(buffer), val_ui32);
2040 200 ptr_text = buffer;
2041 200 break;
2042 }
2043 case GATE_PRINT_I64:
2044 {
2045 val_i64 = va_arg(vl, gate_int64_t);
2046 text_len = gate_str_print_int64(buffer, sizeof(buffer), val_i64);
2047 ptr_text = buffer;
2048 break;
2049 }
2050 case GATE_PRINT_UI64:
2051 {
2052 val_ui64 = va_arg(vl, gate_uint64_t);
2053 text_len = gate_str_print_uint64(buffer, sizeof(buffer), val_ui64);
2054 ptr_text = buffer;
2055 break;
2056 }
2057 6 case GATE_PRINT_H8:
2058 {
2059 6 val_ui8 = (gate_uint8_t)va_arg(vl, unsigned int);
2060 6 text_len = gate_str_print_hex(buffer, sizeof(buffer), val_ui8, 1, false);
2061 6 ptr_text = buffer;
2062 6 break;
2063 }
2064 case GATE_PRINT_H16:
2065 {
2066 val_ui16 = (gate_uint16_t)va_arg(vl, unsigned int);
2067 text_len = gate_str_print_hex(buffer, sizeof(buffer), val_ui16, 2, false);
2068 ptr_text = buffer;
2069 break;
2070 }
2071 case GATE_PRINT_H32:
2072 {
2073 val_ui32 = (gate_uint32_t)va_arg(vl, gate_uint32_t);
2074 text_len = gate_str_print_hex(buffer, sizeof(buffer), val_ui32, 4, false);
2075 ptr_text = buffer;
2076 break;
2077 }
2078 case GATE_PRINT_H64:
2079 {
2080 val_ui64 = (gate_uint64_t)va_arg(vl, gate_uint64_t);
2081 text_len = gate_str_print_hex(buffer, sizeof(buffer), val_ui64, 8, false);
2082 ptr_text = buffer;
2083 break;
2084 }
2085 case GATE_PRINT_R32:
2086 {
2087 val_r32 = (gate_real32_t)va_arg(vl, double);
2088 text_len = gate_str_print_real(buffer, sizeof(buffer), val_r32, 0, 6, 0);
2089 ptr_text = buffer;
2090 break;
2091 }
2092 case GATE_PRINT_R64:
2093 {
2094 val_r64 = va_arg(vl, gate_real64_t);
2095 text_len = gate_str_print_real(buffer, sizeof(buffer), val_r64, 0, 6, 0);
2096 ptr_text = buffer;
2097 break;
2098 }
2099 case GATE_PRINT_ADDRESS:
2100 {
2101 val_ptr = va_arg(vl, void*);
2102 if (sizeof(void*) == 2)
2103 {
2104 text_len = gate_str_print_hex_uint16(buffer, sizeof(buffer), (gate_uint16_t)(gate_uintptr_t)val_ptr, true);
2105 }
2106 else if (sizeof(void*) == 4)
2107 {
2108 text_len = gate_str_print_hex_uint32(buffer, sizeof(buffer), (gate_uint32_t)(gate_uintptr_t)val_ptr, true);
2109 }
2110 else
2111 {
2112 text_len = gate_str_print_hex_uint64(buffer, sizeof(buffer), (gate_uint64_t)(gate_uintptr_t)val_ptr, true);
2113 }
2114 ptr_text = buffer;
2115 break;
2116 }
2117 default:
2118 {
2119 ret = GATE_RESULT_INVALIDARG;
2120 continue_loop = false;
2121 break;
2122 }
2123 }
2124
2125 9985 ret = gate_stream_write_block(stream, ptr_text, text_len, &text_len);
2126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9985 times.
9985 GATE_BREAK_IF_FAILED(ret);
2127 }
2128 3051 va_end(vl);
2129 3051 return ret;
2130 }
2131
2132 static gate_result_t gate_stream_peek_utf8_char(gate_stream_t* stream, gate_char32_t* chr, gate_size_t* decoded)
2133 {
2134 char utf8_buffer[16];
2135 gate_size_t bytes_returned = 0;
2136 gate_size_t bytes_decoded = 0;
2137 gate_result_t ret = GATE_RESULT_FAILED;
2138
2139 ret = gate_stream_peek(stream, utf8_buffer, sizeof(utf8_buffer), &bytes_returned);
2140 if (GATE_SUCCEEDED(ret))
2141 {
2142 if (bytes_returned == 0)
2143 {
2144 /* end of stream reached */
2145 *chr = 0;
2146 *decoded = 0;
2147 }
2148 else
2149 {
2150 bytes_decoded = gate_char_read_utf8(utf8_buffer, bytes_returned, chr);
2151 if (bytes_decoded == 0)
2152 {
2153 /* utf8 error, return byte value instead */
2154 *chr = (gate_char32_t)(gate_uint8_t)utf8_buffer[0];
2155 *decoded = 1;
2156 }
2157 else
2158 {
2159 *decoded = bytes_decoded;
2160 }
2161 }
2162 }
2163 return ret;
2164 }
2165
2166 gate_size_t gate_stream_scan_char32(gate_stream_t* stream, gate_char32_t* chr)
2167 {
2168 /* TODO */
2169 return 0;
2170 }
2171 gate_size_t gate_stream_scan_char16(gate_stream_t* stream, gate_char16_t* chr)
2172 {
2173 /* TODO */
2174 return 0;
2175 }
2176 gate_size_t gate_stream_scan_char8(gate_stream_t* stream, gate_char8_t* chr)
2177 {
2178 /* TODO */
2179 return 0;
2180 }
2181
2182
2183 gate_size_t gate_stream_scan_int(gate_stream_t* stream, gate_int32_t* num)
2184 {
2185 /* TODO */
2186 return 0;
2187 }
2188 gate_size_t gate_stream_scan_uint(gate_stream_t* stream, gate_uint32_t* num)
2189 {
2190 /* TODO */
2191 return 0;
2192 }
2193 gate_size_t gate_stream_scan_int64(gate_stream_t* stream, gate_int64_t* num)
2194 {
2195 /* TODO */
2196 return 0;
2197 }
2198 gate_size_t gate_stream_scan_uint64(gate_stream_t* stream, gate_uint64_t* num)
2199 {
2200 /* TODO */
2201 return 0;
2202 }
2203 gate_size_t gate_stream_scan_real(gate_stream_t* stream, gate_real64_t* num)
2204 {
2205 /* TODO */
2206 return 0;
2207 }
2208 gate_size_t gate_stream_scan_string(gate_stream_t* stream, gate_string_t* text)
2209 {
2210 /* TODO */
2211 return 0;
2212 }
2213
2214
2215
2216
2217 107 gate_result_t gate_stream_transfer_buffer(gate_stream_t* src, gate_stream_t* dst, char* buffer, gate_size_t buffersize)
2218 {
2219 gate_size_t bytes_read;
2220 gate_size_t bytes_written;
2221 gate_result_t result;
2222 for (;;)
2223 {
2224 107 result = gate_stream_read(src, buffer, buffersize, &bytes_read);
2225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (GATE_FAILED(result))
2226 {
2227 break;
2228 }
2229
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 88 times.
107 if (bytes_read == 0)
2230 {
2231 /* end of stream reached */
2232 19 break;
2233 }
2234 88 result = gate_stream_write_block(dst, buffer, bytes_read, &bytes_written);
2235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
88 if (GATE_FAILED(result))
2236 {
2237 break;
2238 }
2239 }
2240 19 return result;
2241 }
2242
2243 4 gate_result_t gate_stream_transfer_limit(gate_stream_t* src, gate_uint64_t limit, gate_stream_t* dst, gate_uint64_t* transferred)
2244 {
2245 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
2246 static gate_size_t const buffer_size = sizeof(buffer);
2247 gate_size_t next_size;
2248 gate_size_t bytes_read;
2249 gate_size_t bytes_written;
2250 4 gate_result_t result = GATE_RESULT_OK;
2251 4 gate_uint64_t counter = 0;
2252
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 while (limit > 0)
2253 {
2254 4 next_size = (limit > buffer_size) ? buffer_size : (gate_size_t)limit;
2255 4 result = gate_stream_read(src, buffer, next_size, &bytes_read);
2256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (GATE_FAILED(result))
2257 {
2258 break;
2259 }
2260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (bytes_read == 0)
2261 {
2262 /* end of stream reached */
2263 break;
2264 }
2265 4 GATE_DEBUG_ASSERT(limit >= bytes_read);
2266 4 limit -= bytes_read;
2267 4 result = gate_stream_write_block(dst, buffer, bytes_read, &bytes_written);
2268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (GATE_FAILED(result))
2269 {
2270 break;
2271 }
2272 4 GATE_DEBUG_ASSERT(bytes_read == bytes_written);
2273 4 counter += bytes_written;
2274 }
2275
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (transferred)
2276 {
2277 4 *transferred = counter;
2278 }
2279 4 return result;
2280 }
2281
2282
2283 13 gate_result_t gate_stream_transfer(gate_stream_t* src, gate_stream_t* dst)
2284 {
2285 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
2286 13 return gate_stream_transfer_buffer(src, dst, buffer, sizeof(buffer));
2287 }
2288
2289 3 gate_result_t gate_stream_skip(gate_stream_t* src, gate_uint64_t count, gate_uint64_t* bytes_skipped)
2290 {
2291 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
2292 gate_size_t nextlen;
2293 3 gate_size_t returned = 1;
2294 3 gate_result_t result = GATE_RESULT_OK;
2295 3 gate_uint64_t actual_skipped = 0;
2296
2297
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
6 while ((count != 0) && (returned != 0))
2298 {
2299 3 nextlen = (count > GATE_MAX_COPYBUFFER_LENGTH) ? GATE_MAX_COPYBUFFER_LENGTH : (gate_size_t)count;
2300 3 result = gate_stream_read_block(src, buffer, nextlen, &returned);
2301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(result);
2302 3 GATE_DEBUG_ASSERT(returned <= nextlen);
2303 3 actual_skipped += returned;
2304 3 count -= returned;
2305 }
2306
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (bytes_skipped)
2307 {
2308 1 *bytes_skipped = actual_skipped;
2309 }
2310 3 return result;
2311 }
2312
2313