GCC Code Coverage Report


Directory: src/gate/
File: src/gate/platforms.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 149 0.0%
Functions: 0 5 0.0%
Branches: 0 116 0.0%

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/platforms.h"
30 #include "gate/streams.h"
31 #include "gate/results.h"
32 #include "gate/debugging.h"
33 #include "gate/strings.h"
34 #include "gate/synchronization.h"
35 #include "gate/times.h"
36
37
38
39 /*****************************
40 * generic implementations *
41 *****************************/
42
43 gate_result_t gate_platform_stream_buffer_init(gate_platform_stream_buffer_t* strmbuf, gate_platform_stream_t strm,
44 gate_int64_t total_size, gate_int64_t position, gate_size_t blocksize)
45 {
46 gate_result_t ret = GATE_RESULT_INVALIDARG;
47 if (strmbuf != NULL)
48 {
49 gate_mem_clear(strmbuf, sizeof(gate_platform_stream_buffer_t));
50 strmbuf->stream = strm;
51 strmbuf->total_size = total_size;
52 strmbuf->position = position;
53 strmbuf->block_size = blocksize;
54 strmbuf->block_buffer_used = 0;
55 ret = GATE_RESULT_OK;
56 }
57 return ret;
58 }
59 gate_result_t gate_platform_stream_buffer_read(gate_platform_stream_buffer_t* strmbuf, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
60 {
61 gate_result_t ret = GATE_RESULT_FAILED;
62 void* read_buffer = buffer;
63 gate_size_t read_buffer_length = bufferlength;
64 gate_size_t tmp_received = 0;
65 gate_size_t* ptr_read_buffer_returned = ((returned == NULL) ? &tmp_received : returned);
66
67 do
68 {
69 if ((strmbuf == NULL) || (bufferlength == 0) || (buffer == NULL))
70 {
71 ret = GATE_RESULT_INVALIDARG;
72 break;
73 }
74 if (!gate_platform_stream_valid(strmbuf->stream))
75 {
76 ret = GATE_RESULT_INVALIDSTATE;
77 break;
78 }
79
80 if (returned != NULL)
81 {
82 *returned = 0;
83 }
84
85 if (strmbuf->block_buffer_used == 0)
86 {
87 /* nothing in buffer -> try to read from stream */
88
89 if (strmbuf->position >= 0)
90 {
91 if (strmbuf->total_size >= 0)
92 {
93 if (strmbuf->position >= strmbuf->total_size)
94 {
95 /* end of stream reached, stop further reading */
96 if (returned != NULL)
97 {
98 *returned = 0;
99 ret = GATE_RESULT_OK;
100 break;
101 }
102 }
103 }
104
105 ret = gate_platform_stream_seek(strmbuf->stream, strmbuf->position, GATE_PLATFORM_STREAM_ORIGIN_BEGIN, NULL);
106 if (GATE_FAILED(ret))
107 {
108 GATE_DEBUG_TRACE_PLATFORM_ERROR("gate_platform_stream_seek() failed");
109 /* failing to change the file pointer is unwanted,
110 but assuming we are in a valid state, the file pointer
111 is already at the correct position*/
112 }
113 }
114
115 if (strmbuf->block_size != 0)
116 {
117 if (bufferlength < strmbuf->block_size)
118 {
119 /* read into local buffer*/
120 read_buffer = &strmbuf->block_buffer[0];
121 read_buffer_length = strmbuf->block_size;
122 ptr_read_buffer_returned = &strmbuf->block_buffer_used;
123 }
124 else
125 {
126 /* align buffer to block-size */
127 bufferlength -= (bufferlength % strmbuf->block_size);
128 }
129 }
130
131 ret = gate_platform_stream_read(strmbuf->stream, read_buffer, read_buffer_length, ptr_read_buffer_returned);
132 if (GATE_FAILED(ret))
133 {
134 GATE_DEBUG_TRACE_PLATFORM_ERROR("gate_platform_stream_read() failed");
135 break;
136 }
137
138 /* success case: update stream position if available */
139 if (strmbuf->position >= 0)
140 {
141 strmbuf->position += *ptr_read_buffer_returned;
142 }
143 }
144
145 if (strmbuf->block_buffer_used != 0)
146 {
147 /* if there are bytes in the internal buffer -> return them */
148
149 if (bufferlength >= strmbuf->block_buffer_used)
150 {
151 gate_mem_copy(buffer, &strmbuf->block_buffer[0], strmbuf->block_buffer_used);
152 if (returned != NULL)
153 {
154 *returned = strmbuf->block_buffer_used;
155 }
156 strmbuf->block_buffer_used = 0;
157 ret = GATE_RESULT_OK;
158 }
159 else
160 {
161 gate_mem_copy(buffer, &strmbuf->block_buffer[0], bufferlength);
162 if (returned != NULL)
163 {
164 *returned = bufferlength;
165 }
166 gate_mem_move(&strmbuf->block_buffer[0], &strmbuf->block_buffer[bufferlength], strmbuf->block_buffer_used - bufferlength);
167 strmbuf->block_buffer_used -= bufferlength;
168 ret = GATE_RESULT_OK;
169 }
170 }
171 } while (0);
172
173 return ret;
174 }
175 gate_result_t gate_platform_stream_buffer_write(gate_platform_stream_buffer_t* strmbuf, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
176 {
177 gate_result_t ret = GATE_RESULT_FAILED;
178
179 gate_size_t block_buffer_avail;
180 gate_size_t written_internal = 0;
181
182 do
183 {
184 if ((strmbuf == NULL) || (bufferlength == 0) || (buffer == NULL))
185 {
186 ret = GATE_RESULT_INVALIDARG;
187 break;
188 }
189 if (!gate_platform_stream_valid(strmbuf->stream))
190 {
191 ret = GATE_RESULT_INVALIDSTATE;
192 break;
193 }
194
195 if (strmbuf->position >= 0)
196 {
197 /* set native stream position */
198 ret = gate_platform_stream_seek(strmbuf->stream, strmbuf->position, GATE_PLATFORM_STREAM_ORIGIN_BEGIN, NULL);
199 if (GATE_FAILED(ret))
200 {
201 GATE_DEBUG_TRACE_PLATFORM_ERROR("gate_platform_stream_seek() failed");
202 /* ignore error and assume that stream is at correct position */
203 }
204 }
205
206 if (strmbuf->block_size == 0)
207 {
208 /* no block sizes -> no troubles */
209 written_internal = 0;
210 ret = gate_platform_stream_write(strmbuf->stream, buffer, bufferlength, &written_internal);
211 if (GATE_SUCCEEDED(ret) && (strmbuf->position >= 0))
212 {
213 /* success case: update stream position if available */
214 strmbuf->position += (gate_int64_t)written_internal;
215 }
216 if (written)
217 {
218 *written = written_internal;
219 }
220 break;
221 }
222
223
224 /* work with block sizes */
225
226 if (strmbuf->block_buffer_used == 0)
227 {
228 /* block buffer is empty */
229 if (bufferlength >= strmbuf->block_size)
230 {
231 /* data block is big enough to directly write it to stream */
232
233 bufferlength -= bufferlength % strmbuf->block_size;
234 written_internal = 0;
235 ret = gate_platform_stream_write(strmbuf->stream, buffer, bufferlength, &written_internal);
236
237 if (GATE_SUCCEEDED(ret) && (strmbuf->position >= 0))
238 {
239 /* success case: update stream position if available */
240 strmbuf->position += (gate_int64_t)written_internal;
241 }
242 if (written)
243 {
244 *written = written_internal;
245 }
246 break;
247 }
248 }
249
250 /* work with block buffer: */
251 block_buffer_avail = strmbuf->block_size - strmbuf->block_buffer_used;
252
253 if (bufferlength > block_buffer_avail)
254 {
255 bufferlength = block_buffer_avail;
256 }
257
258 gate_mem_copy(&strmbuf->block_buffer[strmbuf->block_buffer_used], buffer, bufferlength);
259 if (written != NULL)
260 {
261 *written = bufferlength;
262 }
263 strmbuf->block_buffer_used += bufferlength;
264
265 if (strmbuf->block_buffer_used >= strmbuf->block_size)
266 {
267 ret = gate_platform_stream_write(strmbuf->stream, &strmbuf->block_buffer[0], strmbuf->block_size, &written_internal);
268 if (GATE_SUCCEEDED(ret))
269 {
270 if (strmbuf->position >= 0)
271 {
272 /* success case: update stream position if available */
273 strmbuf->position += (gate_int64_t)written_internal;
274 }
275
276 if (written_internal < strmbuf->block_size)
277 {
278 /* no all was written to stream */
279 gate_mem_move(&strmbuf->block_buffer[0], &strmbuf->block_buffer[written_internal], strmbuf->block_size - written_internal);
280 strmbuf->block_buffer_used -= written_internal;
281 }
282 else
283 {
284 strmbuf->block_buffer_used = 0;
285 }
286 }
287 else
288 {
289 /* remove what was added to block buffer */
290 strmbuf->block_buffer_used -= bufferlength;
291 }
292 }
293 else
294 {
295 /* block buffer is not full, cannot do anything now */
296 ret = GATE_RESULT_OK;
297 }
298 break;
299
300 } while (0);
301
302 return ret;
303
304 }
305 gate_result_t gate_platform_stream_buffer_seek(gate_platform_stream_buffer_t* strmbuf, gate_int64_t position, int origin, gate_int64_t* final_position)
306 {
307 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
308 gate_int64_t new_pos = 0;
309
310 if (final_position == NULL)
311 {
312 final_position = &new_pos;
313 }
314
315 do
316 {
317 if (origin == GATE_PLATFORM_STREAM_ORIGIN_BEGIN)
318 {
319 if ((position < 0) || ((strmbuf->total_size >= 0) && (position > strmbuf->total_size)))
320 {
321 ret = GATE_RESULT_OUTOFBOUNDS;
322 break;
323 }
324 }
325 else if (origin == GATE_PLATFORM_STREAM_ORIGIN_CURRENT)
326 {
327 if (strmbuf->position >= 0)
328 {
329 if (strmbuf->position + position < 0)
330 {
331 ret = GATE_RESULT_OUTOFBOUNDS;
332 break;
333 }
334 if ((strmbuf->total_size >= 0) && (strmbuf->position + position > strmbuf->total_size))
335 {
336 ret = GATE_RESULT_OUTOFBOUNDS;
337 break;
338 }
339 /* convert to absolute position: */
340 position = strmbuf->position + position;
341 origin = GATE_PLATFORM_STREAM_ORIGIN_BEGIN;
342 }
343 }
344 else if (origin == GATE_PLATFORM_STREAM_ORIGIN_END)
345 {
346 if (strmbuf->total_size >= 0)
347 {
348 if ((position > 0) || (strmbuf->total_size + position < 0))
349 {
350 ret = GATE_RESULT_OUTOFBOUNDS;
351 break;
352 }
353
354 /* convert to absolute position: */
355 position = strmbuf->total_size + position;
356 origin = GATE_PLATFORM_STREAM_ORIGIN_BEGIN;
357 }
358 }
359 else
360 {
361 ret = GATE_RESULT_INVALIDARG;
362 break;
363 }
364
365 ret = gate_platform_stream_seek(strmbuf->stream, position, GATE_PLATFORM_STREAM_ORIGIN_BEGIN, final_position);
366 if (GATE_SUCCEEDED(ret))
367 {
368 if (strmbuf->position >= 0)
369 {
370 strmbuf->position = *final_position;
371 }
372 }
373 } while (0);
374
375 return ret;
376 }
377
378 gate_result_t gate_platform_print_last_error(char* buffer, gate_size_t buffer_len)
379 {
380 gate_int32_t last_error = gate_platform_get_last_error();
381 return gate_platform_print_error(last_error, buffer, buffer_len);
382 }
383