GCC Code Coverage Report


Directory: src/gate/
File: src/gate/hashes.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 20 175 11.4%
Functions: 3 21 14.3%
Branches: 2 64 3.1%

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 gate_uint32_t gate_hash_generate(void const* data, gate_size_t data_len)
81 {
82 gate_uint8_t const* ptr = (gate_uint8_t const*)data;
83 gate_uint32_t h1 = hash_initer;
84 gate_uint32_t h2 = hash_initer;
85 gate_uint32_t chr;
86
87 while (data_len-- != 0)
88 {
89 chr = (gate_uint32_t)ptr[0];
90 GATE_HASH_GEN_UPDATE(h1, chr);
91 if (data_len-- == 0)
92 {
93 break;
94 }
95 chr = (gate_uint32_t)ptr[1];
96 GATE_HASH_GEN_UPDATE(h2, chr);
97 ptr += 2;
98 }
99 return h1 + (h2 * 1566083941);
100 }
101
102 gate_hash_code_t gate_hash_generate_1(void const* data)
103 {
104 return gate_hash_generate(data, 1);
105 }
106 gate_hash_code_t gate_hash_generate_2(void const* data)
107 {
108 return gate_hash_generate(data, 2);
109 }
110 gate_hash_code_t gate_hash_generate_4(void const* data)
111 {
112 return gate_hash_generate(data, 4);
113 }
114 gate_hash_code_t gate_hash_generate_8(void const* data)
115 {
116 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 static gate_hash_code_t gate_hash_generate_guid(void const* data)
144 {
145 return gate_hash_generate(data, sizeof(gate_guid_t));
146 }
147 static gate_hash_code_t gate_hash_generate_date(void const* data)
148 {
149 return gate_hash_generate(data, sizeof(gate_date_t));
150 }
151 static gate_hash_code_t gate_hash_generate_daytime(void const* data)
152 {
153 return gate_hash_generate(data, sizeof(gate_daytime_t));
154 }
155 static gate_hash_code_t gate_hash_generate_datetime(void const* data)
156 {
157 return gate_hash_generate(data, sizeof(gate_datetime_t));
158 }
159 static gate_hash_code_t gate_hash_generate_time(void const* data)
160 {
161 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 gate_type_id_t tid;
176 void const* ptr_member;
177 gate_type_hash_generator_t member_hashgen;
178 gate_hash_code_t member_hash;
179
180 gate_hash_generator_init(&gen);
181 gate_hash_generator_update(&gen, name, gate_str_length(name));
182
183 for (ndx = 0; ndx != len; ++ndx)
184 {
185 tid = gate_struct_get_member_type(ptr, ndx);
186 name = gate_struct_get_member_name(ptr, ndx);
187 ptr_member = gate_struct_get_member(ptr, ndx);
188 member_hashgen = gate_hash_generator_of(tid);
189 gate_hash_generator_update(&gen, &tid, sizeof(tid));
190 gate_hash_generator_update(&gen, name, gate_str_length(name));
191 if (member_hashgen)
192 {
193 member_hash = member_hashgen(ptr_member);
194 gate_hash_generator_update(&gen, &member_hash, sizeof(member_hash));
195 }
196 }
197 return gate_hash_generator_finish(&gen);
198 }
199 static gate_hash_code_t gate_hash_generate_object(void const* data)
200 {
201 gate_object_t const* obj = (gate_object_t const*)data;
202 gate_uintptr_t address = (gate_uintptr_t)obj;
203 return gate_hash_generate_address(&address);
204 }
205 static gate_hash_code_t gate_hash_generate_property(void const* data)
206 {
207 gate_property_t const* prop = (gate_property_t const*)data;
208 gate_hash_generator_context_t gen;
209 gate_uint32_t prop_type;
210 gate_bool_t b = false;
211 gate_int64_t i = 0;
212 gate_real64_t r = 0.0;
213 gate_string_t str = GATE_STRING_INIT_EMPTY;
214 gate_size_t len;
215 gate_size_t index;
216 gate_property_t const* ptr_prop;
217 gate_hash_code_t hv;
218 gate_array_t names = GATE_INIT_EMPTY;
219 gate_string_t const* ptr_name;
220
221 gate_hash_generator_init(&gen);
222
223 prop_type = gate_property_get_type(prop);
224 switch (prop_type)
225 {
226 case GATE_PROPERTY_TYPE_EMPTY:
227 break;
228 case GATE_PROPERTY_TYPE_BOOL:
229 gate_property_get_bool(prop, &b);
230 gate_hash_generator_update(&gen, b ? "1" : "0", 1);
231 break;
232 case GATE_PROPERTY_TYPE_INT:
233 gate_property_get_int(prop, &i);
234 gate_hash_generator_update(&gen, &i, sizeof(i));
235 break;
236 case GATE_PROPERTY_TYPE_REAL:
237 gate_property_get_real(prop, &r);
238 gate_hash_generator_update(&gen, &r, sizeof(r));
239 break;
240 case GATE_PROPERTY_TYPE_STRING:
241 gate_property_get_string(prop, &str);
242 gate_hash_generator_update(&gen, str.str, str.length);
243 gate_string_release(&str);
244 break;
245 case GATE_PROPERTY_TYPE_ARRAY:
246 len = gate_property_array_length(prop);
247 for (index = 0; index != len; ++index)
248 {
249 ptr_prop = gate_property_array_get(prop, index);
250 if (ptr_prop)
251 {
252 hv = gate_hash_generate_property(ptr_prop);
253 gate_hash_generator_update(&gen, &hv, sizeof(hv));
254 }
255 }
256 break;
257 case GATE_PROPERTY_TYPE_OBJECT:
258 if (gate_property_member_names(prop, &names))
259 {
260 len = gate_array_length(&names);
261 for (index = 0; index != len; ++index)
262 {
263 ptr_name = (gate_string_t const*)gate_array_get(&names, index);
264 if (ptr_name)
265 {
266 gate_hash_generator_update(&gen, ptr_name->str, ptr_name->length);
267 ptr_prop = gate_property_member_get(prop, ptr_name);
268 if (ptr_prop)
269 {
270 hv = gate_hash_generate_property(ptr_prop);
271 gate_hash_generator_update(&gen, &hv, sizeof(hv));
272 }
273 }
274 }
275 gate_array_release(&names);
276 }
277 break;
278 }
279 return gate_hash_generator_finish(&gen);
280 }
281
282
283
284
285 gate_type_hash_generator_t gate_hash_generator_of(gate_type_id_t type_id)
286 {
287 gate_type_hash_generator_t func = NULL;
288
289 switch (type_id)
290 {
291 case GATE_TYPE_VOID:
292
293 /* basic numeric types */
294 case GATE_TYPE_BOOL: return &gate_hash_generate_1;
295 case GATE_TYPE_I8: return &gate_hash_generate_1;
296 case GATE_TYPE_UI8: return &gate_hash_generate_1;
297 case GATE_TYPE_I16: return &gate_hash_generate_2;
298 case GATE_TYPE_UI16: return &gate_hash_generate_2;
299 case GATE_TYPE_I32: return &gate_hash_generate_4;
300 case GATE_TYPE_UI32: return &gate_hash_generate_4;
301 case GATE_TYPE_I64: return &gate_hash_generate_8;
302 case GATE_TYPE_UI64: return &gate_hash_generate_8;
303 case GATE_TYPE_R32: return &gate_hash_generate_4;
304 case GATE_TYPE_R64: return &gate_hash_generate_8;
305 case GATE_TYPE_ADDRESS: return &gate_hash_generate_address;
306
307 /* basic gate structures (POD) */
308 case GATE_TYPE_DATAPTR: return &gate_hash_generate_address;
309 case GATE_TYPE_FUNCPTR: return &gate_hash_generate_address;
310 case GATE_TYPE_CSTR: return &gate_hash_generate_cstring;
311 case GATE_TYPE_WSTR: return &gate_hash_generate_wstring;
312 case GATE_TYPE_GUID: return &gate_hash_generate_guid;
313 case GATE_TYPE_DATE: return &gate_hash_generate_date;
314 case GATE_TYPE_DAYTIME: return &gate_hash_generate_daytime;
315 case GATE_TYPE_DATETIME: return &gate_hash_generate_datetime;
316 case GATE_TYPE_TIME: return &gate_hash_generate_time;
317
318 /* basic generic types */
319 case GATE_TYPE_STRING: return &gate_hash_generate_string;
320 case GATE_TYPE_ARRAY: return NULL; /* not supported */
321
322 /* basic reference types */
323 case GATE_TYPE_STRUCT: return &gate_hash_generate_struct;
324 case GATE_TYPE_OBJECT: return &gate_hash_generate_object;
325 case GATE_TYPE_PROPERTY: return &gate_hash_generate_property;
326
327 /* arraylists */
328
329 /* arraylist of basic numeric types */
330 case GATE_TYPE_ARRAYLIST:
331 case GATE_TYPE_ARRAYLIST_BOOL:
332 case GATE_TYPE_ARRAYLIST_I8:
333 case GATE_TYPE_ARRAYLIST_UI8:
334 case GATE_TYPE_ARRAYLIST_I16:
335 case GATE_TYPE_ARRAYLIST_UI16:
336 case GATE_TYPE_ARRAYLIST_I32:
337 case GATE_TYPE_ARRAYLIST_UI32:
338 case GATE_TYPE_ARRAYLIST_I64:
339 case GATE_TYPE_ARRAYLIST_UI64:
340 case GATE_TYPE_ARRAYLIST_R32:
341 case GATE_TYPE_ARRAYLIST_R64:
342 case GATE_TYPE_ARRAYLIST_ADDRESS:
343
344 /* arraylist of basic gate structures (POD) */
345 case GATE_TYPE_ARRAYLIST_DATAPTR:
346 case GATE_TYPE_ARRAYLIST_FUNCPTR:
347 case GATE_TYPE_ARRAYLIST_CSTR:
348 case GATE_TYPE_ARRAYLIST_WSTR:
349 case GATE_TYPE_ARRAYLIST_GUID:
350 case GATE_TYPE_ARRAYLIST_DATE:
351 case GATE_TYPE_ARRAYLIST_DAYTIME:
352 case GATE_TYPE_ARRAYLIST_DATETIME:
353 case GATE_TYPE_ARRAYLIST_TIME:
354
355 /* arraylist of basic generic types */
356 case GATE_TYPE_ARRAYLIST_STRING:
357 case GATE_TYPE_ARRAYLIST_ARRAY:
358
359 /* arraylist of basic reference types */
360 case GATE_TYPE_ARRAYLIST_STRUCT:
361 case GATE_TYPE_ARRAYLIST_OBJECT:
362 case GATE_TYPE_ARRAYLIST_PROPERTY:
363 break;
364 }
365
366 GATE_DEBUG_ASSERT(func != NULL);
367
368 return func;
369 }
370