MagickCore 7.0.10
hashmap.c
Go to the documentation of this file.
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% H H AAA SSSSS H H M M AAA PPPP %
7% H H A A SS H H MM MM A A P P %
8% HHHHH AAAAA SSS HHHHH M M M AAAAA PPPP %
9% H H A A SS H H M M A A P %
10% H H A A SSSSS H H M M A A P %
11% %
12% %
13% Wizard's Toolkit Hash-map and Linked-list Methods %
14% %
15% Software Design %
16% Cristy %
17% December 2002 %
18% %
19% %
20% Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization %
21% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% https://imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36% This module implements the standard handy hash and linked-list methods for
37% storing and retrieving large numbers of data elements. It is loosely based
38% on the Java implementation of these algorithms.
39%
40*/
41
42/*
43 Increde declarations.
44*/
45#include "wizard/studio.h"
46#include "wizard/exception.h"
48#include "wizard/hash.h"
49#include "wizard/hashmap.h"
50#include "wizard/memory_.h"
51#include "wizard/semaphore.h"
52#include "wizard/string_.h"
53
54/*
55 Typedef declarations.
56*/
57typedef struct _ElementInfo
58{
59 void
61
62 struct _ElementInfo
65
66typedef struct _EntryInfo
67{
68 size_t
70
71 void
75
77{
78 size_t
81
86
89
90 size_t
92};
93
95{
96 size_t
97 (*hash)(const void *);
98
100 (*compare)(const void *,const void *);
101
102 void
103 *(*relinquish_key)(void *),
104 *(*relinquish_value)(void *);
105
106 size_t
110
113
116
119
120 size_t
122};
123
124/*
125%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
126% %
127% %
128% %
129% A p p e n d V a l u e T o L i n k e d L i s t %
130% %
131% %
132% %
133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134%
135% AppendValueToLinkedList() appends a value to the end of the linked-list.
136%
137% The format of the AppendValueToLinkedList method is:
138%
139% WizardBooleanType AppendValueToLinkedList(LinkedListInfo *list_info,
140% const void *value)
141%
142% A description of each parameter follows:
143%
144% o list_info: The linked-list info.
145%
146% o value: The value.
147%
148*/
150 LinkedListInfo *list_info,const void *value)
151{
153 *next;
154
155 assert(list_info != (LinkedListInfo *) NULL);
156 assert(list_info->signature == WizardSignature);
157 if (list_info->elements == list_info->capacity)
158 return(WizardFalse);
159 next=(ElementInfo *) AcquireWizardMemory(sizeof(*next));
160 if (next == (ElementInfo *) NULL)
161 return(WizardFalse);
162 next->value=(void *) value;
163 next->next=(ElementInfo *) NULL;
164 LockSemaphoreInfo(list_info->semaphore);
165 if (list_info->next == (ElementInfo *) NULL)
166 list_info->next=next;
167 if (list_info->elements == 0)
168 list_info->head=next;
169 else
170 list_info->tail->next=next;
171 list_info->tail=next;
172 list_info->elements++;
173 UnlockSemaphoreInfo(list_info->semaphore);
174 return(WizardTrue);
175}
176
177/*
178%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
179% %
180% %
181% %
182% C l e a r L i n k e d L i s t %
183% %
184% %
185% %
186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187%
188% ClearLinkedList() clears all the elements from the linked-list.
189%
190% The format of the ClearLinkedList method is:
191%
192% void ClearLinkedList(LinkedListInfo *list_info,
193% void *(*relinquish_value)(void *))
194%
195% A description of each parameter follows:
196%
197% o list_info: The linked-list info.
198%
199% o relinquish_value: The value deallocation method; typically
200% RelinquishWizardMemory().
201%
202*/
204 void *(*relinquish_value)(void *))
205{
207 *element;
208
210 *next;
211
212 assert(list_info != (LinkedListInfo *) NULL);
213 assert(list_info->signature == WizardSignature);
214 LockSemaphoreInfo(list_info->semaphore);
215 next=list_info->head;
216 while (next != (ElementInfo *) NULL)
217 {
218 if (relinquish_value != (void *(*)(void *)) NULL)
219 next->value=relinquish_value(next->value);
220 element=next;
221 next=next->next;
222 element=(ElementInfo *) RelinquishWizardMemory(element);
223 }
224 list_info->head=(ElementInfo *) NULL;
225 list_info->tail=(ElementInfo *) NULL;
226 list_info->next=(ElementInfo *) NULL;
227 list_info->elements=0;
228 UnlockSemaphoreInfo(list_info->semaphore);
229}
230
231/*
232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233% %
234% %
235% %
236% C o m p a r e H a s h m a p S t r i n g %
237% %
238% %
239% %
240%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241%
242% CompareHashmapString() finds an entry in a hash-map based on the contents
243% of a string.
244%
245% The format of the CompareHashmapString method is:
246%
247% WizardBooleanType CompareHashmapString(const void *target,
248% const void *source)
249%
250% A description of each parameter follows:
251%
252% o target: The target string.
253%
254% o source: The source string.
255%
256*/
258 const void *source)
259{
260 char
261 *p,
262 *q;
263
264 p=(char *) target;
265 q=(char *) source;
266 return(strcmp(p,q) == 0 ? WizardTrue : WizardFalse);
267}
268
269/*
270%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
271% %
272% %
273% %
274% C o m p a r e H a s h m a p S t r i n g I n f o %
275% %
276% %
277% %
278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279%
280% CompareHashmapStringInfo() finds an entry in a hash-map based on the
281% contents of a string.
282%
283% The format of the CompareHashmapStringInfo method is:
284%
285% WizardBooleanType CompareHashmapStringInfo(const void *target,
286% const void *source)
287%
288% A description of each parameter follows:
289%
290% o target: The target string.
291%
292% o source: The source string.
293%
294*/
296 const void *source)
297{
299 *p,
300 *q;
301
302 p=(StringInfo *) target;
303 q=(StringInfo *) source;
304 return(CompareStringInfo(p,q) == 0 ? WizardTrue : WizardFalse);
305}
306
307/*
308%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309% %
310% %
311% %
312% D e s t r o y H a s h m a p %
313% %
314% %
315% %
316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317%
318% DestroyHashmap() frees the hash-map and all associated resources.
319%
320% The format of the DestroyHashmap method is:
321%
322% HashmapInfo *DestroyHashmap(HashmapInfo *hashmap_info)
323%
324% A description of each parameter follows:
325%
326% o hashmap_info: The hashmap info.
327%
328*/
330{
332 *list_info;
333
335 *entry;
336
337 ssize_t
338 i;
339
340 assert(hashmap_info != (HashmapInfo *) NULL);
341 assert(hashmap_info->signature == WizardSignature);
342 LockSemaphoreInfo(hashmap_info->semaphore);
343 for (i=0; i < (ssize_t) hashmap_info->capacity; i++)
344 {
345 list_info=hashmap_info->map[i];
346 if (list_info != (LinkedListInfo *) NULL)
347 {
348 list_info->next=list_info->head;
349 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
350 while (entry != (EntryInfo *) NULL)
351 {
352 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
353 entry->key=hashmap_info->relinquish_key(entry->key);
354 if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
355 entry->value=hashmap_info->relinquish_value(entry->value);
356 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
357 }
358 }
359 if (list_info != (LinkedListInfo *) NULL)
360 list_info=DestroyLinkedList(list_info,RelinquishWizardMemory);
361 }
362 hashmap_info->map=(LinkedListInfo **) RelinquishWizardMemory(
363 hashmap_info->map);
364 hashmap_info->signature=(~WizardSignature);
365 UnlockSemaphoreInfo(hashmap_info->semaphore);
366 RelinquishSemaphoreInfo(&hashmap_info->semaphore);
367 hashmap_info=(HashmapInfo *) RelinquishWizardMemory(hashmap_info);
368 return(hashmap_info);
369}
370
371/*
372%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373% %
374% %
375% %
376% D e s t r o y L i n k e d L i s t %
377% %
378% %
379% %
380%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381%
382% DestroyLinkedList() frees the linked-list and all associated resources.
383%
384% The format of the DestroyLinkedList method is:
385%
386% LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
387% void *(*relinquish_value)(void *))
388%
389% A description of each parameter follows:
390%
391% o list_info: The linked-list info.
392%
393% o relinquish_value: The value deallocation method; typically
394% RelinquishWizardMemory().
395%
396*/
398 void *(*relinquish_value)(void *))
399{
401 *entry;
402
404 *next;
405
406 assert(list_info != (LinkedListInfo *) NULL);
407 assert(list_info->signature == WizardSignature);
408 LockSemaphoreInfo(list_info->semaphore);
409 for (next=list_info->head; next != (ElementInfo *) NULL; )
410 {
411 if (relinquish_value != (void *(*)(void *)) NULL)
412 next->value=relinquish_value(next->value);
413 entry=next;
414 next=next->next;
415 entry=(ElementInfo *) RelinquishWizardMemory(entry);
416 }
417 list_info->signature=(~WizardSignature);
418 UnlockSemaphoreInfo(list_info->semaphore);
420 list_info=(LinkedListInfo *) RelinquishWizardMemory(list_info);
421 return(list_info);
422}
423
424/*
425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
426% %
427% %
428% %
429% G e t L a s t V a l u e I n L i n k e d L i s t %
430% %
431% %
432% %
433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434%
435% GetLastValueInLinkedList() gets the last value in the linked-list.
436%
437% The format of the GetLastValueInLinkedList method is:
438%
439% void *GetLastValueInLinkedList(LinkedListInfo *list_info)
440%
441% A description of each parameter follows:
442%
443% o list_info: The linked_list info.
444%
445*/
447{
448 void
449 *value;
450
451 assert(list_info != (LinkedListInfo *) NULL);
452 assert(list_info->signature == WizardSignature);
453 if (list_info->elements == 0)
454 return((void *) NULL);
455 LockSemaphoreInfo(list_info->semaphore);
456 value=list_info->tail->value;
457 UnlockSemaphoreInfo(list_info->semaphore);
458 return(value);
459}
460
461/*
462%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
463% %
464% %
465% %
466% G e t N e x t K e y I n H a s h m a p %
467% %
468% %
469% %
470%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
471%
472% GetNextKeyInHashmap() gets the next key in the hash-map.
473%
474% The format of the GetNextKeyInHashmap method is:
475%
476% void *GetNextKeyInHashmap(HashmapInfo *hashmap_info)
477%
478% A description of each parameter follows:
479%
480% o hashmap_info: The hashmap info.
481%
482*/
484{
486 *list_info;
487
489 *entry;
490
491 void
492 *key;
493
494 assert(hashmap_info != (HashmapInfo *) NULL);
495 assert(hashmap_info->signature == WizardSignature);
496 LockSemaphoreInfo(hashmap_info->semaphore);
497 while (hashmap_info->next < hashmap_info->capacity)
498 {
499 list_info=hashmap_info->map[hashmap_info->next];
500 if (list_info != (LinkedListInfo *) NULL)
501 {
502 if (hashmap_info->head_of_list == WizardFalse)
503 {
504 list_info->next=list_info->head;
505 hashmap_info->head_of_list=WizardTrue;
506 }
507 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
508 if (entry != (EntryInfo *) NULL)
509 {
510 key=entry->key;
511 UnlockSemaphoreInfo(hashmap_info->semaphore);
512 return(key);
513 }
514 hashmap_info->head_of_list=WizardFalse;
515 }
516 hashmap_info->next++;
517 }
518 UnlockSemaphoreInfo(hashmap_info->semaphore);
519 return((void *) NULL);
520}
521
522/*
523%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524% %
525% %
526% %
527% G e t N e x t V a l u e I n H a s h m a p %
528% %
529% %
530% %
531%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532%
533% GetNextValueInHashmap() gets the next value in the hash-map.
534%
535% The format of the GetNextValueInHashmap method is:
536%
537% void *GetNextValueInHashmap(HashmapInfo *hashmap_info)
538%
539% A description of each parameter follows:
540%
541% o hashmap_info: The hashmap info.
542%
543*/
545{
547 *list_info;
548
550 *entry;
551
552 void
553 *value;
554
555 assert(hashmap_info != (HashmapInfo *) NULL);
556 assert(hashmap_info->signature == WizardSignature);
557 LockSemaphoreInfo(hashmap_info->semaphore);
558 while (hashmap_info->next < hashmap_info->capacity)
559 {
560 list_info=hashmap_info->map[hashmap_info->next];
561 if (list_info != (LinkedListInfo *) NULL)
562 {
563 if (hashmap_info->head_of_list == WizardFalse)
564 {
565 list_info->next=list_info->head;
566 hashmap_info->head_of_list=WizardTrue;
567 }
568 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
569 if (entry != (EntryInfo *) NULL)
570 {
571 value=entry->value;
572 UnlockSemaphoreInfo(hashmap_info->semaphore);
573 return(value);
574 }
575 hashmap_info->head_of_list=WizardFalse;
576 }
577 hashmap_info->next++;
578 }
579 UnlockSemaphoreInfo(hashmap_info->semaphore);
580 return((void *) NULL);
581}
582
583/*
584%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
585% %
586% %
587% %
588% G e t N e x t V a l u e I n L i n k e d L i s t %
589% %
590% %
591% %
592%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
593%
594% GetNextValueInLinkedList() gets the next value in the linked-list.
595%
596% The format of the GetNextValueInLinkedList method is:
597%
598% void *GetNextValueInLinkedList(LinkedListInfo *list_info)
599%
600% A description of each parameter follows:
601%
602% o list_info: The linked-list info.
603%
604*/
606{
607 void
608 *value;
609
610 assert(list_info != (LinkedListInfo *) NULL);
611 assert(list_info->signature == WizardSignature);
612 LockSemaphoreInfo(list_info->semaphore);
613 if (list_info->next == (ElementInfo *) NULL)
614 {
615 UnlockSemaphoreInfo(list_info->semaphore);
616 return((void *) NULL);
617 }
618 value=list_info->next->value;
619 list_info->next=list_info->next->next;
620 UnlockSemaphoreInfo(list_info->semaphore);
621 return(value);
622}
623
624/*
625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
626% %
627% %
628% %
629% G e t N u m b e r O f E n t r i e s I n H a s h m a p %
630% %
631% %
632% %
633%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
634%
635% GetNumberOfEntriesInHashmap() returns the number of entries in the hash-map.
636%
637% The format of the GetNumberOfEntriesInHashmap method is:
638%
639% size_t GetNumberOfEntriesInHashmap(const HashmapInfo *hashmap_info)
640%
641% A description of each parameter follows:
642%
643% o hashmap_info: The hashmap info.
644%
645*/
647 const HashmapInfo *hashmap_info)
648{
649 assert(hashmap_info != (HashmapInfo *) NULL);
650 assert(hashmap_info->signature == WizardSignature);
651 return(hashmap_info->entries);
652}
653
654/*
655%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
656% %
657% %
658% %
659% G e t N u m b e r O f E l e m e n t s I n L i n k e d L i s t %
660% %
661% %
662% %
663%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
664%
665% GetNumberOfElementsInLinkedList() returns the number of entries in the
666% linked-list.
667%
668% The format of the GetNumberOfElementsInLinkedList method is:
669%
670% size_t GetNumberOfElementsInLinkedList(
671% const LinkedListInfo *list_info)
672%
673% A description of each parameter follows:
674%
675% o list_info: The linked-list info.
676%
677*/
679 const LinkedListInfo *list_info)
680{
681 assert(list_info != (LinkedListInfo *) NULL);
682 assert(list_info->signature == WizardSignature);
683 return(list_info->elements);
684}
685
686/*
687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
688% %
689% %
690% %
691% G e t V a l u e F r o m H a s h m a p %
692% %
693% %
694% %
695%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
696%
697% GetValueFromHashmap() gets a value from the hash-map by its key.
698%
699% The format of the GetValueFromHashmap method is:
700%
701% void *GetValueFromHashmap(HashmapInfo *hashmap_info,const void *key)
702%
703% A description of each parameter follows:
704%
705% o hashmap_info: The hashmap info.
706%
707% o key: The key.
708%
709*/
711 const void *key)
712{
714 *list_info;
715
717 *entry;
718
719 size_t
720 hash;
721
722 void
723 *value;
724
725 assert(hashmap_info != (HashmapInfo *) NULL);
726 assert(hashmap_info->signature == WizardSignature);
727 if (key == NULL)
728 return((void *) NULL);
729 LockSemaphoreInfo(hashmap_info->semaphore);
730 hash=hashmap_info->hash(key);
731 list_info=hashmap_info->map[hash % hashmap_info->capacity];
732 if (list_info != (LinkedListInfo *) NULL)
733 {
734 list_info->next=list_info->head;
735 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
736 while (entry != (EntryInfo *) NULL)
737 {
738 if (entry->hash == hash)
739 {
741 compare;
742
743 compare=WizardTrue;
744 if (hashmap_info->compare !=
745 (WizardBooleanType (*)(const void *,const void *)) NULL)
746 compare=hashmap_info->compare(key,entry->key);
747 if (compare == WizardTrue)
748 {
749 value=entry->value;
750 UnlockSemaphoreInfo(hashmap_info->semaphore);
751 return(value);
752 }
753 }
754 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
755 }
756 }
757 UnlockSemaphoreInfo(hashmap_info->semaphore);
758 return((void *) NULL);
759}
760
761/*
762%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
763% %
764% %
765% %
766% G e t V a l u e F r o m L i n k e d L i s t %
767% %
768% %
769% %
770%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
771%
772% GetValueFromLinkedList() gets a vlaue from the linked-list by the specified
773% location.
774%
775% The format of the GetValueFromLinkedList method is:
776%
777% void *GetValueFromLinkedList(LinkedListInfo *list_info,
778% const size_t index)
779%
780% A description of each parameter follows:
781%
782% o list_info: The linked_list info.
783%
784% o index: The list index.
785%
786*/
788 const size_t index)
789{
791 *next;
792
793 ssize_t
794 i;
795
796 void
797 *value;
798
799 assert(list_info != (LinkedListInfo *) NULL);
800 assert(list_info->signature == WizardSignature);
801 if (index >= list_info->elements)
802 return((void *) NULL);
803 LockSemaphoreInfo(list_info->semaphore);
804 if (index == 0)
805 {
806 value=list_info->head->value;
807 UnlockSemaphoreInfo(list_info->semaphore);
808 return(value);
809 }
810 if (index == (list_info->elements-1))
811 {
812 value=list_info->tail->value;
813 UnlockSemaphoreInfo(list_info->semaphore);
814 return(value);
815 }
816 next=list_info->head;
817 for (i=0; i < (ssize_t) index; i++)
818 next=next->next;
819 value=next->value;
820 UnlockSemaphoreInfo(list_info->semaphore);
821 return(value);
822}
823
824/*
825%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
826% %
827% %
828% %
829% H a s h P o i n t e r T y p e %
830% %
831% %
832% %
833%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
834%
835% HashPointerType() finds an entry in a hash-map based on the address of a
836% pointer.
837%
838% The format of the HashPointerType method is:
839%
840% size_t HashPointerType(const void *pointer)
841%
842% A description of each parameter follows:
843%
844% o pointer: compute the hash entry location from this pointer address.
845%
846*/
847WizardExport size_t HashPointerType(const void *pointer)
848{
849 size_t
850 hash;
851
852 hash=(size_t) pointer;
853 hash+=(~(hash << 9));
854 hash^=(hash >> 14);
855 hash+=(hash << 4);
856 hash^=(hash >> 10);
857 return(hash);
858}
859
860/*
861%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
862% %
863% %
864% %
865% H a s h S t r i n g T y p e %
866% %
867% %
868% %
869%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
870%
871% HashStringType() finds an entry in a hash-map based on the contents of a
872% string.
873%
874% The format of the HashStringType method is:
875%
876% size_t HashStringType(const void *string)
877%
878% A description of each parameter follows:
879%
880% o string: compute the hash entry location from this string.
881%
882*/
883WizardExport size_t HashStringType(const void *string)
884{
885 const StringInfo
886 *digest;
887
889 *hashmap_info;
890
891 size_t
892 i;
893
894 size_t
895 hash;
896
898 *message;
899
900 unsigned char
901 *datum;
902
903 hashmap_info=AcquireHashInfo(CRC64Hash);
904 if (hashmap_info == (HashInfo *) NULL)
905 return((size_t) string);
906 InitializeHash(hashmap_info);
907 message=StringToStringInfo((const char *) string);
908 UpdateHash(hashmap_info,message);
909 FinalizeHash(hashmap_info);
910 hash=0;
911 digest=GetHashDigest(hashmap_info);
912 datum=GetStringInfoDatum(digest);
913 for (i=0; i < GetStringInfoLength(digest); i++)
914 hash^=datum[i];
915 hashmap_info=DestroyHashInfo(hashmap_info);
916 return(hash);
917}
918
919/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
920% %
921% %
922% %
923% H a s h S t r i n g I n f o T y p e %
924% %
925% %
926% %
927%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
928%
929% HashStringInfoType() finds an entry in a hash-map based on the contents of
930% a string.
931%
932% The format of the HashStringInfoType method is:
933%
934% size_t HashStringInfoType(const void *string)
935%
936% A description of each parameter follows:
937%
938% o string: compute the hash entry location from this string.
939%
940*/
941WizardExport size_t HashStringInfoType(const void *string)
942{
943 size_t
944 i;
945
946 size_t
947 hash;
948
950 *message;
951
952 unsigned char
953 *datum;
954
955 message=(StringInfo *) string;
956 hash=0;
957 datum=GetStringInfoDatum(message);
958 for (i=0; i < GetStringInfoLength(message); i++)
959 hash^=datum[i];
960 return(hash);
961}
962
963/*
964%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965% %
966% %
967% %
968% I n s e r t V a l u e I n L i n k e d L i s t %
969% %
970% %
971% %
972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973%
974% InsertValueInLinkedList() inserts an element in the linked-list at the
975% specified location.
976%
977% The format of the InsertValueInLinkedList method is:
978%
979% WizardBooleanType InsertValueInLinkedList(ListInfo *list_info,
980% const size_t index,const void *value)
981%
982% A description of each parameter follows:
983%
984% o list_info: The hashmap info.
985%
986% o index: The index.
987%
988% o value: The value.
989%
990*/
992 LinkedListInfo *list_info,const size_t index,const void *value)
993{
995 *next;
996
997 ssize_t
998 i;
999
1000 assert(list_info != (LinkedListInfo *) NULL);
1001 assert(list_info->signature == WizardSignature);
1002 if (value == NULL)
1003 return(WizardFalse);
1004 if ((index > list_info->elements) ||
1005 (list_info->elements == list_info->capacity))
1006 return(WizardFalse);
1007 next=(ElementInfo *) AcquireWizardMemory(sizeof(*next));
1008 if (next == (ElementInfo *) NULL)
1009 return(WizardFalse);
1010 next->value=(void *) value;
1011 next->next=(ElementInfo *) NULL;
1012 LockSemaphoreInfo(list_info->semaphore);
1013 if (list_info->elements == 0)
1014 {
1015 if (list_info->next == (ElementInfo *) NULL)
1016 list_info->next=next;
1017 list_info->head=next;
1018 list_info->tail=next;
1019 }
1020 else
1021 {
1022 if (index == 0)
1023 {
1024 if (list_info->next == list_info->head)
1025 list_info->next=next;
1026 next->next=list_info->head;
1027 list_info->head=next;
1028 }
1029 else
1030 if (index == list_info->elements)
1031 {
1032 if (list_info->next == (ElementInfo *) NULL)
1033 list_info->next=next;
1034 list_info->tail->next=next;
1035 list_info->tail=next;
1036 }
1037 else
1038 {
1040 *element;
1041
1042 element=list_info->head;
1043 next->next=element->next;
1044 for (i=1; i < (ssize_t) index; i++)
1045 {
1046 element=element->next;
1047 next->next=element->next;
1048 }
1049 next=next->next;
1050 element->next=next;
1051 if (list_info->next == next->next)
1052 list_info->next=next;
1053 }
1054 }
1055 list_info->elements++;
1056 UnlockSemaphoreInfo(list_info->semaphore);
1057 return(WizardTrue);
1058}
1059
1060/*
1061%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1062% %
1063% %
1064% %
1065% I n s e r t V a l u e I n S o r t e d L i n k e d L i s t %
1066% %
1067% %
1068% %
1069%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1070%
1071% InsertValueInSortedLinkedList() inserts a value in the sorted linked-list.
1072%
1073% The format of the InsertValueInSortedLinkedList method is:
1074%
1075% WizardBooleanType InsertValueInSortedLinkedList(ListInfo *list_info,
1076% int (*compare)(const void *,const void *),void **replace,
1077% const void *value)
1078%
1079% A description of each parameter follows:
1080%
1081% o list_info: The hashmap info.
1082%
1083% o index: The index.
1084%
1085% o compare: The compare method.
1086%
1087% o replace: return previous element here.
1088%
1089% o value: The value.
1090%
1091*/
1093 LinkedListInfo *list_info,int (*compare)(const void *,const void *),
1094 void **replace,const void *value)
1095{
1097 *element;
1098
1100 *next;
1101
1102 ssize_t
1103 i;
1104
1105 assert(list_info != (LinkedListInfo *) NULL);
1106 assert(list_info->signature == WizardSignature);
1107 if ((compare == (int (*)(const void *,const void *)) NULL) ||
1108 (value == (const void *) NULL))
1109 return(WizardFalse);
1110 if (list_info->elements == list_info->capacity)
1111 return(WizardFalse);
1112 next=(ElementInfo *) AcquireWizardMemory(sizeof(*next));
1113 if (next == (ElementInfo *) NULL)
1114 return(WizardFalse);
1115 next->value=(void *) value;
1116 element=(ElementInfo *) NULL;
1117 LockSemaphoreInfo(list_info->semaphore);
1118 next->next=list_info->head;
1119 while (next->next != (ElementInfo *) NULL)
1120 {
1121 i=compare(value,next->next->value);
1122 if ((i < 0) || ((replace != (void **) NULL) && (i == 0)))
1123 {
1124 if (i == 0)
1125 {
1126 *replace=next->next->value;
1127 next->next=next->next->next;
1128 if (element != (ElementInfo *) NULL)
1130 element->next);
1131 list_info->elements--;
1132 }
1133 if (element != (ElementInfo *) NULL)
1134 element->next=next;
1135 else
1136 list_info->head=next;
1137 break;
1138 }
1139 element=next->next;
1140 next->next=next->next->next;
1141 }
1142 if (next->next == (ElementInfo *) NULL)
1143 {
1144 if (element != (ElementInfo *) NULL)
1145 element->next=next;
1146 else
1147 list_info->head=next;
1148 list_info->tail=next;
1149 }
1150 list_info->elements++;
1151 UnlockSemaphoreInfo(list_info->semaphore);
1152 return(WizardTrue);
1153}
1154
1155/*
1156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1157% %
1158% %
1159% %
1160% I s H a s h m a p E m p t y %
1161% %
1162% %
1163% %
1164%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1165%
1166% IsHashmapEmpty() returns WizardTrue if the hash-map is empty.
1167%
1168% The format of the IsHashmapEmpty method is:
1169%
1170% WizardBooleanType IsHashmapEmpty(const HashmapInfo *hashmap_info)
1171%
1172% A description of each parameter follows:
1173%
1174% o hashmap_info: The hashmap info.
1175%
1176*/
1178{
1179 assert(hashmap_info != (HashmapInfo *) NULL);
1180 assert(hashmap_info->signature == WizardSignature);
1181 return(hashmap_info->entries == 0 ? WizardTrue : WizardFalse);
1182}
1183
1184/*
1185%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1186% %
1187% %
1188% %
1189% I s L i n k e d L i s t E m p t y %
1190% %
1191% %
1192% %
1193%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1194%
1195% IsLinkedListEmpty() returns WizardTrue if the linked-list is empty.
1196%
1197% The format of the IsLinkedListEmpty method is:
1198%
1199% WizardBooleanType IsLinkedListEmpty(LinkedListInfo *list_info)
1200%
1201% A description of each parameter follows:
1202%
1203% o list_info: The linked-list info.
1204%
1205*/
1207 const LinkedListInfo *list_info)
1208{
1209 assert(list_info != (LinkedListInfo *) NULL);
1210 assert(list_info->signature == WizardSignature);
1211 return(list_info->elements == 0 ? WizardTrue : WizardFalse);
1212}
1213
1214/*
1215%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1216% %
1217% %
1218% %
1219% L i n k e d L i s t T o A r r a y %
1220% %
1221% %
1222% %
1223%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1224%
1225% LinkedListToArray() converts the linked-list to an array.
1226%
1227% The format of the LinkedListToArray method is:
1228%
1229% WizardBooleanType LinkedListToArray(LinkedListInfo *list_info,
1230% void **array)
1231%
1232% A description of each parameter follows:
1233%
1234% o list_info: The linked-list info.
1235%
1236% o array: The array.
1237%
1238*/
1240 void **array)
1241{
1243 *next;
1244
1245 ssize_t
1246 i;
1247
1248 assert(list_info != (LinkedListInfo *) NULL);
1249 assert(list_info->signature == WizardSignature);
1250 if (array == (void **) NULL)
1251 return(WizardFalse);
1252 LockSemaphoreInfo(list_info->semaphore);
1253 next=list_info->head;
1254 for (i=0; next != (ElementInfo *) NULL; i++)
1255 {
1256 array[i]=next->value;
1257 next=next->next;
1258 }
1259 UnlockSemaphoreInfo(list_info->semaphore);
1260 return(WizardTrue);
1261}
1262
1263/*
1264%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1265% %
1266% %
1267% %
1268% N e w H a s h m a p %
1269% %
1270% %
1271% %
1272%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1273%
1274% NewHashmap() returns a pointer to a HashmapInfo structure initialized
1275% to default values. The capacity is an initial estimate. The hashmap will
1276% increase capacity dynamically as the demand requires.
1277%
1278% The format of the NewHashmap method is:
1279%
1280% HashmapInfo *NewHashmap(const size_t capacity,
1281% size_t (*hash)(const void *),
1282% WizardBooleanType (*compare)(const void *,const void *),
1283% void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1284%
1285% A description of each parameter follows:
1286%
1287% o capacity: The initial number entries in the hash-map: typically
1288% SmallHashmapSize, MediumHashmapSize, or LargeHashmapSize. The
1289% hashmap will dynamically increase its capacity on demand.
1290%
1291% o hash: The hash method, typically HashPointerType(), HashStringType(),
1292% or HashStringInfoType().
1293%
1294% o compare: The compare method, typically NULL, CompareHashmapString(),
1295% or CompareHashmapStringInfo().
1296%
1297% o relinquish_key: The key deallocation method, typically
1298% RelinquishWizardMemory(), called whenever a key is removed from the
1299% hash-map.
1300%
1301% o relinquish_value: The value deallocation method; typically
1302% RelinquishWizardMemory(), called whenever a value object is removed from
1303% the hash-map.
1304%
1305*/
1306WizardExport HashmapInfo *NewHashmap(const size_t capacity,
1307 size_t (*hash)(const void *),
1308 WizardBooleanType (*compare)(const void *,const void *),
1309 void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1310{
1312 *hashmap_info;
1313
1314 hashmap_info=(HashmapInfo *) AcquireWizardMemory(sizeof(*hashmap_info));
1315 if (hashmap_info == (HashmapInfo *) NULL)
1317 (void) memset(hashmap_info,0,sizeof(*hashmap_info));
1318 hashmap_info->hash=HashPointerType;
1319 if (hash != (size_t (*)(const void *)) NULL)
1320 hashmap_info->hash=hash;
1321 hashmap_info->compare=(WizardBooleanType (*)(const void *,const void *)) NULL;
1322 if (compare != (WizardBooleanType (*)(const void *,const void *)) NULL)
1323 hashmap_info->compare=compare;
1324 hashmap_info->relinquish_key=relinquish_key;
1325 hashmap_info->relinquish_value=relinquish_value;
1326 hashmap_info->entries=0;
1327 hashmap_info->capacity=capacity;
1328 hashmap_info->map=(LinkedListInfo **) AcquireQuantumMemory((size_t)
1329 capacity+1UL,sizeof(*hashmap_info->map));
1330 if (hashmap_info->map == (LinkedListInfo **) NULL)
1332 (void) memset(hashmap_info->map,0,(size_t) capacity*
1333 sizeof(*hashmap_info->map));
1334 hashmap_info->semaphore=AcquireSemaphoreInfo();
1335 hashmap_info->signature=WizardSignature;
1336 return(hashmap_info);
1337}
1338
1339/*
1340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1341% %
1342% %
1343% %
1344% N e w L i n k e d L i s t I n f o %
1345% %
1346% %
1347% %
1348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1349%
1350% NewLinkedList() returns a pointer to a LinkedListInfo structure
1351% initialized to default values.
1352%
1353% The format of the Acquirestruct LinkedListInfomethod is:
1354%
1355% LinkedListInfo *NewLinkedList(const size_t capacity)
1356%
1357% A description of each parameter follows:
1358%
1359% o capacity: The maximum number of elements in the list.
1360%
1361*/
1363{
1365 *list_info;
1366
1367 list_info=(LinkedListInfo *) AcquireWizardMemory(sizeof(*list_info));
1368 if (list_info == (LinkedListInfo *) NULL)
1370 (void) memset(list_info,0,sizeof(*list_info));
1371 list_info->capacity=capacity == 0 ? (size_t) (~0) : capacity;
1372 list_info->elements=0;
1373 list_info->head=(ElementInfo *) NULL;
1374 list_info->tail=(ElementInfo *) NULL;
1375 list_info->next=(ElementInfo *) NULL;
1376 list_info->semaphore=AcquireSemaphoreInfo();
1377 list_info->signature=WizardSignature;
1378 return(list_info);
1379}
1380
1381/*
1382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1383% %
1384% %
1385% %
1386% P u t E n t r y I n H a s h m a p %
1387% %
1388% %
1389% %
1390%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1391%
1392% PutEntryInHashmap() puts an entry in the hash-map. If the key already
1393% exists in the map it is first removed.
1394%
1395% The format of the PutEntryInHashmap method is:
1396%
1397% WizardBooleanType PutEntryInHashmap(HashmapInfo *hashmap_info,
1398% const void *key,const void *value)
1399%
1400% A description of each parameter follows:
1401%
1402% o hashmap_info: The hashmap info.
1403%
1404% o key: The key.
1405%
1406% o value: The value.
1407%
1408*/
1409
1411{
1412#define MaxCapacities 20
1413
1414 const size_t
1415 capacities[MaxCapacities] =
1416 {
1417 17, 31, 61, 131, 257, 509, 1021, 2053, 4099, 8191, 16381, 32771,
1418 65537, 131071, 262147, 524287, 1048573, 2097143, 4194301, 8388617
1419 };
1420
1422 *element;
1423
1424 EntryInfo
1425 *entry;
1426
1428 *map_info,
1429 **map;
1430
1432 *next;
1433
1434 ssize_t
1435 i;
1436
1437 size_t
1438 capacity;
1439
1440 /*
1441 Increase to the next prime capacity.
1442 */
1443 for (i=0; i < MaxCapacities; i++)
1444 if (hashmap_info->capacity < capacities[i])
1445 break;
1446 if (i >= (MaxCapacities-1))
1447 return(WizardFalse);
1448 capacity=capacities[i+1];
1449 map=(LinkedListInfo **) AcquireQuantumMemory((size_t) capacity+1UL,
1450 sizeof(*map));
1451 if (map == (LinkedListInfo **) NULL)
1452 return(WizardFalse);
1453 (void) memset(map,0,(size_t) capacity*sizeof(*map));
1454 /*
1455 Copy entries to new hashmap with increased capacity.
1456 */
1457 for (i=0; i < (ssize_t) hashmap_info->capacity; i++)
1458 {
1460 *list_info;
1461
1462 list_info=hashmap_info->map[i];
1463 if (list_info == (LinkedListInfo *) NULL)
1464 continue;
1465 LockSemaphoreInfo(list_info->semaphore);
1466 for (next=list_info->head; next != (ElementInfo *) NULL; )
1467 {
1468 element=next;
1469 next=next->next;
1470 entry=(EntryInfo *) element->value;
1471 map_info=map[entry->hash % capacity];
1472 if (map_info == (LinkedListInfo *) NULL)
1473 {
1474 map_info=NewLinkedList(0);
1475 map[entry->hash % capacity]=map_info;
1476 }
1477 map_info->next=element;
1478 element->next=map_info->head;
1479 map_info->head=element;
1480 map_info->elements++;
1481 }
1482 list_info->signature=(~WizardSignature);
1483 UnlockSemaphoreInfo(list_info->semaphore);
1485 list_info=(LinkedListInfo *) RelinquishWizardMemory(list_info);
1486 }
1487 hashmap_info->map=(LinkedListInfo **) RelinquishWizardMemory(hashmap_info->map);
1488 hashmap_info->map=map;
1489 hashmap_info->capacity=capacity;
1490 return(WizardTrue);
1491}
1492
1494 const void *key,const void *value)
1495{
1496 EntryInfo
1497 *entry,
1498 *next;
1499
1501 *list_info;
1502
1503 size_t
1504 i;
1505
1506 assert(hashmap_info != (HashmapInfo *) NULL);
1507 assert(hashmap_info->signature == WizardSignature);
1508 if ((key == (void *) NULL) || (value == (void *) NULL))
1509 return(WizardFalse);
1510 next=(EntryInfo *) AcquireWizardMemory(sizeof(*next));
1511 if (next == (EntryInfo *) NULL)
1512 return(WizardFalse);
1513 LockSemaphoreInfo(hashmap_info->semaphore);
1514 next->hash=hashmap_info->hash(key);
1515 next->key=(void *) key;
1516 next->value=(void *) value;
1517 list_info=hashmap_info->map[next->hash % hashmap_info->capacity];
1518 if (list_info == (LinkedListInfo *) NULL)
1519 {
1520 list_info=NewLinkedList(0);
1521 hashmap_info->map[next->hash % hashmap_info->capacity]=list_info;
1522 }
1523 else
1524 {
1525 list_info->next=list_info->head;
1526 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1527 for (i=0; entry != (EntryInfo *) NULL; i++)
1528 {
1529 if (entry->hash == next->hash)
1530 {
1532 compare;
1533
1534 compare=WizardTrue;
1535 if (hashmap_info->compare !=
1536 (WizardBooleanType (*)(const void *,const void *)) NULL)
1537 compare=hashmap_info->compare(key,entry->key);
1538 if (compare == WizardTrue)
1539 {
1540 (void) RemoveElementFromLinkedList(list_info,i);
1541 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
1542 entry->key=hashmap_info->relinquish_key(entry->key);
1543 if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
1544 entry->value=hashmap_info->relinquish_value(entry->value);
1545 entry=(EntryInfo *) RelinquishWizardMemory(entry);
1546 break;
1547 }
1548 }
1549 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1550 }
1551 }
1552 if (InsertValueInLinkedList(list_info,0,next) == WizardFalse)
1553 {
1554 next=(EntryInfo *) RelinquishWizardMemory(next);
1555 UnlockSemaphoreInfo(hashmap_info->semaphore);
1556 return(WizardFalse);
1557 }
1558 if (list_info->elements >= (hashmap_info->capacity-1))
1559 if (IncreaseHashmapCapacity(hashmap_info) == WizardFalse)
1560 {
1561 UnlockSemaphoreInfo(hashmap_info->semaphore);
1562 return(WizardFalse);
1563 }
1564 hashmap_info->entries++;
1565 UnlockSemaphoreInfo(hashmap_info->semaphore);
1566 return(WizardTrue);
1567}
1568
1569/*
1570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1571% %
1572% %
1573% %
1574% R e m o v e E l e m e n t B y V a l u e F r o m L i n k e d L i s t %
1575% %
1576% %
1577% %
1578%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1579%
1580% RemoveElementByValueFromLinkedList() removes an element from the linked-list
1581% by value.
1582%
1583% The format of the RemoveElementByValueFromLinkedList method is:
1584%
1585% void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
1586% const void *value)
1587%
1588% A description of each parameter follows:
1589%
1590% o list_info: The list info.
1591%
1592% o value: The value.
1593%
1594*/
1596 const void *value)
1597{
1599 *next;
1600
1601 assert(list_info != (LinkedListInfo *) NULL);
1602 assert(list_info->signature == WizardSignature);
1603 if ((list_info->elements == 0) || (value == NULL))
1604 return((void *) NULL);
1605 LockSemaphoreInfo(list_info->semaphore);
1606 if (value == list_info->head->value)
1607 {
1608 if (list_info->next == list_info->head)
1609 list_info->next=list_info->head->next;
1610 next=list_info->head;
1611 list_info->head=list_info->head->next;
1612 next=(ElementInfo *) RelinquishWizardMemory(next);
1613 }
1614 else
1615 {
1617 *element;
1618
1619 next=list_info->head;
1620 while ((next->next != (ElementInfo *) NULL) &&
1621 (next->next->value != value))
1622 next=next->next;
1623 if (next->next == (ElementInfo *) NULL)
1624 {
1625 UnlockSemaphoreInfo(list_info->semaphore);
1626 return((void *) NULL);
1627 }
1628 element=next->next;
1629 next->next=element->next;
1630 if (element == list_info->tail)
1631 list_info->tail=next;
1632 if (list_info->next == element)
1633 list_info->next=element->next;
1634 element=(ElementInfo *) RelinquishWizardMemory(element);
1635 }
1636 list_info->elements--;
1637 UnlockSemaphoreInfo(list_info->semaphore);
1638 return((void *) value);
1639}
1640
1641/*
1642%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1643% %
1644% %
1645% %
1646% R e m o v e E l e m e n t F r o m L i n k e d L i s t %
1647% %
1648% %
1649% %
1650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1651%
1652% RemoveElementFromLinkedList() removes an element from the linked-list at the
1653% specified location.
1654%
1655% The format of the RemoveElementFromLinkedList method is:
1656%
1657% void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
1658% const size_t index)
1659%
1660% A description of each parameter follows:
1661%
1662% o list_info: The linked-list info.
1663%
1664% o index: The index.
1665%
1666*/
1668 const size_t index)
1669{
1671 *next;
1672
1673 ssize_t
1674 i;
1675
1676 void
1677 *value;
1678
1679 assert(list_info != (LinkedListInfo *) NULL);
1680 assert(list_info->signature == WizardSignature);
1681 if (index >= list_info->elements)
1682 return((void *) NULL);
1683 LockSemaphoreInfo(list_info->semaphore);
1684 if (index == 0)
1685 {
1686 if (list_info->next == list_info->head)
1687 list_info->next=list_info->head->next;
1688 value=list_info->head->value;
1689 next=list_info->head;
1690 list_info->head=list_info->head->next;
1691 next=(ElementInfo *) RelinquishWizardMemory(next);
1692 }
1693 else
1694 {
1696 *element;
1697
1698 next=list_info->head;
1699 for (i=1; i < (ssize_t) index; i++)
1700 next=next->next;
1701 element=next->next;
1702 next->next=element->next;
1703 if (element == list_info->tail)
1704 list_info->tail=next;
1705 if (list_info->next == element)
1706 list_info->next=element->next;
1707 value=element->value;
1708 element=(ElementInfo *) RelinquishWizardMemory(element);
1709 }
1710 list_info->elements--;
1711 UnlockSemaphoreInfo(list_info->semaphore);
1712 return(value);
1713}
1714
1715/*
1716%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1717% %
1718% %
1719% %
1720% R e m o v e E n t r y F r o m H a s h m a p %
1721% %
1722% %
1723% %
1724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725%
1726% RemoveEntryFromHashmap() removes an entry from the hash-map by its key.
1727%
1728% The format of the RemoveEntryFromHashmap method is:
1729%
1730% void *RemoveEntryFromHashmap(HashmapInfo *hashmap_info,void *key)
1731%
1732% A description of each parameter follows:
1733%
1734% o hashmap_info: The hashmap info.
1735%
1736% o key: The key.
1737%
1738*/
1740 const void *key)
1741{
1742 EntryInfo
1743 *entry;
1744
1746 *list_info;
1747
1748 size_t
1749 i;
1750
1751 size_t
1752 hash;
1753
1754 void
1755 *value;
1756
1757 assert(hashmap_info != (HashmapInfo *) NULL);
1758 assert(hashmap_info->signature == WizardSignature);
1759 if (key == NULL)
1760 return((void *) NULL);
1761 LockSemaphoreInfo(hashmap_info->semaphore);
1762 hash=hashmap_info->hash(key);
1763 list_info=hashmap_info->map[hash % hashmap_info->capacity];
1764 if (list_info != (LinkedListInfo *) NULL)
1765 {
1766 list_info->next=list_info->head;
1767 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1768 for (i=0; entry != (EntryInfo *) NULL; i++)
1769 {
1770 if (entry->hash == hash)
1771 {
1773 compare;
1774
1775 compare=WizardTrue;
1776 if (hashmap_info->compare !=
1777 (WizardBooleanType (*)(const void *,const void *)) NULL)
1778 compare=hashmap_info->compare(key,entry->key);
1779 if (compare == WizardTrue)
1780 {
1781 entry=(EntryInfo *) RemoveElementFromLinkedList(list_info,i);
1782 if (entry == (EntryInfo *) NULL)
1783 {
1784 UnlockSemaphoreInfo(hashmap_info->semaphore);
1785 return((void *) NULL);
1786 }
1787 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
1788 entry->key=hashmap_info->relinquish_key(entry->key);
1789 value=entry->value;
1790 entry=(EntryInfo *) RelinquishWizardMemory(entry);
1791 hashmap_info->entries--;
1792 UnlockSemaphoreInfo(hashmap_info->semaphore);
1793 return(value);
1794 }
1795 }
1796 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1797 }
1798 }
1799 UnlockSemaphoreInfo(hashmap_info->semaphore);
1800 return((void *) NULL);
1801}
1802
1803/*
1804%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1805% %
1806% %
1807% %
1808% R e m o v e L a s t E l e m e n t F r o m L i n k e d L i s t %
1809% %
1810% %
1811% %
1812%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1813%
1814% RemoveLastElementFromLinkedList() removes the last element from the
1815% linked-list.
1816%
1817% The format of the RemoveLastElementFromLinkedList method is:
1818%
1819% void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
1820%
1821% A description of each parameter follows:
1822%
1823% o list_info: The linked-list info.
1824%
1825*/
1827{
1828 void
1829 *value;
1830
1831 assert(list_info != (LinkedListInfo *) NULL);
1832 assert(list_info->signature == WizardSignature);
1833 if (list_info->elements == 0)
1834 return((void *) NULL);
1835 LockSemaphoreInfo(list_info->semaphore);
1836 if (list_info->next == list_info->tail)
1837 list_info->next=(ElementInfo *) NULL;
1838 if (list_info->elements == 1UL)
1839 {
1840 value=list_info->head->value;
1841 list_info->head=(ElementInfo *) NULL;
1842 list_info->tail=(ElementInfo *) RelinquishWizardMemory(list_info->tail);
1843 }
1844 else
1845 {
1847 *next;
1848
1849 value=list_info->tail->value;
1850 next=list_info->head;
1851 while (next->next != list_info->tail)
1852 next=next->next;
1853 list_info->tail=(ElementInfo *) RelinquishWizardMemory(list_info->tail);
1854 list_info->tail=next;
1855 next->next=(ElementInfo *) NULL;
1856 }
1857 list_info->elements--;
1858 UnlockSemaphoreInfo(list_info->semaphore);
1859 return(value);
1860}
1861
1862/*
1863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1864% %
1865% %
1866% %
1867% R e s e t H a s h m a p I t e r a t o r %
1868% %
1869% %
1870% %
1871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1872%
1873% ResetHashmapIterator() resets the hash-map iterator. Use it in conjunction
1874% with GetNextKeyInHashmap() to iterate over all the keys in the hash-map.
1875%
1876% The format of the ResetHashmapIterator method is:
1877%
1878% ResetHashmapIterator(HashmapInfo *hashmap_info)
1879%
1880% A description of each parameter follows:
1881%
1882% o hashmap_info: The hashmap info.
1883%
1884*/
1886{
1887 assert(hashmap_info != (HashmapInfo *) NULL);
1888 assert(hashmap_info->signature == WizardSignature);
1889 LockSemaphoreInfo(hashmap_info->semaphore);
1890 hashmap_info->next=0;
1891 hashmap_info->head_of_list=WizardFalse;
1892 UnlockSemaphoreInfo(hashmap_info->semaphore);
1893}
1894
1895/*
1896%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1897% %
1898% %
1899% %
1900% R e s e t L i n k e d L i s t I t e r a t o r %
1901% %
1902% %
1903% %
1904%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1905%
1906% ResetLinkedListIterator() resets the lined-list iterator. Use it in
1907% conjunction with GetNextValueInLinkedList() to iterate over all the values
1908% in the linked-list.
1909%
1910% The format of the ResetLinkedListIterator method is:
1911%
1912% ResetLinkedListIterator(LinkedListInfo *list_info)
1913%
1914% A description of each parameter follows:
1915%
1916% o list_info: The linked-list info.
1917%
1918*/
1920{
1921 assert(list_info != (LinkedListInfo *) NULL);
1922 assert(list_info->signature == WizardSignature);
1923 LockSemaphoreInfo(list_info->semaphore);
1924 list_info->next=list_info->head;
1925 UnlockSemaphoreInfo(list_info->semaphore);
1926}
#define ThrowWizardFatalError(domain, error)
@ CacheDomain
Definition exception.h:40
@ MemoryError
Definition exception.h:49
WizardExport HashInfo * AcquireHashInfo(const HashType hash)
Definition hash.c:99
WizardExport WizardBooleanType UpdateHash(HashInfo *hash_info, const StringInfo *message)
Definition hash.c:849
WizardExport WizardBooleanType InitializeHash(HashInfo *hash_info)
Definition hash.c:760
WizardExport HashInfo * DestroyHashInfo(HashInfo *hash_info)
Definition hash.c:231
WizardExport const StringInfo * GetHashDigest(const HashInfo *hash_info)
Definition hash.c:568
WizardExport WizardBooleanType FinalizeHash(HashInfo *hash_info)
Definition hash.c:324
@ CRC64Hash
Definition hash.h:31
WizardExport void * RemoveEntryFromHashmap(HashmapInfo *hashmap_info, const void *key)
Definition hashmap.c:1739
WizardExport size_t HashStringInfoType(const void *string)
Definition hashmap.c:941
WizardExport void * GetNextValueInHashmap(HashmapInfo *hashmap_info)
Definition hashmap.c:544
WizardExport WizardBooleanType CompareHashmapString(const void *target, const void *source)
Definition hashmap.c:257
static WizardBooleanType IncreaseHashmapCapacity(HashmapInfo *hashmap_info)
Definition hashmap.c:1410
WizardExport void * GetLastValueInLinkedList(LinkedListInfo *list_info)
Definition hashmap.c:446
WizardExport void * GetValueFromHashmap(HashmapInfo *hashmap_info, const void *key)
Definition hashmap.c:710
WizardExport HashmapInfo * NewHashmap(const size_t capacity, size_t(*hash)(const void *), WizardBooleanType(*compare)(const void *, const void *), void *(*relinquish_key)(void *), void *(*relinquish_value)(void *))
Definition hashmap.c:1306
WizardExport void * GetValueFromLinkedList(LinkedListInfo *list_info, const size_t index)
Definition hashmap.c:787
WizardExport void * RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
Definition hashmap.c:1826
WizardExport WizardBooleanType IsLinkedListEmpty(const LinkedListInfo *list_info)
Definition hashmap.c:1206
WizardExport WizardBooleanType IsHashmapEmpty(const HashmapInfo *hashmap_info)
Definition hashmap.c:1177
WizardExport size_t GetNumberOfEntriesInHashmap(const HashmapInfo *hashmap_info)
Definition hashmap.c:646
struct _ElementInfo ElementInfo
WizardExport size_t HashStringType(const void *string)
Definition hashmap.c:883
WizardExport WizardBooleanType LinkedListToArray(LinkedListInfo *list_info, void **array)
Definition hashmap.c:1239
WizardExport void ClearLinkedList(LinkedListInfo *list_info, void *(*relinquish_value)(void *))
Definition hashmap.c:203
WizardExport void * GetNextKeyInHashmap(HashmapInfo *hashmap_info)
Definition hashmap.c:483
WizardExport void ResetLinkedListIterator(LinkedListInfo *list_info)
Definition hashmap.c:1919
WizardExport size_t GetNumberOfElementsInLinkedList(const LinkedListInfo *list_info)
Definition hashmap.c:678
WizardExport WizardBooleanType InsertValueInSortedLinkedList(LinkedListInfo *list_info, int(*compare)(const void *, const void *), void **replace, const void *value)
Definition hashmap.c:1092
WizardExport WizardBooleanType AppendValueToLinkedList(LinkedListInfo *list_info, const void *value)
Definition hashmap.c:149
WizardExport WizardBooleanType CompareHashmapStringInfo(const void *target, const void *source)
Definition hashmap.c:295
#define MaxCapacities
WizardExport HashmapInfo * DestroyHashmap(HashmapInfo *hashmap_info)
Definition hashmap.c:329
WizardExport void * RemoveElementFromLinkedList(LinkedListInfo *list_info, const size_t index)
Definition hashmap.c:1667
WizardExport size_t HashPointerType(const void *pointer)
Definition hashmap.c:847
struct _EntryInfo EntryInfo
WizardExport WizardBooleanType InsertValueInLinkedList(LinkedListInfo *list_info, const size_t index, const void *value)
Definition hashmap.c:991
WizardExport void * RemoveElementByValueFromLinkedList(LinkedListInfo *list_info, const void *value)
Definition hashmap.c:1595
WizardExport void ResetHashmapIterator(HashmapInfo *hashmap_info)
Definition hashmap.c:1885
WizardExport LinkedListInfo * NewLinkedList(const size_t capacity)
Definition hashmap.c:1362
WizardExport WizardBooleanType PutEntryInHashmap(HashmapInfo *hashmap_info, const void *key, const void *value)
Definition hashmap.c:1493
WizardExport void * GetNextValueInLinkedList(LinkedListInfo *list_info)
Definition hashmap.c:605
WizardExport LinkedListInfo * DestroyLinkedList(LinkedListInfo *list_info, void *(*relinquish_value)(void *))
Definition hashmap.c:397
WizardExport void * AcquireWizardMemory(const size_t size)
Definition memory.c:586
WizardExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition memory.c:657
WizardExport void * RelinquishWizardMemory(void *memory)
Definition memory.c:1039
#define WizardExport
#define WizardSignature
WizardExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition semaphore.c:338
WizardExport SemaphoreInfo * AcquireSemaphoreInfo(void)
Definition semaphore.c:156
WizardExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition semaphore.c:282
WizardExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition semaphore.c:437
WizardExport size_t GetStringInfoLength(const StringInfo *string_info)
Definition string.c:1280
WizardExport int CompareStringInfo(const StringInfo *target, const StringInfo *source)
Definition string.c:372
WizardExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition string.c:1251
WizardExport StringInfo * StringToStringInfo(const char *string)
Definition string.c:2199
void * value
Definition hashmap.c:60
struct _ElementInfo * next
Definition hashmap.c:62
void * value
Definition hashmap.c:73
void * key
Definition hashmap.c:72
size_t hash
Definition hashmap.c:69
size_t(* hash)(const void *)
Definition hashmap.c:97
void *(* relinquish_key)(void *)
Definition hashmap.c:103
size_t next
Definition hashmap.c:109
void *(*) *(* relinquish_value)(void *)
Definition hashmap.c:104
WizardBooleanType head_of_list
Definition hashmap.c:112
LinkedListInfo ** map
Definition hashmap.c:115
size_t signature
Definition hashmap.c:121
size_t capacity
Definition hashmap.c:107
WizardBooleanType(* compare)(const void *, const void *)
Definition hashmap.c:100
SemaphoreInfo * semaphore
Definition hashmap.c:118
size_t entries
Definition hashmap.c:108
size_t signature
Definition hashmap.c:91
ElementInfo * tail
Definition hashmap.c:84
ElementInfo * head
Definition hashmap.c:83
SemaphoreInfo * semaphore
Definition hashmap.c:88
size_t elements
Definition hashmap.c:80
size_t capacity
Definition hashmap.c:79
ElementInfo * next
Definition hashmap.c:85
WizardBooleanType
Definition wizard-type.h:26
@ WizardTrue
Definition wizard-type.h:28
@ WizardFalse
Definition wizard-type.h:27