GCC Code Coverage Report


Directory: src/gate/
File: src/gate/hashes.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 68 175 38.9%
Functions: 14 21 66.7%
Branches: 20 66 30.3%

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