GCC Code Coverage Report


Directory: src/gate/
File: src/gate/filesstream.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 74 124 59.7%
Functions: 11 17 64.7%
Branches: 19 42 45.2%

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/files.h"
30 #include "gate/results.h"
31
32
33 #define GATE_INTERFACE_NAME_FILESTREAM GATE_INTERFACE_NAME_CONTROLSTREAM
34
35 typedef struct gate_filestream_impl
36 {
37 GATE_INTERFACE_VTBL(gate_controlstream)* vbl;
38 gate_atomic_int_t ref_counter;
39 gate_file_t file_handle;
40 gate_bool_t can_read;
41 gate_bool_t can_write;
42 } gate_filestream_impl_t;
43
44
45 23 static void gate_filestream_release(void* thisptr)
46 {
47 23 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
48
2/2
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 2 times.
23 if (gate_atomic_int_dec(&ptr->ref_counter) == 0)
49 {
50 21 gate_file_close(ptr->file_handle);
51 21 gate_mem_dealloc(ptr);
52 }
53 23 }
54 2 static int gate_filestream_retain(void* thisptr)
55 {
56 2 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
57 2 return (int)gate_atomic_int_inc(&ptr->ref_counter);
58 }
59 static char const* gate_filestream_get_interface_name(void* thisptr)
60 {
61 (void)thisptr;
62 return GATE_INTERFACE_NAME_CONTROLSTREAM;
63 }
64 1531 static gate_result_t gate_filestream_read(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
65 {
66 1531 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
67 1531 return gate_file_read(ptr->file_handle, buffer, bufferlength, returned);
68 }
69 1 static gate_result_t gate_filestream_peek(void* thisptr, char* buffer, gate_size_t bufferlength, gate_size_t* returned)
70 {
71 gate_result_t ret;
72 1 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
73 1 gate_int64_t position = 0;
74 do
75 {
76 1 ret = gate_file_pos(ptr->file_handle, &position);
77
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
78 {
79 break;
80 }
81 1 ret = gate_file_read(ptr->file_handle, buffer, bufferlength, returned);
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
83 {
84 break;
85 }
86 1 ret = gate_file_seek(ptr->file_handle, position, GATE_FILE_SEEK_ORIGIN_BEGIN, NULL);
87 } while (0);
88 1 return ret;
89 }
90 102 static gate_result_t gate_filestream_write(void* thisptr, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
91 {
92 102 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
93 102 return gate_file_write(ptr->file_handle, buffer, bufferlength, written);
94 }
95 1 static gate_result_t gate_filestream_flush(void* thisptr)
96 {
97 1 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
98 1 return gate_file_flush(ptr->file_handle);
99 }
100 static gate_result_t gate_filestream_get_resource(void* thisptr, gate_enumint_t resource_type, gate_uintptr_t* resource)
101 {
102 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
103 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
104 do
105 {
106 if (resource == NULL)
107 {
108 ret = GATE_RESULT_INVALIDARG;
109 break;
110 }
111 switch (resource_type)
112 {
113 case GATE_STREAM_RESOURCE_DEFAULT:
114 case GATE_STREAM_RESOURCE_INPUT:
115 case GATE_STREAM_RESOURCE_OUTPUT:
116 {
117 *resource = (gate_uintptr_t)ptr->file_handle;
118 ret = GATE_RESULT_OK;
119 break;
120 }
121 }
122 } while (0);
123 return ret;
124 }
125 static gate_result_t gate_filestream_can_read(void* thisptr, gate_bool_t* return_value)
126 {
127 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
128 gate_result_t ret = GATE_RESULT_OK;
129 *return_value = ptr->can_read;
130 return ret;
131 }
132 static gate_result_t gate_filestream_can_write(void* thisptr, gate_bool_t* return_value)
133 {
134 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
135 gate_result_t ret = GATE_RESULT_OK;
136 *return_value = ptr->can_write;
137 return ret;
138 }
139 static gate_result_t gate_filestream_get_size(void* thisptr, gate_int64_t* return_value)
140 {
141 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
142 return gate_file_size(ptr->file_handle, return_value);
143 }
144 static gate_result_t gate_filestream_get_available(void* thisptr, gate_int64_t* return_value)
145 {
146 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
147 gate_int64_t filesize = 0;
148 gate_int64_t filepos = 0;
149 gate_result_t ret;
150 do
151 {
152 ret = gate_file_size(ptr->file_handle, &filesize);
153 GATE_BREAK_IF_FAILED(ret);
154 ret = gate_file_pos(ptr->file_handle, &filepos);
155 GATE_BREAK_IF_FAILED(ret);
156 if (return_value != NULL)
157 {
158 *return_value = filesize - filepos;
159 }
160 } while (0);
161 return ret;
162 }
163 9 static gate_result_t gate_filestream_seek(void* thisptr, gate_int64_t position, gate_enumint_t origin, gate_int64_t* new_position)
164 {
165 9 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
166 9 unsigned native_origin = GATE_FILE_SEEK_ORIGIN_BEGIN;
167 9 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
168 do
169 {
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (origin == GATE_STREAM_SEEK_CURRENT)
171 {
172 native_origin = GATE_FILE_SEEK_ORIGIN_CURPOS;
173 }
174
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 else if (origin == GATE_STREAM_SEEK_BEGIN)
175 {
176 9 native_origin = GATE_FILE_SEEK_ORIGIN_BEGIN;
177 }
178 else if (origin == GATE_STREAM_SEEK_END)
179 {
180 native_origin = GATE_FILE_SEEK_ORIGIN_END;
181 }
182 else
183 {
184 ret = GATE_RESULT_INVALIDARG;
185 break;
186 }
187
188 9 ret = gate_file_seek(ptr->file_handle, position, native_origin, new_position);
189 } while (0);
190 9 return ret;
191 }
192 8 static gate_result_t gate_filestream_reset(void* thisptr)
193 {
194 8 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
195 8 gate_int64_t dummy = 0;
196 8 gate_result_t ret = gate_filestream_seek(ptr, 0, GATE_STREAM_SEEK_BEGIN, &dummy);
197
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (GATE_SUCCEEDED(ret))
198 {
199
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (ptr->can_write)
200 {
201 8 ret = gate_file_truncate(ptr->file_handle);
202 }
203 }
204 8 return ret;
205 }
206 2 static gate_result_t gate_filestream_close(void* thisptr, gate_enumint_t close_type)
207 {
208 2 gate_filestream_impl_t* ptr = (gate_filestream_impl_t*)thisptr;
209 2 gate_result_t ret = gate_file_close(ptr->file_handle);
210 (void)close_type;
211
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
212 {
213 2 ptr->file_handle = GATE_FILE_INVALID;
214 }
215 2 return ret;
216 }
217
218
219 static GATE_INTERFACE_VTBL(gate_controlstream) gate_filestream_vtbl;
220 21 static void gate_init_filestream_vtbl()
221 {
222
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 18 times.
21 if (!gate_filestream_vtbl.get_interface_name)
223 {
224 GATE_INTERFACE_VTBL(gate_controlstream) const local_vtbl =
225 {
226 &gate_filestream_get_interface_name,
227 &gate_filestream_release,
228 &gate_filestream_retain,
229 &gate_filestream_read,
230 &gate_filestream_peek,
231 &gate_filestream_write,
232 &gate_filestream_flush,
233 &gate_filestream_get_resource,
234 &gate_filestream_can_read,
235 &gate_filestream_can_write,
236 &gate_filestream_get_size,
237 &gate_filestream_get_available,
238 &gate_filestream_seek,
239 &gate_filestream_reset,
240 &gate_filestream_close
241 };
242 3 gate_filestream_vtbl = local_vtbl;
243 }
244 21 }
245
246
247 21 gate_result_t gate_file_openstream(gate_string_t const* filepath, gate_enumint_t flags, gate_filestream_t** ptrtostreamptr)
248 {
249 gate_result_t result;
250 gate_filestream_impl_t* ret;
251
252 do
253 {
254 21 ret = (gate_filestream_impl_t*)gate_mem_alloc(sizeof(gate_filestream_impl_t));
255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (ret == NULL)
256 {
257 result = GATE_RESULT_OUTOFMEMORY;
258 break;
259 }
260 21 gate_init_filestream_vtbl();
261 21 ret->vbl = &gate_filestream_vtbl;
262 21 ret->can_read = false;
263 21 ret->can_write = false;
264 21 gate_atomic_int_init(&ret->ref_counter, 1);
265
266 21 result = gate_file_open(filepath, flags, &ret->file_handle);
267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (GATE_FAILED(result))
268 {
269 break;
270 }
271
272
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 4 times.
21 if (GATE_FLAG_ENABLED(flags, GATE_STREAM_OPEN_READ))
273 {
274 17 ret->can_read = true;
275 }
276
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 9 times.
21 if (GATE_FLAG_ENABLED(flags, GATE_STREAM_OPEN_WRITE))
277 {
278 12 ret->can_write = true;
279 }
280
281
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (ptrtostreamptr)
282 {
283 21 *ptrtostreamptr = (gate_filestream_t*)ret;
284 21 ret = NULL;
285 }
286 21 result = GATE_RESULT_OK;
287 } while (0);
288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (ret != NULL)
289 {
290 gate_mem_dealloc(ret);
291 }
292 21 return result;
293 }
294