GCC Code Coverage Report


Directory: src/gate/
File: src/gate/objects.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 83 96 86.5%
Functions: 14 16 87.5%
Branches: 18 30 60.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 #include "gate/objects.h"
29 #include "gate/strings.h"
30 #include "gate/atomics.h"
31 #include "gate/memalloc.h"
32 #include "gate/results.h"
33
34 typedef struct gate_runnable_dispatcher_class
35 {
36 GATE_INTERFACE_VTBL(gate_runnable) const* vtbl;
37 gate_atomic_int_t ref_counter;
38 gate_entrypoint_t func_ptr;
39 void* func_param;
40 gate_mem_dtor_t func_param_release;
41 gate_c_maxalign_t param_copy_begin;
42 } gate_runnable_dispatcher_t;
43
44 1 static void gate_runnable_dispatcher_release_impl(void* self)
45 {
46 1 gate_runnable_dispatcher_t* disp = (gate_runnable_dispatcher_t*)self;
47
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_atomic_int_dec(&disp->ref_counter) == 0)
48 {
49
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL != disp->func_param_release)
50 {
51 disp->func_param_release(disp->func_param);
52 }
53 1 gate_mem_dealloc(disp);
54 }
55 1 }
56 static int gate_runnable_dispatcher_retain_impl(void* self)
57 {
58 gate_runnable_dispatcher_t* disp = (gate_runnable_dispatcher_t*)self;
59 return gate_atomic_int_inc(&disp->ref_counter);
60 }
61 static char const* gate_runnable_dispatcher_interface_name_impl(void* self)
62 {
63 (void)self;
64 return GATE_INTERFACE_NAME_RUNNABLE;
65 }
66 1 static gate_result_t gate_runnable_dispatcher_run(void* self)
67 {
68 1 gate_runnable_dispatcher_t* disp = (gate_runnable_dispatcher_t*)self;
69 1 gate_result_t ret = disp->func_ptr(disp->func_param);
70 1 return ret;
71 }
72
73 static GATE_INTERFACE_VTBL(gate_runnable) gate_runnable_dispatcher_vtbl;
74 1 static void gate_init_runnable_dispatcher_vtbl()
75 {
76
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!gate_runnable_dispatcher_vtbl.get_interface_name)
77 {
78 GATE_INTERFACE_VTBL(gate_runnable) const local_vtbl =
79 {
80 &gate_runnable_dispatcher_interface_name_impl,
81 &gate_runnable_dispatcher_release_impl,
82 &gate_runnable_dispatcher_retain_impl,
83
84 &gate_runnable_dispatcher_run
85 };
86 1 gate_runnable_dispatcher_vtbl = local_vtbl;
87 }
88 1 }
89
90 1 gate_runnable_t* gate_runnable_create(gate_entrypoint_t function,
91 void* param,
92 gate_size_t param_copy_length,
93 gate_mem_copyctor_t param_copy_constructor,
94 gate_mem_dtor_t param_destructor)
95 {
96 1 gate_runnable_t* ret = NULL;
97 1 gate_runnable_dispatcher_t* runnable = NULL;
98 1 gate_size_t runnable_size = sizeof(gate_runnable_dispatcher_t) + param_copy_length;
99 gate_result_t result;
100
101 do
102 {
103 1 runnable = (gate_runnable_dispatcher_t*)gate_mem_alloc(runnable_size);
104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == runnable)
105 {
106 break;
107 }
108 1 gate_mem_clear(runnable, runnable_size);
109 1 gate_init_runnable_dispatcher_vtbl();
110 1 runnable->vtbl = &gate_runnable_dispatcher_vtbl;
111 1 gate_atomic_int_init(&runnable->ref_counter, 1);
112 1 runnable->func_ptr = function;
113
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (param_copy_length == 0)
114 {
115 /* parameter is external pointer */
116 1 runnable->func_param = param;
117 1 runnable->func_param_release = NULL;
118 }
119 else
120 {
121 /* parameter copied and embedded into runnable allocation block */
122 gate_mem_copy(&runnable->param_copy_begin, param, param_copy_length);
123 runnable->func_param = &runnable->param_copy_begin;
124 runnable->func_param_release = param_destructor;
125 if (NULL != param_copy_constructor)
126 {
127 result = param_copy_constructor(&runnable->param_copy_begin, param);
128 GATE_BREAK_IF_FAILED(result);
129 }
130 }
131
132 /* success case, runnable ready to use */
133 1 ret = (gate_runnable_t*)runnable;
134 } while (0);
135
136 1 return ret;
137 }
138
139
140
141 4 gate_result_t gate_object_ptr_copyctor(void* dest, void const* src)
142 {
143 4 gate_object_t* const* ptr_src = (gate_object_t* const*)src;
144 4 gate_object_t** ptr_dest = (gate_object_t**)dest;
145
146 4 *ptr_dest = *ptr_src;
147
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (*ptr_dest != NULL)
148 {
149 4 gate_object_retain(*ptr_dest);
150 }
151 4 return GATE_RESULT_OK;
152 }
153
154 4 void gate_object_ptr_dtor(void* dest)
155 {
156 4 gate_object_t** ptr_dest = (gate_object_t**)dest;
157
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (*ptr_dest != NULL)
158 {
159 4 gate_object_release(*ptr_dest);
160 }
161 4 }
162
163 13 gate_bool_t gate_object_implements_interface(gate_object_t* obj, char const* interface_name)
164 {
165 13 char const* obj_if_name = gate_object_get_interface_name(obj);
166 13 gate_size_t obj_if_name_len = gate_str_length(obj_if_name);
167 13 gate_size_t interface_name_len = gate_str_length(interface_name);
168
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 5 times.
13 if (gate_str_starts_with(obj_if_name, obj_if_name_len, interface_name, interface_name_len))
169 {
170
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (obj_if_name_len > interface_name_len)
171 {
172 4 return (obj_if_name[interface_name_len] == GATE_INTERFACE_NAME_SEPARATOR_CHAR);
173 }
174 else
175 {
176 4 return true;
177 }
178 }
179 5 return false;
180 }
181
182
183
184 typedef struct gate_memoryblock_impl_class
185 {
186 GATE_INTERFACE_VTBL(gate_memoryblock) const* vtbl;
187 gate_atomic_int_t ref_counter;
188 gate_size_t size;
189 union
190 {
191 gate_c_maxalign_t content_alignment;
192 char content[1];
193 };
194
195 } gate_memoryblock_impl_t;
196
197 1 static char const* memoryblock_interface_name(void* self)
198 {
199 (void)self;
200 1 return GATE_INTERFACE_NAME_MEMORYBLOCK;
201 }
202 10 static void memoryblock_release(void* obj)
203 {
204 10 gate_memoryblock_impl_t* self = (gate_memoryblock_impl_t*)obj;
205
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6 times.
10 if (gate_atomic_int_dec(&self->ref_counter) == 0)
206 {
207 4 gate_mem_dealloc(self);
208 }
209 10 }
210 6 static int memoryblock_retain(void* obj)
211 {
212 6 gate_memoryblock_impl_t* self = (gate_memoryblock_impl_t*)obj;
213 6 return gate_atomic_int_inc(&self->ref_counter);
214 }
215
216 6 static gate_size_t memoryblock_size(void* obj)
217 {
218 6 gate_memoryblock_impl_t* self = (gate_memoryblock_impl_t*)obj;
219 6 return self->size;
220 }
221 9 static void* memoryblock_get(void* obj)
222 {
223 9 gate_memoryblock_impl_t* self = (gate_memoryblock_impl_t*)obj;
224 9 return &self->content[0];
225 }
226
227 static GATE_INTERFACE_VTBL(gate_memoryblock) gate_memoryblock_vtbl;
228 4 static void gate_init_memoryblock_vtbl()
229 {
230
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (!gate_memoryblock_vtbl.get_interface_name)
231 {
232 GATE_INTERFACE_VTBL(gate_memoryblock) const local_vtbl =
233 {
234 &memoryblock_interface_name,
235 &memoryblock_release,
236 &memoryblock_retain,
237
238 &memoryblock_size,
239 &memoryblock_get
240 };
241 1 gate_memoryblock_vtbl = local_vtbl;
242 }
243 4 }
244
245
246 4 gate_memoryblock_t* gate_memoryblock_create(size_t data_length)
247 {
248 4 gate_memoryblock_impl_t* ret = NULL;
249 4 gate_size_t real_length = sizeof(gate_memoryblock_impl_t);
250
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (data_length > sizeof(gate_c_maxalign_t))
251 {
252 1 real_length += (data_length - sizeof(gate_c_maxalign_t));
253 }
254 4 ret = (gate_memoryblock_impl_t*)gate_mem_alloc(real_length);
255
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (ret)
256 {
257 4 gate_init_memoryblock_vtbl();
258 4 ret->vtbl = &gate_memoryblock_vtbl;
259 4 gate_atomic_int_init(&ret->ref_counter, 1);
260 4 ret->size = data_length;
261 }
262 4 return (gate_memoryblock_t*)ret;
263 }
264