GCC Code Coverage Report


Directory: src/gate/
File: src/gate/hashes.c
Date: 2026-06-21 00:38:37
Exec Total Coverage
Lines: 170 176 96.6%
Functions: 21 21 100.0%
Branches: 52 66 78.8%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, 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/hashes.h"
30 #include "gate/strings.h"
31 #include "gate/debugging.h"
32 #include "gate/guids.h"
33 #include "gate/times.h"
34 #include "gate/structs.h"
35 #include "gate/objects.h"
36 #include "gate/properties.h"
37
38 static gate_uint32_t hash_initer = 5381;
39 static gate_uint32_t hash_finisher = 1566083941;
40
41 #define GATE_HASH_GEN_UPDATE(store, value) store = ((store << 5) + store) ^ value
42
43 11 void gate_hash_generator_init(gate_hash_generator_context_t* generator)
44 {
45 11 gate_mem_clear(generator, sizeof(gate_hash_generator_t));
46 11 generator->stores[0] = hash_initer;
47 11 generator->stores[1] = hash_initer;
48 11 generator->len = 0;
49 11 }
50
51
52 14 void gate_hash_generator_update(gate_hash_generator_context_t* generator, void const* data, gate_size_t data_len)
53 {
54 14 gate_uint8_t const* ptr = (gate_uint8_t const*)data;
55 gate_uint32_t chr;
56 gate_uint32_t h;
57
58 gate_hash_generator_context_t context; /* operate on local stack to speed up operations */
59
60 14 gate_mem_copy(&context, generator, sizeof(context));
61
62
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 14 times.
82 while (data_len-- != 0)
63 {
64 68 chr = (gate_uint32_t)*ptr;
65 68 h = context.stores[context.len % 2];
66 68 GATE_HASH_GEN_UPDATE(h, chr);
67 68 context.stores[context.len % 2] = h;
68 68 ++context.len;
69 68 ++ptr;
70 }
71 14 gate_mem_copy(generator, &context, sizeof(context));
72 14 }
73 11 gate_hash_code_t gate_hash_generator_finish(gate_hash_generator_context_t* generator)
74 {
75 11 return generator->stores[0] + generator->stores[1] * hash_finisher;
76 }
77
78
79
80 23 gate_uint32_t gate_hash_generate(void const* data, gate_size_t data_len)
81 {
82 23 gate_uint8_t const* ptr = (gate_uint8_t const*)data;
83 23 gate_uint32_t h1 = hash_initer;
84 23 gate_uint32_t h2 = hash_initer;
85 gate_uint32_t chr;
86
87
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 18 times.
95 while (data_len-- != 0)
88 {
89 77 chr = (gate_uint32_t)ptr[0];
90 77 GATE_HASH_GEN_UPDATE(h1, chr);
91
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 72 times.
77 if (data_len-- == 0)
92 {
93 5 break;
94 }
95 72 chr = (gate_uint32_t)ptr[1];
96 72 GATE_HASH_GEN_UPDATE(h2, chr);
97 72 ptr += 2;
98 }
99 23 return h1 + (h2 * 1566083941);
100 }
101
102 3 gate_hash_code_t gate_hash_generate_1(void const* data)
103 {
104 3 return gate_hash_generate(data, 1);
105 }
106 2 gate_hash_code_t gate_hash_generate_2(void const* data)
107 {
108 2 return gate_hash_generate(data, 2);
109 }
110 3 gate_hash_code_t gate_hash_generate_4(void const* data)
111 {
112 3 return gate_hash_generate(data, 4);
113 }
114 3 gate_hash_code_t gate_hash_generate_8(void const* data)
115 {
116 3 return gate_hash_generate(data, 8);
117 }
118 3 static gate_hash_code_t GATE_CALL gate_hash_generate_address(void const* data)
119 {
120 3 return gate_hash_generate(data, sizeof(gate_uintptr_t));
121 }
122 1 static gate_hash_code_t GATE_CALL gate_hash_generate_cstring(void const* data)
123 {
124 1 gate_const_str8_t const* ptr = (gate_const_str8_t const*)data;
125 1 gate_size_t len = gate_str_length(*ptr);
126 1 return gate_hash_generate(*ptr, len);
127 }
128 1 static gate_hash_code_t GATE_CALL gate_hash_generate_wstring(void const* data)
129 {
130 1 wchar_t const* const* ptr = (wchar_t const* const*)data;
131 1 gate_size_t len = 0;
132 1 wchar_t const* s = *ptr;
133
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (s)
134 {
135
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 while (*s)
136 {
137 3 ++len;
138 3 ++s;
139 }
140 }
141 1 return gate_hash_generate(*ptr, len * sizeof(wchar_t));
142 }
143 1 gate_hash_code_t gate_hash_generate_guid(void const* data)
144 {
145 1 return gate_hash_generate(data, sizeof(gate_guid_t));
146 }
147 1 gate_hash_code_t gate_hash_generate_date(void const* data)
148 {
149 1 return gate_hash_generate(data, sizeof(gate_date_t));
150 }
151 1 gate_hash_code_t gate_hash_generate_daytime(void const* data)
152 {
153 1 return gate_hash_generate(data, sizeof(gate_daytime_t));
154 }
155 1 gate_hash_code_t gate_hash_generate_datetime(void const* data)
156 {
157 1 return gate_hash_generate(data, sizeof(gate_datetime_t));
158 }
159 1 gate_hash_code_t gate_hash_generate_time(void const* data)
160 {
161 1 return gate_hash_generate(data, sizeof(gate_time_t));
162 }
163 2 gate_hash_code_t gate_hash_generate_string(void const* data)
164 {
165 2 gate_string_t const* ptr = (gate_string_t const*)data;
166 2 return gate_hash_generate(gate_string_ptr(ptr, 0), gate_string_length(ptr));
167 }
168 1 static gate_hash_code_t GATE_CALL gate_hash_generate_struct(void const* data)
169 {
170 1 gate_struct_ptr_t const* ptrptr = (gate_struct_ptr_t const*)data;
171 1 gate_struct_ptr_t ptr = *ptrptr;
172 gate_hash_generator_context_t gen;
173 1 char const* name = gate_struct_get_name(ptr);
174 1 gate_size_t len = gate_struct_get_member_count(ptr);
175 gate_size_t ndx;
176
177 1 gate_hash_generator_init(&gen);
178 1 gate_hash_generator_update(&gen, name, gate_str_length(name));
179
180
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (ndx = 0; ndx != len; ++ndx)
181 {
182 1 gate_type_id_t tid = gate_struct_get_member_type(ptr, ndx);
183 1 void const* ptr_member = gate_struct_get_member(ptr, ndx);
184 1 gate_type_hash_generator_t member_hashgen = gate_hash_generator_of(tid);
185
186 1 name = gate_struct_get_member_name(ptr, ndx);
187 1 gate_hash_generator_update(&gen, &tid, sizeof(tid));
188 1 gate_hash_generator_update(&gen, name, gate_str_length(name));
189
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (member_hashgen)
190 {
191 1 gate_hash_code_t member_hash = member_hashgen(ptr_member);
192 1 gate_hash_generator_update(&gen, &member_hash, sizeof(member_hash));
193 }
194 }
195 1 return gate_hash_generator_finish(&gen);
196 }
197 1 static gate_hash_code_t GATE_CALL gate_hash_generate_object(void const* data)
198 {
199 1 gate_object_t const* obj = (gate_object_t const*)data;
200 1 gate_uintptr_t address = (gate_uintptr_t)obj;
201 1 return gate_hash_generate_address(&address);
202 }
203 9 static gate_hash_code_t GATE_CALL gate_hash_generate_property(void const* data)
204 {
205 9 gate_property_t const* prop = (gate_property_t const*)data;
206 gate_hash_generator_context_t gen;
207 gate_uint32_t prop_type;
208 9 gate_bool_t b = false;
209 9 gate_int64_t i = 0;
210 9 gate_real64_t r = 0.0;
211 9 gate_string_t str = GATE_STRING_INIT_EMPTY;
212 gate_size_t len;
213 gate_size_t index;
214 gate_property_t const* ptr_prop;
215 gate_hash_code_t hv;
216
217 9 gate_hash_generator_init(&gen);
218
219 9 prop_type = gate_property_get_type(prop);
220
7/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
9 switch (prop_type)
221 {
222 1 case GATE_PROPERTY_TYPE_EMPTY:
223 1 break;
224 2 case GATE_PROPERTY_TYPE_BOOL:
225 2 gate_property_get_bool(prop, &b);
226
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 gate_hash_generator_update(&gen, b ? "1" : "0", 1);
227 2 break;
228 1 case GATE_PROPERTY_TYPE_INT:
229 1 gate_property_get_int(prop, &i);
230 1 gate_hash_generator_update(&gen, &i, sizeof(i));
231 1 break;
232 2 case GATE_PROPERTY_TYPE_REAL:
233 2 gate_property_get_real(prop, &r);
234 2 gate_hash_generator_update(&gen, &r, sizeof(r));
235 2 break;
236 1 case GATE_PROPERTY_TYPE_STRING:
237 1 gate_property_get_string(prop, &str);
238 1 gate_hash_generator_update(&gen, str.str, str.length);
239 1 gate_string_release(&str);
240 1 break;
241 1 case GATE_PROPERTY_TYPE_ARRAY:
242 1 len = gate_property_array_length(prop);
243
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (index = 0; index != len; ++index)
244 {
245 1 ptr_prop = gate_property_array_get(prop, index);
246
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_prop)
247 {
248 1 hv = gate_hash_generate_property(ptr_prop);
249 1 gate_hash_generator_update(&gen, &hv, sizeof(hv));
250 }
251 }
252 1 break;
253 1 case GATE_PROPERTY_TYPE_OBJECT:
254 {
255 1 gate_array_t names = GATE_INIT_EMPTY;
256
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_property_member_names(prop, &names))
257 {
258 1 len = gate_array_length(&names);
259
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (index = 0; index != len; ++index)
260 {
261 1 gate_string_t const* ptr_name = (gate_string_t const*)gate_array_get(&names, index);
262
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_name)
263 {
264 1 gate_hash_generator_update(&gen, ptr_name->str, ptr_name->length);
265 1 ptr_prop = gate_property_member_get(prop, ptr_name);
266
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_prop)
267 {
268 1 hv = gate_hash_generate_property(ptr_prop);
269 1 gate_hash_generator_update(&gen, &hv, sizeof(hv));
270 }
271 }
272 }
273 1 gate_array_release(&names);
274 }
275 1 break;
276 }
277 }
278 9 return gate_hash_generator_finish(&gen);
279 }
280
281
282
283
284 30 gate_type_hash_generator_t gate_hash_generator_of(gate_type_id_t type_id)
285 {
286 30 gate_type_hash_generator_t func = NULL;
287
288
24/28
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 1 times.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 1 times.
✓ Branch 17 taken 1 times.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 1 times.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 24 taken 1 times.
✓ Branch 25 taken 7 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
30 switch (type_id)
289 {
290 1 case GATE_TYPE_VOID:
291
292 /* basic numeric types */
293 1 case GATE_TYPE_BOOL: return &gate_hash_generate_1;
294 1 case GATE_TYPE_I8: return &gate_hash_generate_1;
295 1 case GATE_TYPE_UI8: return &gate_hash_generate_1;
296 1 case GATE_TYPE_I16: return &gate_hash_generate_2;
297 1 case GATE_TYPE_UI16: return &gate_hash_generate_2;
298 1 case GATE_TYPE_I32: return &gate_hash_generate_4;
299 1 case GATE_TYPE_UI32: return &gate_hash_generate_4;
300 1 case GATE_TYPE_I64: return &gate_hash_generate_8;
301 1 case GATE_TYPE_UI64: return &gate_hash_generate_8;
302 1 case GATE_TYPE_R32: return &gate_hash_generate_4;
303 1 case GATE_TYPE_R64: return &gate_hash_generate_8;
304 case GATE_TYPE_ADDRESS: return &gate_hash_generate_address;
305
306 /* basic gate structures (POD) */
307 1 case GATE_TYPE_DATAPTR: return &gate_hash_generate_address;
308 1 case GATE_TYPE_FUNCPTR: return &gate_hash_generate_address;
309 1 case GATE_TYPE_CSTR: return &gate_hash_generate_cstring;
310 1 case GATE_TYPE_WSTR: return &gate_hash_generate_wstring;
311 1 case GATE_TYPE_GUID: return &gate_hash_generate_guid;
312 1 case GATE_TYPE_DATE: return &gate_hash_generate_date;
313 1 case GATE_TYPE_DAYTIME: return &gate_hash_generate_daytime;
314 1 case GATE_TYPE_DATETIME: return &gate_hash_generate_datetime;
315 1 case GATE_TYPE_TIME: return &gate_hash_generate_time;
316
317 /* basic generic types */
318 1 case GATE_TYPE_STRING: return &gate_hash_generate_string;
319 case GATE_TYPE_ARRAY: return NULL; /* not supported */
320
321 /* basic reference types */
322 1 case GATE_TYPE_STRUCT: return &gate_hash_generate_struct;
323 1 case GATE_TYPE_OBJECT: return &gate_hash_generate_object;
324 7 case GATE_TYPE_PROPERTY: return &gate_hash_generate_property;
325
326 /* arraylists */
327
328 /* arraylist of basic numeric types */
329 case GATE_TYPE_ARRAYLIST:
330 case GATE_TYPE_ARRAYLIST_BOOL:
331 case GATE_TYPE_ARRAYLIST_I8:
332 case GATE_TYPE_ARRAYLIST_UI8:
333 case GATE_TYPE_ARRAYLIST_I16:
334 case GATE_TYPE_ARRAYLIST_UI16:
335 case GATE_TYPE_ARRAYLIST_I32:
336 case GATE_TYPE_ARRAYLIST_UI32:
337 case GATE_TYPE_ARRAYLIST_I64:
338 case GATE_TYPE_ARRAYLIST_UI64:
339 case GATE_TYPE_ARRAYLIST_R32:
340 case GATE_TYPE_ARRAYLIST_R64:
341 case GATE_TYPE_ARRAYLIST_ADDRESS:
342
343 /* arraylist of basic gate structures (POD) */
344 case GATE_TYPE_ARRAYLIST_DATAPTR:
345 case GATE_TYPE_ARRAYLIST_FUNCPTR:
346 case GATE_TYPE_ARRAYLIST_CSTR:
347 case GATE_TYPE_ARRAYLIST_WSTR:
348 case GATE_TYPE_ARRAYLIST_GUID:
349 case GATE_TYPE_ARRAYLIST_DATE:
350 case GATE_TYPE_ARRAYLIST_DAYTIME:
351 case GATE_TYPE_ARRAYLIST_DATETIME:
352 case GATE_TYPE_ARRAYLIST_TIME:
353
354 /* arraylist of basic generic types */
355 case GATE_TYPE_ARRAYLIST_STRING:
356 case GATE_TYPE_ARRAYLIST_ARRAY:
357
358 /* arraylist of basic reference types */
359 case GATE_TYPE_ARRAYLIST_STRUCT:
360 case GATE_TYPE_ARRAYLIST_OBJECT:
361 case GATE_TYPE_ARRAYLIST_PROPERTY:
362 break;
363 }
364
365 GATE_DEBUG_ASSERT(func != NULL);
366
367 return func;
368 }
369