1 /********************************************************************/
2 /*                                                                  */
3 /*  hsh_rtl.c     Primitive actions for the hash map type.          */
4 /*  Copyright (C) 1989 - 2016, 2018  Thomas Mertes                  */
5 /*                                                                  */
6 /*  This file is part of the Seed7 Runtime Library.                 */
7 /*                                                                  */
8 /*  The Seed7 Runtime Library is free software; you can             */
9 /*  redistribute it and/or modify it under the terms of the GNU     */
10 /*  Lesser General Public License as published by the Free Software */
11 /*  Foundation; either version 2.1 of the License, or (at your      */
12 /*  option) any later version.                                      */
13 /*                                                                  */
14 /*  The Seed7 Runtime Library is distributed in the hope that it    */
15 /*  will be useful, but WITHOUT ANY WARRANTY; without even the      */
16 /*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
17 /*  PURPOSE.  See the GNU Lesser General Public License for more    */
18 /*  details.                                                        */
19 /*                                                                  */
20 /*  You should have received a copy of the GNU Lesser General       */
21 /*  Public License along with this program; if not, write to the    */
22 /*  Free Software Foundation, Inc., 51 Franklin Street,             */
23 /*  Fifth Floor, Boston, MA  02110-1301, USA.                       */
24 /*                                                                  */
25 /*  Module: Seed7 Runtime Library                                   */
26 /*  File: seed7/src/hsh_rtl.c                                       */
27 /*  Changes: 2005, 2006, 2007, 2013, 2016  Thomas Mertes            */
28 /*  Content: Primitive actions for the hash map type.               */
29 /*                                                                  */
30 /*  The functions from this file should only be used in compiled    */
31 /*  Seed7 programs. The interpreter should not use functions of     */
32 /*  this file.                                                      */
33 /*                                                                  */
34 /*  The functions in this file use type declarations from the       */
35 /*  include file data_rtl.h instead of data.h. Therefore the types  */
36 /*  rtlHashElemType and rtlHashType are declared different than the */
37 /*  types hashElemType and hashType in the interpreter.             */
38 /*                                                                  */
39 /********************************************************************/
40 
41 #define LOG_FUNCTIONS 0
42 #define VERBOSE_EXCEPTIONS 0
43 
44 #include "version.h"
45 
46 #include "stdlib.h"
47 #include "stdio.h"
48 #include "string.h"
49 
50 #include "common.h"
51 #include "data_rtl.h"
52 #include "heaputl.h"
53 #include "striutl.h"
54 #include "rtl_err.h"
55 #include "int_rtl.h"
56 
57 #undef EXTERN
58 #define EXTERN
59 #include "hsh_rtl.h"
60 
61 
62 #define TABLE_BITS 10
63 #define TABLE_SIZE(bits) ((unsigned int) 1 << (bits))
64 #define TABLE_MASK(bits) (TABLE_SIZE(bits)-1)
65 
66 
67 
free_helem(const const_rtlHashElemType old_helem,const destrFuncType key_destr_func,const destrFuncType data_destr_func)68 static memSizeType free_helem (const const_rtlHashElemType old_helem,
69     const destrFuncType key_destr_func, const destrFuncType data_destr_func)
70 
71   {
72     memSizeType freed = 1;
73 
74   /* free_helem */
75     key_destr_func(old_helem->key.value.genericValue);
76     data_destr_func(old_helem->data.value.genericValue);
77     if (old_helem->next_less != NULL) {
78       freed += free_helem(old_helem->next_less, key_destr_func,
79                          data_destr_func);
80     } /* if */
81     if (old_helem->next_greater != NULL) {
82       freed += free_helem(old_helem->next_greater, key_destr_func,
83                          data_destr_func);
84     } /* if */
85     FREE_RECORD(old_helem, rtlHashElemRecord, count.rtl_helem);
86     return freed;
87   } /* free_helem */
88 
89 
90 
free_hash(const const_rtlHashType old_hash,const destrFuncType key_destr_func,const destrFuncType data_destr_func)91 static void free_hash (const const_rtlHashType old_hash,
92     const destrFuncType key_destr_func, const destrFuncType data_destr_func)
93 
94   {
95     memSizeType to_free;
96     unsigned int number;
97     const rtlHashElemType *table;
98 
99   /* free_hash */
100     if (old_hash != NULL) {
101       to_free = old_hash->size;
102       if (to_free != 0) {
103         number = old_hash->table_size;
104         table = old_hash->table;
105         do {
106           do {
107             number--;
108           } while (table[number] == NULL);
109           to_free -= free_helem(table[number], key_destr_func, data_destr_func);
110         } while (to_free != 0);
111       } /* if */
112       FREE_RTL_HASH(old_hash, old_hash->table_size);
113     } /* if */
114   } /* free_hash */
115 
116 
117 
new_helem(genericType key,genericType data,const createFuncType key_create_func,const createFuncType data_create_func,errInfoType * err_info)118 static rtlHashElemType new_helem (genericType key, genericType data,
119     const createFuncType key_create_func, const createFuncType data_create_func,
120     errInfoType *err_info)
121 
122   {
123     rtlHashElemType helem;
124 
125   /* new_helem */
126     /* printf("new_helem(" FMT_U_GEN ", " FMT_U_GEN ")\n", key, data); */
127     if (unlikely(!ALLOC_RECORD(helem, rtlHashElemRecord, count.rtl_helem))) {
128       *err_info = MEMORY_ERROR;
129     } else {
130       helem->key.value.genericValue = key_create_func(key);
131       helem->data.value.genericValue = data_create_func(data);
132       helem->next_less = NULL;
133       helem->next_greater = NULL;
134       /* printf("new_helem(" FMT_U_GEN ", " FMT_U_GEN ")\n",
135           helem->key.value.genericValue,
136           helem->data.value.genericValue); */
137     } /* if */
138     return helem;
139   } /* new_helem */
140 
141 
142 
new_hash(unsigned int bits)143 static rtlHashType new_hash (unsigned int bits)
144 
145   {
146     rtlHashType hash;
147 
148   /* new_hash */
149     if (likely(ALLOC_RTL_HASH(hash, TABLE_SIZE(bits)))) {
150       hash->bits = bits;
151       hash->mask = TABLE_MASK(bits);
152       hash->table_size = TABLE_SIZE(bits);
153       hash->size = 0;
154       memset(hash->table, 0, hash->table_size * sizeof(rtlHashElemType));
155     } /* if */
156     return hash;
157   } /* new_hash */
158 
159 
160 
create_helem(const const_rtlHashElemType source_helem,const createFuncType key_create_func,const createFuncType data_create_func,errInfoType * err_info)161 static rtlHashElemType create_helem (const const_rtlHashElemType source_helem,
162     const createFuncType key_create_func, const createFuncType data_create_func,
163     errInfoType *err_info)
164 
165   {
166     rtlHashElemType dest_helem;
167 
168   /* create_helem */
169     if (unlikely(!ALLOC_RECORD(dest_helem, rtlHashElemRecord, count.rtl_helem))) {
170       *err_info = MEMORY_ERROR;
171     } else {
172       dest_helem->key.value.genericValue =
173           key_create_func(source_helem->key.value.genericValue);
174       dest_helem->data.value.genericValue =
175           data_create_func(source_helem->data.value.genericValue);
176       if (source_helem->next_less != NULL) {
177         dest_helem->next_less = create_helem(source_helem->next_less,
178             key_create_func, data_create_func, err_info);
179       } else {
180         dest_helem->next_less = NULL;
181       } /* if */
182       if (source_helem->next_greater != NULL) {
183         dest_helem->next_greater = create_helem(source_helem->next_greater,
184             key_create_func, data_create_func, err_info);
185       } else {
186         dest_helem->next_greater = NULL;
187       } /* if */
188     } /* if */
189     return dest_helem;
190   } /* create_helem */
191 
192 
193 
create_hash(const const_rtlHashType source_hash,const createFuncType key_create_func,const createFuncType data_create_func,errInfoType * err_info)194 static rtlHashType create_hash (const const_rtlHashType source_hash,
195     const createFuncType key_create_func, const createFuncType data_create_func,
196     errInfoType *err_info)
197 
198   {
199     unsigned int table_size;
200     unsigned int number;
201     const rtlHashElemType *source_helem;
202     rtlHashElemType *dest_helem;
203     rtlHashType dest_hash;
204 
205   /* create_hash */
206     table_size = source_hash->table_size;
207     if (unlikely(!ALLOC_RTL_HASH(dest_hash, table_size))) {
208       *err_info = MEMORY_ERROR;
209     } else {
210       dest_hash->bits = source_hash->bits;
211       dest_hash->mask = source_hash->mask;
212       dest_hash->table_size = table_size;
213       dest_hash->size = source_hash->size;
214       if (source_hash->size == 0) {
215         memset(dest_hash->table, 0, table_size * sizeof(rtlHashElemType));
216       } else {
217         number = table_size;
218         source_helem = &source_hash->table[0];
219         dest_helem = &dest_hash->table[0];
220         while (number > 0) {
221           while (number > 0 && *source_helem == NULL) {
222             *dest_helem = NULL;
223             number--;
224             source_helem++;
225             dest_helem++;
226           } /* while */
227           if (number > 0 && *source_helem != NULL) {
228             *dest_helem = create_helem(*source_helem, key_create_func,
229                                        data_create_func, err_info);
230             number--;
231             source_helem++;
232             dest_helem++;
233           } /* if */
234         } /* while */
235       } /* if */
236     } /* if */
237     return dest_hash;
238   } /* create_hash */
239 
240 
241 
copy_hash(const rtlHashType dest_hash,const const_rtlHashType source_hash,const createFuncType key_create_func,const createFuncType data_create_func,const destrFuncType key_destr_func,const destrFuncType data_destr_func,errInfoType * err_info)242 static void copy_hash (const rtlHashType dest_hash, const const_rtlHashType source_hash,
243     const createFuncType key_create_func, const createFuncType data_create_func,
244     const destrFuncType key_destr_func, const destrFuncType data_destr_func,
245     errInfoType *err_info)
246 
247   {
248     unsigned int number;
249     const rtlHashElemType *source_helem;
250     rtlHashElemType *dest_helem;
251 
252   /* copy_hash */
253     logFunction(printf("copy_hash(" FMT_X_MEM ", " FMT_X_MEM ")\n",
254                        (memSizeType) dest_hash, (memSizeType) source_hash););
255     dest_hash->bits = source_hash->bits;
256     dest_hash->mask = source_hash->mask;
257     dest_hash->size = source_hash->size;
258     number = source_hash->table_size;
259     source_helem = &source_hash->table[0];
260     dest_helem = &dest_hash->table[0];
261     while (number > 0 && *err_info == OKAY_NO_ERROR) {
262       if (*dest_helem != NULL) {
263         free_helem(*dest_helem, key_destr_func, data_destr_func);
264       } /* if */
265       if (*source_helem != NULL) {
266         *dest_helem = create_helem(*source_helem, key_create_func, data_create_func,
267                                    err_info);
268       } else {
269         *dest_helem = NULL;
270       } /* if */
271       number--;
272       source_helem++;
273       dest_helem++;
274     } /* while */
275     logFunction(printf("copy_hash -->\n"););
276   } /* copy_hash */
277 
278 
279 
keys_helem(const rtlArrayType key_array,memSizeType arr_pos,const_rtlHashElemType curr_helem,const createFuncType key_create_func)280 static memSizeType keys_helem (const rtlArrayType key_array,
281     memSizeType arr_pos, const_rtlHashElemType curr_helem,
282     const createFuncType key_create_func)
283 
284   { /* keys_helem */
285     do {
286       arr_pos--;
287       key_array->arr[arr_pos].value.genericValue =
288           key_create_func(curr_helem->key.value.genericValue);
289       if (curr_helem->next_less != NULL) {
290         arr_pos = keys_helem(key_array, arr_pos, curr_helem->next_less,
291                              key_create_func);
292       } /* if */
293       curr_helem = curr_helem->next_greater;
294     } while (curr_helem != NULL);
295     return arr_pos;
296   } /* keys_helem */
297 
298 
299 
keys_hash(const const_rtlHashType curr_hash,const createFuncType key_create_func)300 static inline rtlArrayType keys_hash (const const_rtlHashType curr_hash,
301     const createFuncType key_create_func)
302 
303   {
304     memSizeType arr_pos;
305     memSizeType number;
306     const rtlHashElemType *table;
307     rtlArrayType key_array;
308 
309   /* keys_hash */
310     if (unlikely(curr_hash->size > INTTYPE_MAX ||
311                  !ALLOC_RTL_ARRAY(key_array, curr_hash->size))) {
312       raise_error(MEMORY_ERROR);
313       key_array = NULL;
314     } else {
315       key_array->min_position = 1;
316       key_array->max_position = (intType) curr_hash->size;
317       if (curr_hash->size != 0) {
318         arr_pos = curr_hash->size;
319         number = curr_hash->table_size;
320         table = curr_hash->table;
321         do {
322           do {
323             number--;
324           } while (table[number] == NULL);
325           arr_pos = keys_helem(key_array, arr_pos, table[number],
326                                key_create_func);
327         } while (arr_pos != 0);
328       } /* if */
329     } /* if */
330     return key_array;
331   } /* keys_hash */
332 
333 
334 
values_helem(const rtlArrayType value_array,memSizeType arr_pos,const_rtlHashElemType curr_helem,const createFuncType value_create_func)335 static memSizeType values_helem (const rtlArrayType value_array,
336     memSizeType arr_pos, const_rtlHashElemType curr_helem,
337     const createFuncType value_create_func)
338 
339   { /* values_helem */
340     do {
341       arr_pos--;
342       value_array->arr[arr_pos].value.genericValue =
343           value_create_func(curr_helem->data.value.genericValue);
344       if (curr_helem->next_less != NULL) {
345         arr_pos = values_helem(value_array, arr_pos, curr_helem->next_less,
346                                value_create_func);
347       } /* if */
348       curr_helem = curr_helem->next_greater;
349     } while (curr_helem != NULL);
350     return arr_pos;
351   } /* values_helem */
352 
353 
354 
values_hash(const const_rtlHashType curr_hash,const createFuncType value_create_func)355 static inline rtlArrayType values_hash (const const_rtlHashType curr_hash,
356     const createFuncType value_create_func)
357 
358   {
359     memSizeType arr_pos;
360     memSizeType number;
361     const rtlHashElemType *table;
362     rtlArrayType value_array;
363 
364   /* values_hash */
365     if (unlikely(curr_hash->size > INTTYPE_MAX ||
366                  !ALLOC_RTL_ARRAY(value_array, curr_hash->size))) {
367       raise_error(MEMORY_ERROR);
368       value_array = NULL;
369     } else {
370       value_array->min_position = 1;
371       value_array->max_position = (intType) curr_hash->size;
372       if (curr_hash->size != 0) {
373         arr_pos = curr_hash->size;
374         number = curr_hash->table_size;
375         table = curr_hash->table;
376         do {
377           do {
378             number--;
379           } while (table[number] == NULL);
380           arr_pos = values_helem(value_array, arr_pos, table[number],
381                                  value_create_func);
382         } while (arr_pos != 0);
383       } /* if */
384     } /* if */
385     return value_array;
386   } /* values_hash */
387 
388 
389 
get_helem_elem(const_rtlHashElemType * hash_elem,memSizeType arr_pos,const_rtlHashElemType curr_helem)390 static memSizeType get_helem_elem (const_rtlHashElemType *hash_elem,
391     memSizeType arr_pos, const_rtlHashElemType curr_helem)
392 
393   { /* get_helem_elem */
394     do {
395       arr_pos--;
396       if (arr_pos == 0) {
397         *hash_elem = curr_helem;
398       } else {
399         if (curr_helem->next_less != NULL) {
400           arr_pos = get_helem_elem(hash_elem, arr_pos, curr_helem->next_less);
401         } /* if */
402         curr_helem = curr_helem->next_greater;
403       } /* if */
404     } while (curr_helem != NULL && arr_pos != 0);
405     return arr_pos;
406   } /* get_helem_elem */
407 
408 
409 
get_hash_elem(const const_rtlHashType curr_hash,memSizeType arr_pos)410 static inline const_rtlHashElemType get_hash_elem (const const_rtlHashType curr_hash,
411     memSizeType arr_pos)
412 
413   {
414     memSizeType number;
415     const rtlHashElemType *table;
416     const_rtlHashElemType hash_elem = NULL;
417 
418   /* get_hash_elem */
419     if (arr_pos >= 1 && arr_pos <= curr_hash->size) {
420       number = curr_hash->table_size;
421       table = curr_hash->table;
422       do {
423         do {
424           number--;
425         } while (table[number] == NULL);
426         arr_pos = get_helem_elem(&hash_elem, arr_pos, table[number]);
427       } while (arr_pos != 0);
428     } /* if */
429     return hash_elem;
430   } /* get_hash_elem */
431 
432 
433 
434 #ifdef OUT_OF_ORDER
dump_helem(const_rtlHashElemType curr_helem)435 static void dump_helem (const_rtlHashElemType curr_helem)
436 
437   { /* dump_helem */
438     printf("key: %ld, %lx, %f / value: %ld, %lx, %f\n",
439            curr_helem->key.value.intValue,
440            curr_helem->key.value.genericValue,
441            curr_helem->key.value.floatValue,
442            curr_helem->data.value.intValue,
443            curr_helem->data.value.genericValue,
444            curr_helem->data.value.floatValue);
445     if (curr_helem->next_less != NULL) {
446       dump_helem(curr_helem->next_less);
447     } /* if */
448     if (curr_helem->next_greater != NULL) {
449       dump_helem(curr_helem->next_greater);
450     } /* if */
451   } /* dump_helem */
452 
453 
454 
dump_hash(const const_rtlHashType curr_hash)455 static void dump_hash (const const_rtlHashType curr_hash)
456 
457   {
458     memSizeType number;
459     const rtlHashElemType *curr_helem;
460 
461   /* dump_hash */
462     number = curr_hash->table_size;
463     curr_helem = &curr_hash->table[0];
464     while (number > 0) {
465       if (*curr_helem != NULL) {
466         dump_helem(*curr_helem);
467       } /* if */
468       number--;
469       curr_helem++;
470     } /* while */
471   } /* dump_hash */
472 #endif
473 
474 
475 
476 /**
477  *  Hash membership test.
478  *  Determine if 'aKey' is a member of the hash map 'aHashMap'.
479  *  @return TRUE if 'aKey' is a member of 'aHashMap',
480  *          FALSE otherwise.
481  */
hshContains(const const_rtlHashType aHashMap,const genericType aKey,intType hashcode,compareType cmp_func)482 boolType hshContains (const const_rtlHashType aHashMap, const genericType aKey,
483     intType hashcode, compareType cmp_func)
484 
485   {
486     const_rtlHashElemType hashelem;
487     intType cmp;
488     boolType result = FALSE;
489 
490   /* hshContains */
491     logFunction(printf("hshContains(" FMT_X_MEM ", " FMT_U_GEN ", " FMT_U ")\n",
492                        (memSizeType) aHashMap, aKey, hashcode););
493     hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
494     while (hashelem != NULL) {
495 /*
496 printf("sizeof(hashelem->key.value.genericValue)=%lu\n",
497     sizeof(hashelem->key.value.genericValue));
498 printf("sizeof(aKey)=%lu\n", sizeof(aKey));
499 printf("%llX\n", hashelem->key.value.genericValue);
500 printf("%lX\n", (long unsigned) hashelem->key.value.genericValue);
501 printf("%llX\n", aKey);
502 printf("%lX\n", (long unsigned) aKey);
503 */
504       cmp = cmp_func(hashelem->key.value.genericValue, aKey);
505       if (cmp < 0) {
506         hashelem = hashelem->next_less;
507       } else if (unlikely(cmp == 0)) {
508         result = TRUE;
509         hashelem = NULL;
510       } else {
511         hashelem = hashelem->next_greater;
512       } /* if */
513     } /* while */
514     logFunction(printf("hshContains(" FMT_X_MEM ", " FMT_U_GEN ", " FMT_U ") --> %d\n",
515                        (memSizeType) aHashMap, aKey, hashcode, result););
516     return result;
517   } /* hshContains */
518 
519 
520 
521 /**
522  *  Assign source to *dest.
523  *  A copy function assumes that *dest contains a legal value.
524  *  @exception MEMORY_ERROR Not enough memory to create dest.
525  */
hshCpy(rtlHashType * const dest,const const_rtlHashType source,const createFuncType key_create_func,const destrFuncType key_destr_func,const createFuncType data_create_func,const destrFuncType data_destr_func)526 void hshCpy (rtlHashType *const dest, const const_rtlHashType source,
527     const createFuncType key_create_func, const destrFuncType key_destr_func,
528     const createFuncType data_create_func, const destrFuncType data_destr_func)
529 
530   {
531     errInfoType err_info = OKAY_NO_ERROR;
532 
533   /* hshCpy */
534     logFunction(printf("hshCpy(" FMT_X_MEM ", " FMT_X_MEM ")\n",
535                        (memSizeType) *dest, (memSizeType) source););
536     if ((*dest)->table_size == source->table_size) {
537       /* The following check avoids an error for: aHash := aHash; */
538       if (*dest != source) {
539         copy_hash(*dest, source,
540             key_create_func, data_create_func,
541             key_destr_func, data_destr_func, &err_info);
542       } /* if */
543     } else {
544       free_hash(*dest, key_destr_func, data_destr_func);
545       *dest = create_hash(source,
546           key_create_func, data_create_func, &err_info);
547     } /* if */
548     if (unlikely(err_info != OKAY_NO_ERROR)) {
549       free_hash(*dest, key_destr_func, data_destr_func);
550       *dest = NULL;
551       raise_error(MEMORY_ERROR);
552     } /* if */
553     logFunction(printf("hshCpy -->\n"););
554   } /* hshCpy */
555 
556 
557 
558 /**
559  *  Return a copy of source, that can be assigned to a new destination.
560  *  It is assumed that the destination of the assignment is undefined.
561  *  Create functions can be used to initialize Seed7 constants.
562  *  @return a copy of source.
563  *  @exception MEMORY_ERROR Not enough memory to represent the result.
564  */
hshCreate(const const_rtlHashType source,const createFuncType key_create_func,const destrFuncType key_destr_func,const createFuncType data_create_func,const destrFuncType data_destr_func)565 rtlHashType hshCreate (const const_rtlHashType source,
566     const createFuncType key_create_func, const destrFuncType key_destr_func,
567     const createFuncType data_create_func, const destrFuncType data_destr_func)
568 
569   {
570     errInfoType err_info = OKAY_NO_ERROR;
571     rtlHashType result;
572 
573   /* hshCreate */
574     result = create_hash(source,
575         key_create_func, data_create_func, &err_info);
576     if (unlikely(err_info != OKAY_NO_ERROR)) {
577       free_hash(result, key_destr_func, data_destr_func);
578       result = NULL;
579       raise_error(MEMORY_ERROR);
580     } /* if */
581     return result;
582   } /* hshCreate */
583 
584 
585 
586 /**
587  *  Free the memory referred by 'old_hash'.
588  *  After hshDestr is left 'old_hash' refers to not existing memory.
589  *  The memory where 'old_hash' is stored can be freed afterwards.
590  */
hshDestr(const const_rtlHashType old_hash,const destrFuncType key_destr_func,const destrFuncType data_destr_func)591 void hshDestr (const const_rtlHashType old_hash, const destrFuncType key_destr_func,
592     const destrFuncType data_destr_func)
593 
594   { /* hshDestr */
595     logFunction(printf("hshDestr(" FMT_X_MEM ")\n", (memSizeType) old_hash););
596     free_hash(old_hash, key_destr_func, data_destr_func);
597     logFunction(printf("hshDestr -->\n"););
598   } /* hshDestr */
599 
600 
601 
602 /**
603  *  Create an empty hash table.
604  *  @return an empty hash table.
605  *  @exception MEMORY_ERROR Not enough memory for the result.
606  */
hshEmpty(void)607 rtlHashType hshEmpty (void)
608 
609   {
610     rtlHashType result;
611 
612   /* hshEmpty */
613     result = new_hash(TABLE_BITS);
614     if (unlikely(result == NULL)) {
615       raise_error(MEMORY_ERROR);
616     } /* if */
617     return result;
618   } /* hshEmpty */
619 
620 
621 
622 /**
623  *  Remove the element with the key 'aKey' from the hash map 'aHashMap'.
624  */
hshExcl(const rtlHashType aHashMap,const genericType aKey,intType hashcode,compareType cmp_func,const destrFuncType key_destr_func,const destrFuncType data_destr_func)625 void hshExcl (const rtlHashType aHashMap, const genericType aKey,
626     intType hashcode, compareType cmp_func, const destrFuncType key_destr_func,
627     const destrFuncType data_destr_func)
628 
629   {
630     rtlHashElemType *delete_pos;
631     rtlHashElemType hashelem;
632     rtlHashElemType greater_hashelems;
633     rtlHashElemType old_hashelem;
634     intType cmp;
635 
636   /* hshExcl */
637     logFunction(printf("hshExcl(" FMT_X_MEM ", " FMT_U_GEN ", "
638                        FMT_U ") size=" FMT_U_MEM "\n",
639                        (memSizeType) aHashMap, aKey, hashcode, aHashMap->size););
640     delete_pos = &aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
641     hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
642     while (hashelem != NULL) {
643       cmp = cmp_func(hashelem->key.value.genericValue, aKey);
644       if (cmp < 0) {
645         delete_pos = &hashelem->next_less;
646         hashelem = hashelem->next_less;
647       } else if (unlikely(cmp == 0)) {
648         old_hashelem = hashelem;
649         if (hashelem->next_less == NULL) {
650           *delete_pos = hashelem->next_greater;
651         } else if (hashelem->next_greater == NULL) {
652           *delete_pos = hashelem->next_less;
653         } else {
654           *delete_pos = hashelem->next_less;
655           greater_hashelems = hashelem->next_greater;
656           hashelem = hashelem->next_less;
657           while (hashelem->next_greater != NULL) {
658             hashelem = hashelem->next_greater;
659           } /* while */
660           hashelem->next_greater = greater_hashelems;
661         } /* if */
662         old_hashelem->next_less = NULL;
663         old_hashelem->next_greater = NULL;
664         free_helem(old_hashelem, key_destr_func, data_destr_func);
665         aHashMap->size--;
666         hashelem = NULL;
667       } else {
668         delete_pos = &hashelem->next_greater;
669         hashelem = hashelem->next_greater;
670       } /* if */
671     } /* while */
672     logFunction(printf("hshExcl(" FMT_X_MEM ", " FMT_U_GEN ", "
673                        FMT_U ") size=" FMT_U_MEM " -->\n",
674                        (memSizeType) aHashMap, aKey, hashcode, aHashMap->size););
675   } /* hshExcl */
676 
677 
678 
679 /**
680  *  Access one value from the hash table 'aHashMap'.
681  *  @return the element with the key 'aKey' from 'aHashMap'.
682  *  @exception RANGE_ERROR If 'aHashMap' does not have an element
683  *             with the key 'aKey'.
684  */
hshIdx(const const_rtlHashType aHashMap,const genericType aKey,intType hashcode,compareType cmp_func)685 genericType hshIdx (const const_rtlHashType aHashMap, const genericType aKey,
686     intType hashcode, compareType cmp_func)
687 
688   {
689     rtlHashElemType hashelem;
690     rtlHashElemType result_hashelem = NULL;
691     intType cmp;
692     genericType result;
693 
694   /* hshIdx */
695     logFunction(printf("hshIdx(" FMT_X_MEM ", " FMT_U_GEN ", " FMT_U ")\n",
696                        (memSizeType) aHashMap, aKey, hashcode););
697     hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
698     while (hashelem != NULL) {
699       cmp = cmp_func(hashelem->key.value.genericValue, aKey);
700       if (cmp < 0) {
701         hashelem = hashelem->next_less;
702       } else if (unlikely(cmp == 0)) {
703         result_hashelem = hashelem;
704         hashelem = NULL;
705       } else {
706         hashelem = hashelem->next_greater;
707       } /* if */
708     } /* while */
709     if (unlikely(result_hashelem == NULL)) {
710       logError(printf("hshIdx(" FMT_X_MEM ", " FMT_U_GEN ", " FMT_U "): "
711                       "Hashmap does not have an element with the key.\n",
712                       (memSizeType) aHashMap, aKey, hashcode););
713       raise_error(RANGE_ERROR);
714       result = 0;
715     } else {
716       result = result_hashelem->data.value.genericValue;
717     } /* if */
718     logFunction(printf("hshIdx(" FMT_X_MEM ", " FMT_U_GEN ", "
719                        FMT_U ") --> " FMT_X_GEN " (" FMT_X_GEN ")\n",
720                        (memSizeType) aHashMap, aKey, hashcode, result,
721                        (result != 0 ?
722                            ((const_rtlObjectType *) &result)->value.genericValue :
723                            (genericType) 0)););
724     return result;
725   } /* hshIdx */
726 
727 
728 
729 /**
730  *  Determine the address of a value from the hash table 'aHashMap'.
731  *  @return the address of the element with the key 'aKey' from 'aHashMap'.
732  *  @exception RANGE_ERROR If 'aHashMap' does not have an element
733  *             with the key 'aKey'.
734  */
hshIdxAddr(const const_rtlHashType aHashMap,const genericType aKey,intType hashcode,compareType cmp_func)735 rtlObjectType *hshIdxAddr (const const_rtlHashType aHashMap,
736     const genericType aKey, intType hashcode, compareType cmp_func)
737 
738   {
739     rtlHashElemType hashelem;
740     rtlHashElemType result_hashelem = NULL;
741     intType cmp;
742     rtlObjectType *result;
743 
744   /* hshIdxAddr */
745     logFunction(printf("hshIdxAddr(" FMT_X_MEM ", " FMT_U_GEN ", " FMT_U ")\n",
746                        (memSizeType) aHashMap, aKey, hashcode););
747     hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
748     while (hashelem != NULL) {
749       cmp = cmp_func(hashelem->key.value.genericValue, aKey);
750       /* printf(". %llu %llu cmp=%d\n",
751           (unsigned long long) hashelem->key.value.genericValue,
752           (unsigned long long) aKey, cmp); */
753       if (cmp < 0) {
754         hashelem = hashelem->next_less;
755       } else if (unlikely(cmp == 0)) {
756         result_hashelem = hashelem;
757         hashelem = NULL;
758       } else {
759         hashelem = hashelem->next_greater;
760       } /* if */
761     } /* while */
762     if (unlikely(result_hashelem == NULL)) {
763       logError(printf("hshIdxAddr(" FMT_X_MEM ", " FMT_U_GEN ", " FMT_U "): "
764                       "Hashmap does not have an element with the key.\n",
765                       (memSizeType) aHashMap, aKey, hashcode););
766       raise_error(RANGE_ERROR);
767       result = NULL;
768     } else {
769       result = &result_hashelem->data;
770     } /* if */
771     logFunction(printf("hshIdxAddr(" FMT_X_MEM ", " FMT_U_GEN ", "
772                        FMT_U ") --> " FMT_U_MEM " (" FMT_X_GEN ", %f)\n",
773                        (memSizeType) aHashMap, aKey, hashcode, (memSizeType) result,
774                        result != NULL ? result->value.genericValue : (genericType) 0,
775                        result != NULL ? result->value.floatValue : 0.0););
776     return result;
777   } /* hshIdxAddr */
778 
779 
780 
781 /**
782  *  Determine the address of a value from the hash table 'aHashMap'.
783  *  @return the address of the element with the key 'aKey' from 'aHashMap' or
784  *          NULL if 'aHashMap' does not have an element with the key 'aKey'.
785  */
hshIdxAddr2(const const_rtlHashType aHashMap,const genericType aKey,intType hashcode,compareType cmp_func)786 rtlObjectType *hshIdxAddr2 (const const_rtlHashType aHashMap,
787     const genericType aKey, intType hashcode, compareType cmp_func)
788 
789   {
790     rtlHashElemType hashelem;
791     rtlHashElemType result_hashelem = NULL;
792     intType cmp;
793     rtlObjectType *result;
794 
795   /* hshIdxAddr2 */
796     logFunction(printf("hshIdxAddr2(" FMT_X_MEM ", " FMT_U_GEN ", " FMT_U ")\n",
797                        (memSizeType) aHashMap, aKey, hashcode););
798     hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
799     while (hashelem != NULL) {
800       cmp = cmp_func(hashelem->key.value.genericValue, aKey);
801       /* printf(". %llu %llu cmp=%d\n",
802           (unsigned long long) hashelem->key.value.genericValue,
803           (unsigned long long) aKey, cmp); */
804       if (cmp < 0) {
805         hashelem = hashelem->next_less;
806       } else if (unlikely(cmp == 0)) {
807         result_hashelem = hashelem;
808         hashelem = NULL;
809       } else {
810         hashelem = hashelem->next_greater;
811       } /* if */
812     } /* while */
813     if (result_hashelem != NULL) {
814       result = &result_hashelem->data;
815     } else {
816       result = NULL;
817     } /* if */
818     logFunction(printf("hshIdxAddr2(" FMT_X_MEM ", " FMT_U_GEN ", "
819                        FMT_U ") --> " FMT_U_MEM " (" FMT_X_GEN ", %f)\n",
820                        (memSizeType) aHashMap, aKey, hashcode, (memSizeType) result,
821                        result != NULL ? result->value.genericValue : (genericType) 0,
822                        result != NULL ? result->value.floatValue : 0.0););
823     return result;
824   } /* hshIdxAddr2 */
825 
826 
827 
828 /**
829  *  Search for 'aKey' in 'aHashMap'.
830  *  If 'aKey' is element of 'aHashMap' the corresponding value is returned.
831  *  If 'aKey' is not element of 'aHashMap' then 'defaultData' is stored
832  *  as value of 'aKey' in 'aHashMap' and 'defaultData' is returned.
833  *  @return the value stored for 'aKey' in 'aHashMap', or
834  *          'defaultData', if 'aKey' is not a member of 'aHashMap'.
835  */
hshIdxEnterDefault(const rtlHashType aHashMap,const genericType aKey,const genericType defaultData,intType hashcode)836 genericType hshIdxEnterDefault (const rtlHashType aHashMap,
837     const genericType aKey, const genericType defaultData, intType hashcode)
838 
839   {
840     rtlHashElemType hashelem;
841     rtlHashElemType result_hashelem;
842     errInfoType err_info = OKAY_NO_ERROR;
843     genericType result;
844 
845   /* hshIdxEnterDefault */
846     logFunction(printf("hshIdxEnterDefault(" FMT_X_MEM ", " FMT_U_GEN ", "
847                        FMT_U_GEN ", " FMT_U ")\n",
848                        (memSizeType) aHashMap, aKey, defaultData, hashcode););
849     hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
850     if (hashelem == NULL) {
851       result_hashelem = new_helem(aKey, defaultData,
852           (createFuncType) &genericCreate,
853           (createFuncType) &genericCreate, &err_info);
854       aHashMap->table[(unsigned int) hashcode & aHashMap->mask] = result_hashelem;
855       aHashMap->size++;
856     } else {
857       do {
858         /* printf("key=%llX\n", hashelem->key.value.genericValue); */
859         if (hashelem->key.value.genericValue < aKey) {
860           if (hashelem->next_less == NULL) {
861             result_hashelem = new_helem(aKey, defaultData,
862                 (createFuncType) &genericCreate,
863                 (createFuncType) &genericCreate, &err_info);
864             hashelem->next_less = result_hashelem;
865             aHashMap->size++;
866             hashelem = NULL;
867           } else {
868             hashelem = hashelem->next_less;
869           } /* if */
870         } else if (unlikely(hashelem->key.value.genericValue == aKey)) {
871           result_hashelem = hashelem;
872           hashelem = NULL;
873         } else {
874           if (hashelem->next_greater == NULL) {
875             result_hashelem = new_helem(aKey, defaultData,
876                 (createFuncType) &genericCreate,
877                 (createFuncType) &genericCreate, &err_info);
878             hashelem->next_greater = result_hashelem;
879             aHashMap->size++;
880             hashelem = NULL;
881           } else {
882             hashelem = hashelem->next_greater;
883           } /* if */
884         } /* if */
885       } while (hashelem != NULL);
886     } /* if */
887     if (unlikely(err_info != OKAY_NO_ERROR)) {
888       aHashMap->size--;
889       raise_error(MEMORY_ERROR);
890       result = 0;
891     } else {
892       result = result_hashelem->data.value.genericValue;
893     } /* if */
894     logFunction(printf("hshIdxEnterDefault(" FMT_X_MEM ", " FMT_U_GEN ", "
895                        FMT_U_GEN ", " FMT_U ") --> " FMT_U_GEN "\n",
896                        (memSizeType) aHashMap, aKey, defaultData,
897                        hashcode, result););
898     return result;
899   } /* hshIdxEnterDefault */
900 
901 
902 
903 /**
904  *  Search for 'aKey' in 'aHashMap'.
905  *  If 'aKey' is element of 'aHashMap' the corresponding value is returned.
906  *  If 'aKey' is not element of 'aHashMap' then 'defaultData' is returned.
907  *  @return the value stored for 'aKey' in 'aHashMap', or
908  *          'defaultData', if 'aKey' is not a member of 'aHashMap'.
909  */
hshIdxWithDefault(const const_rtlHashType aHashMap,const genericType aKey,const genericType defaultData,intType hashcode,compareType cmp_func)910 genericType hshIdxWithDefault (const const_rtlHashType aHashMap, const genericType aKey,
911     const genericType defaultData, intType hashcode, compareType cmp_func)
912 
913   {
914     rtlHashElemType hashelem;
915     rtlHashElemType result_hashelem = NULL;
916     intType cmp;
917     genericType result;
918 
919   /* hshIdxWithDefault */
920     logFunction(printf("hshIdxWithDefault(" FMT_X_MEM ", " FMT_U_GEN ", "
921                        FMT_U_GEN ", " FMT_U ")\n",
922                        (memSizeType) aHashMap, aKey, defaultData, hashcode););
923     hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
924     while (hashelem != NULL) {
925       cmp = cmp_func(hashelem->key.value.genericValue, aKey);
926       if (cmp < 0) {
927         hashelem = hashelem->next_less;
928       } else if (unlikely(cmp == 0)) {
929         result_hashelem = hashelem;
930         hashelem = NULL;
931       } else {
932         hashelem = hashelem->next_greater;
933       } /* if */
934     } /* while */
935     if (result_hashelem != NULL) {
936       result = result_hashelem->data.value.genericValue;
937     } else {
938       result = defaultData;
939     } /* if */
940     logFunction(printf("hshIdxWithDefault(" FMT_X_MEM ", " FMT_U_GEN ", "
941                        FMT_U_GEN ", " FMT_U ") --> " FMT_U_GEN "\n",
942                        (memSizeType) aHashMap, aKey, defaultData,
943                        hashcode, result););
944     return result;
945   } /* hshIdxWithDefault */
946 
947 
948 
949 /**
950  *  Search for 'aKey' in 'aHashMap'.
951  *  If 'aKey' is element of 'aHashMap' the corresponding value is returned.
952  *  If 'aKey' is not element of 'aHashMap' then 0 is returned.
953  *  @return the value stored for 'aKey' in 'aHashMap', or
954  *          0, if 'aKey' is not a member of 'aHashMap'.
955  */
hshIdxDefault0(const const_rtlHashType aHashMap,const genericType aKey,intType hashcode,compareType cmp_func)956 genericType hshIdxDefault0 (const const_rtlHashType aHashMap, const genericType aKey,
957     intType hashcode, compareType cmp_func)
958 
959   {
960     rtlHashElemType hashelem;
961     intType cmp;
962     genericType result;
963 
964   /* hshIdxDefault0 */
965     logFunction(printf("hshIdxDefault0(" FMT_X_MEM ", " FMT_U_GEN ", " FMT_U ")\n",
966                        (memSizeType) aHashMap, aKey, hashcode););
967     hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
968     while (hashelem != NULL) {
969       cmp = cmp_func(hashelem->key.value.genericValue, aKey);
970       if (cmp < 0) {
971         hashelem = hashelem->next_less;
972       } else if (unlikely(cmp == 0)) {
973         result = hashelem->data.value.genericValue;
974         logFunction(printf("hshIdxDefault0(" FMT_X_MEM ", " FMT_U_GEN ", "
975                            FMT_U ") --> " FMT_U_GEN "\n",
976                            (memSizeType) aHashMap, aKey, hashcode, result););
977         return result;
978       } else {
979         hashelem = hashelem->next_greater;
980       } /* if */
981     } /* while */
982     logFunction(printf("hshIdxDefault0(" FMT_X_MEM ", " FMT_U_GEN ", "
983                        FMT_U ") --> 0\n",
984                        (memSizeType) aHashMap, aKey, hashcode););
985     return 0;
986   } /* hshIdxDefault0 */
987 
988 
989 
990 /**
991  *  Add 'data' with the key 'aKey' to the hash map 'aHashMap'.
992  *  If an element with the key 'aKey' already exists,
993  *  it is overwritten with 'data'.
994  *  @exception MEMORY_ERROR If there is not enough memory.
995  */
hshIncl(const rtlHashType aHashMap,const genericType aKey,const genericType data,intType hashcode,compareType cmp_func,const createFuncType key_create_func,const createFuncType data_create_func,const copyFuncType data_copy_func)996 void hshIncl (const rtlHashType aHashMap, const genericType aKey,
997     const genericType data, intType hashcode, compareType cmp_func,
998     const createFuncType key_create_func, const createFuncType data_create_func,
999     const copyFuncType data_copy_func)
1000 
1001   {
1002     rtlHashElemType hashelem;
1003     intType cmp;
1004     errInfoType err_info = OKAY_NO_ERROR;
1005 
1006   /* hshIncl */
1007     logFunction(printf("hshIncl(" FMT_X_MEM ", " FMT_U_GEN ", "
1008                        FMT_U_GEN ", " FMT_U ") size=" FMT_U_MEM "\n",
1009                        (memSizeType) aHashMap, aKey, data, hashcode, aHashMap->size););
1010     hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
1011     if (hashelem == NULL) {
1012       aHashMap->table[(unsigned int) hashcode & aHashMap->mask] = new_helem(aKey, data,
1013           key_create_func, data_create_func, &err_info);
1014       /*
1015       hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
1016       printf("aKey=%llX\n", (unsigned long long) aKey);
1017       printf("new hashelem: aKey=%llX, data=%llX\n",
1018           hashelem->key.value.intValue, hashelem->data.value.intValue);
1019       printf("cmp = %d\n", (int) cmp_func(hashelem->key.value.genericValue, aKey));
1020       */
1021       aHashMap->size++;
1022     } else {
1023       do {
1024         cmp = cmp_func(hashelem->key.value.genericValue, aKey);
1025         if (cmp < 0) {
1026           if (hashelem->next_less == NULL) {
1027             hashelem->next_less = new_helem(aKey, data,
1028                 key_create_func, data_create_func, &err_info);
1029             aHashMap->size++;
1030             hashelem = NULL;
1031           } else {
1032             hashelem = hashelem->next_less;
1033           } /* if */
1034         } else if (unlikely(cmp == 0)) {
1035           data_copy_func(&hashelem->data.value.genericValue, data);
1036           hashelem = NULL;
1037         } else {
1038           if (hashelem->next_greater == NULL) {
1039             hashelem->next_greater = new_helem(aKey, data,
1040                 key_create_func, data_create_func, &err_info);
1041             aHashMap->size++;
1042             hashelem = NULL;
1043           } else {
1044             hashelem = hashelem->next_greater;
1045           } /* if */
1046         } /* if */
1047       } while (hashelem != NULL);
1048     } /* if */
1049     if (unlikely(err_info != OKAY_NO_ERROR)) {
1050       aHashMap->size--;
1051       raise_error(MEMORY_ERROR);
1052     } /* if */
1053     logFunction(printf("hshIncl(" FMT_X_MEM ", " FMT_U_GEN ", "
1054                        FMT_U_GEN ", " FMT_U ") size=" FMT_U_MEM " -->\n",
1055                        (memSizeType) aHashMap, aKey, data, hashcode, aHashMap->size););
1056   } /* hshIncl */
1057 
1058 
1059 
1060 /**
1061  *  Obtain the keys of the hash map 'aHashMap'.
1062  *  @return the keys of the hash map.
1063  */
hshKeys(const const_rtlHashType aHashMap,const createFuncType key_create_func,const destrFuncType key_destr_func)1064 rtlArrayType hshKeys (const const_rtlHashType aHashMap,
1065     const createFuncType key_create_func, const destrFuncType key_destr_func)
1066 
1067   {
1068     rtlArrayType key_array;
1069 
1070   /* hshKeys */
1071     key_array = keys_hash(aHashMap, key_create_func);
1072     return key_array;
1073   } /* hshKeys */
1074 
1075 
1076 
1077 /**
1078  *  Compute pseudo-random hash table element from 'aHashMap'.
1079  *  The hash table element contains key and value.
1080  *  The random values are uniform distributed.
1081  *  @return a random hash table element such that hshRand(aHashMap) in aHashMap holds.
1082  *  @exception RANGE_ERROR If 'aHashMap' is empty.
1083  */
hshRand(const const_rtlHashType aHashMap)1084 const_rtlHashElemType hshRand (const const_rtlHashType aHashMap)
1085 
1086   {
1087     memSizeType num_elements;
1088     memSizeType elem_index;
1089     const_rtlHashElemType result;
1090 
1091   /* hshRand */
1092     logFunction(printf("hshRand(" FMT_U_MEM ")\n",
1093                        (memSizeType) aHashMap););
1094     num_elements = aHashMap->size;
1095     if (unlikely(num_elements == 0)) {
1096       logError(printf("hshRand(): Hash map is empty.\n"););
1097       raise_error(RANGE_ERROR);
1098       return NULL;
1099     } else {
1100       elem_index = (memSizeType) (uintType)
1101           intRand((intType) 1, (intType) num_elements);
1102       /* printf("elem_index " FMT_U_MEM "\n", elem_index); */
1103       result = get_hash_elem(aHashMap, elem_index);
1104     } /* if */
1105     logFunction(printf("hshRand --> " FMT_U_MEM "\n",
1106                        (memSizeType) result););
1107     return result;
1108   } /* hshRand */
1109 
1110 
1111 
1112 /**
1113  *  Add 'data' with the key 'aKey' to the hash map 'aHashMap'.
1114  *  If an element with the key 'aKey' already exists,
1115  *  it is overwritten with 'data'.
1116  *  @param data New value, a temporary value which is used or returned.
1117  *  @return the old element with the key 'aKey' or
1118  *          the new data value if no old element existed.
1119  *  @exception MEMORY_ERROR If there is not enough memory.
1120  */
hshUpdate(const rtlHashType aHashMap,const genericType aKey,const genericType data,intType hashcode,compareType cmp_func,const createFuncType key_create_func,const createFuncType data_create_func)1121 genericType hshUpdate (const rtlHashType aHashMap, const genericType aKey,
1122     const genericType data, intType hashcode, compareType cmp_func,
1123     const createFuncType key_create_func, const createFuncType data_create_func)
1124 
1125   {
1126     rtlHashElemType hashelem;
1127     intType cmp;
1128     errInfoType err_info = OKAY_NO_ERROR;
1129     genericType result;
1130 
1131   /* hshUpdate */
1132     logFunction(printf("hshUpdate(" FMT_X_MEM ", " FMT_U_GEN ", "
1133                        FMT_U_GEN ", " FMT_U ") size=" FMT_U_MEM "\n",
1134                        (memSizeType) aHashMap, aKey, data, hashcode, aHashMap->size););
1135     hashelem = aHashMap->table[(unsigned int) hashcode & aHashMap->mask];
1136     if (hashelem == NULL) {
1137       aHashMap->table[(unsigned int) hashcode & aHashMap->mask] = new_helem(aKey, data,
1138           key_create_func, data_create_func, &err_info);
1139       aHashMap->size++;
1140       result = data;
1141     } else {
1142       do {
1143         cmp = cmp_func(hashelem->key.value.genericValue, aKey);
1144         if (cmp < 0) {
1145           if (hashelem->next_less == NULL) {
1146             hashelem->next_less = new_helem(aKey, data,
1147                 key_create_func, data_create_func, &err_info);
1148             aHashMap->size++;
1149             result = data;
1150             hashelem = NULL;
1151           } else {
1152             hashelem = hashelem->next_less;
1153           } /* if */
1154         } else if (unlikely(cmp == 0)) {
1155           result = hashelem->data.value.genericValue;
1156           hashelem->data.value.genericValue = data;
1157           hashelem = NULL;
1158         } else {
1159           if (hashelem->next_greater == NULL) {
1160             hashelem->next_greater = new_helem(aKey, data,
1161                 key_create_func, data_create_func, &err_info);
1162             aHashMap->size++;
1163             result = data;
1164             hashelem = NULL;
1165           } else {
1166             hashelem = hashelem->next_greater;
1167           } /* if */
1168         } /* if */
1169       } while (hashelem != NULL);
1170     } /* if */
1171     if (unlikely(err_info != OKAY_NO_ERROR)) {
1172       aHashMap->size--;
1173       raise_error(MEMORY_ERROR);
1174     } /* if */
1175     logFunction(printf("hshUpdate(" FMT_X_MEM ", " FMT_U_GEN ", "
1176                        FMT_U_GEN ", " FMT_U ") size=" FMT_U_MEM " -->\n",
1177                        (memSizeType) aHashMap, aKey, data, hashcode, aHashMap->size););
1178     return result;
1179   } /* hshUpdate */
1180 
1181 
1182 
1183 /**
1184  *  Obtain the values of the hash map 'aHashMap'.
1185  *  @return the values of the hash map.
1186  */
hshValues(const const_rtlHashType aHashMap,const createFuncType value_create_func,const destrFuncType value_destr_func)1187 rtlArrayType hshValues (const const_rtlHashType aHashMap,
1188     const createFuncType value_create_func, const destrFuncType value_destr_func)
1189 
1190   {
1191     rtlArrayType value_array;
1192 
1193   /* hshValues */
1194     value_array = values_hash(aHashMap, value_create_func);
1195     return value_array;
1196   } /* hshValues */
1197