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 |