2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
13 % MagickCore Hash-map and Linked-list Methods %
20 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
45 #include "MagickCore/studio.h"
46 #include "MagickCore/exception.h"
47 #include "MagickCore/exception-private.h"
48 #include "MagickCore/hashmap.h"
49 #include "MagickCore/memory_.h"
50 #include "MagickCore/semaphore.h"
51 #include "MagickCore/signature-private.h"
52 #include "MagickCore/string_.h"
57 typedef struct _ElementInfo
66 typedef struct _EntryInfo
76 struct _LinkedListInfo
100 (*hash)(const void *);
103 (*compare)(const void *,const void *);
106 *(*relinquish_key)(void *),
107 *(*relinquish_value)(void *);
131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135 % A p p e n d V a l u e T o L i n k e d L i s t %
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 % AppendValueToLinkedList() appends a value to the end of the linked-list.
143 % The format of the AppendValueToLinkedList method is:
145 % MagickBooleanType AppendValueToLinkedList(LinkedListInfo *list_info,
148 % A description of each parameter follows:
150 % o list_info: the linked-list info.
152 % o value: the value.
155 MagickExport MagickBooleanType AppendValueToLinkedList(
156 LinkedListInfo *list_info,const void *value)
161 assert(list_info != (LinkedListInfo *) NULL);
162 assert(list_info->signature == MagickSignature);
163 list_info->debug=IsEventLogging();
164 if (list_info->debug != MagickFalse)
165 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
166 if (list_info->elements == list_info->capacity)
168 next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
169 if (next == (ElementInfo *) NULL)
171 next->value=(void *) value;
172 next->next=(ElementInfo *) NULL;
173 LockSemaphoreInfo(list_info->semaphore);
174 if (list_info->next == (ElementInfo *) NULL)
175 list_info->next=next;
176 if (list_info->elements == 0)
177 list_info->head=next;
179 list_info->tail->next=next;
180 list_info->tail=next;
181 list_info->elements++;
182 UnlockSemaphoreInfo(list_info->semaphore);
187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191 % C l e a r L i n k e d L i s t %
195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197 % ClearLinkedList() clears all the elements from the linked-list.
199 % The format of the ClearLinkedList method is:
201 % void ClearLinkedList(LinkedListInfo *list_info,
202 % void *(*relinquish_value)(void *))
204 % A description of each parameter follows:
206 % o list_info: the linked-list info.
208 % o relinquish_value: the value deallocation method; typically
209 % RelinquishMagickMemory().
212 MagickExport void ClearLinkedList(LinkedListInfo *list_info,
213 void *(*relinquish_value)(void *))
221 assert(list_info != (LinkedListInfo *) NULL);
222 assert(list_info->signature == MagickSignature);
223 if (list_info->debug != MagickFalse)
224 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
225 LockSemaphoreInfo(list_info->semaphore);
226 next=list_info->head;
227 while (next != (ElementInfo *) NULL)
229 if (relinquish_value != (void *(*)(void *)) NULL)
230 next->value=relinquish_value(next->value);
233 element=(ElementInfo *) RelinquishMagickMemory(element);
235 list_info->head=(ElementInfo *) NULL;
236 list_info->tail=(ElementInfo *) NULL;
237 list_info->next=(ElementInfo *) NULL;
238 list_info->elements=0;
239 UnlockSemaphoreInfo(list_info->semaphore);
243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 % C o m p a r e H a s h m a p S t r i n g %
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 % CompareHashmapString() finds an entry in a hash-map based on the contents
256 % The format of the CompareHashmapString method is:
258 % MagickBooleanType CompareHashmapString(const void *target,
259 % const void *source)
261 % A description of each parameter follows:
263 % o target: the target string.
265 % o source: the source string.
268 MagickExport MagickBooleanType CompareHashmapString(const void *target,
275 p=(const char *) target;
276 q=(const char *) source;
277 return(LocaleCompare(p,q) == 0 ? MagickTrue : MagickFalse);
281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
285 % C o m p a r e H a s h m a p S t r i n g I n f o %
289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291 % CompareHashmapStringInfo() finds an entry in a hash-map based on the
292 % contents of a string.
294 % The format of the CompareHashmapStringInfo method is:
296 % MagickBooleanType CompareHashmapStringInfo(const void *target,
297 % const void *source)
299 % A description of each parameter follows:
301 % o target: the target string.
303 % o source: the source string.
306 MagickExport MagickBooleanType CompareHashmapStringInfo(const void *target,
313 p=(const StringInfo *) target;
314 q=(const StringInfo *) source;
315 return(CompareStringInfo(p,q) == 0 ? MagickTrue : MagickFalse);
319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323 % D e s t r o y H a s h m a p %
327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329 % DestroyHashmap() frees the hash-map and all associated resources.
331 % The format of the DestroyHashmap method is:
333 % HashmapInfo *DestroyHashmap(HashmapInfo *hashmap_info)
335 % A description of each parameter follows:
337 % o hashmap_info: the hashmap info.
340 MagickExport HashmapInfo *DestroyHashmap(HashmapInfo *hashmap_info)
351 assert(hashmap_info != (HashmapInfo *) NULL);
352 assert(hashmap_info->signature == MagickSignature);
353 if (hashmap_info->debug != MagickFalse)
354 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
355 LockSemaphoreInfo(hashmap_info->semaphore);
356 for (i=0; i < (ssize_t) hashmap_info->capacity; i++)
358 list_info=hashmap_info->map[i];
359 if (list_info != (LinkedListInfo *) NULL)
361 list_info->next=list_info->head;
362 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
363 while (entry != (EntryInfo *) NULL)
365 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
366 entry->key=hashmap_info->relinquish_key(entry->key);
367 if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
368 entry->value=hashmap_info->relinquish_value(entry->value);
369 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
372 if (list_info != (LinkedListInfo *) NULL)
373 list_info=DestroyLinkedList(list_info,RelinquishMagickMemory);
375 hashmap_info->map=(LinkedListInfo **) RelinquishMagickMemory(
377 hashmap_info->signature=(~MagickSignature);
378 UnlockSemaphoreInfo(hashmap_info->semaphore);
379 DestroySemaphoreInfo(&hashmap_info->semaphore);
380 hashmap_info=(HashmapInfo *) RelinquishMagickMemory(hashmap_info);
381 return(hashmap_info);
385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389 % D e s t r o y L i n k e d L i s t %
393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 % DestroyLinkedList() frees the linked-list and all associated resources.
397 % The format of the DestroyLinkedList method is:
399 % LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
400 % void *(*relinquish_value)(void *))
402 % A description of each parameter follows:
404 % o list_info: the linked-list info.
406 % o relinquish_value: the value deallocation method; typically
407 % RelinquishMagickMemory().
410 MagickExport LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
411 void *(*relinquish_value)(void *))
419 assert(list_info != (LinkedListInfo *) NULL);
420 assert(list_info->signature == MagickSignature);
421 if (list_info->debug != MagickFalse)
422 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
423 LockSemaphoreInfo(list_info->semaphore);
424 for (next=list_info->head; next != (ElementInfo *) NULL; )
426 if (relinquish_value != (void *(*)(void *)) NULL)
427 next->value=relinquish_value(next->value);
430 entry=(ElementInfo *) RelinquishMagickMemory(entry);
432 list_info->signature=(~MagickSignature);
433 UnlockSemaphoreInfo(list_info->semaphore);
434 DestroySemaphoreInfo(&list_info->semaphore);
435 list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
444 % G e t L a s t V a l u e I n L i n k e d L i s t %
448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
450 % GetLastValueInLinkedList() gets the last value in the linked-list.
452 % The format of the GetLastValueInLinkedList method is:
454 % void *GetLastValueInLinkedList(LinkedListInfo *list_info)
456 % A description of each parameter follows:
458 % o list_info: the linked_list info.
461 MagickExport void *GetLastValueInLinkedList(LinkedListInfo *list_info)
466 assert(list_info != (LinkedListInfo *) NULL);
467 assert(list_info->signature == MagickSignature);
468 if (list_info->debug != MagickFalse)
469 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
470 if (list_info->elements == 0)
471 return((void *) NULL);
472 LockSemaphoreInfo(list_info->semaphore);
473 value=list_info->tail->value;
474 UnlockSemaphoreInfo(list_info->semaphore);
479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
483 % G e t N e x t K e y I n H a s h m a p %
487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
489 % GetNextKeyInHashmap() gets the next key in the hash-map.
491 % The format of the GetNextKeyInHashmap method is:
493 % void *GetNextKeyInHashmap(HashmapInfo *hashmap_info)
495 % A description of each parameter follows:
497 % o hashmap_info: the hashmap info.
500 MagickExport void *GetNextKeyInHashmap(HashmapInfo *hashmap_info)
511 assert(hashmap_info != (HashmapInfo *) NULL);
512 assert(hashmap_info->signature == MagickSignature);
513 if (hashmap_info->debug != MagickFalse)
514 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
515 LockSemaphoreInfo(hashmap_info->semaphore);
516 while (hashmap_info->next < hashmap_info->capacity)
518 list_info=hashmap_info->map[hashmap_info->next];
519 if (list_info != (LinkedListInfo *) NULL)
521 if (hashmap_info->head_of_list == MagickFalse)
523 list_info->next=list_info->head;
524 hashmap_info->head_of_list=MagickTrue;
526 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
527 if (entry != (EntryInfo *) NULL)
530 UnlockSemaphoreInfo(hashmap_info->semaphore);
533 hashmap_info->head_of_list=MagickFalse;
535 hashmap_info->next++;
537 UnlockSemaphoreInfo(hashmap_info->semaphore);
538 return((void *) NULL);
542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546 % G e t N e x t V a l u e I n H a s h m a p %
550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
552 % GetNextValueInHashmap() gets the next value in the hash-map.
554 % The format of the GetNextValueInHashmap method is:
556 % void *GetNextValueInHashmap(HashmapInfo *hashmap_info)
558 % A description of each parameter follows:
560 % o hashmap_info: the hashmap info.
563 MagickExport void *GetNextValueInHashmap(HashmapInfo *hashmap_info)
574 assert(hashmap_info != (HashmapInfo *) NULL);
575 assert(hashmap_info->signature == MagickSignature);
576 if (hashmap_info->debug != MagickFalse)
577 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
578 LockSemaphoreInfo(hashmap_info->semaphore);
579 while (hashmap_info->next < hashmap_info->capacity)
581 list_info=hashmap_info->map[hashmap_info->next];
582 if (list_info != (LinkedListInfo *) NULL)
584 if (hashmap_info->head_of_list == MagickFalse)
586 list_info->next=list_info->head;
587 hashmap_info->head_of_list=MagickTrue;
589 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
590 if (entry != (EntryInfo *) NULL)
593 UnlockSemaphoreInfo(hashmap_info->semaphore);
596 hashmap_info->head_of_list=MagickFalse;
598 hashmap_info->next++;
600 UnlockSemaphoreInfo(hashmap_info->semaphore);
601 return((void *) NULL);
605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
609 % G e t N e x t V a l u e I n L i n k e d L i s t %
613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
615 % GetNextValueInLinkedList() gets the next value in the linked-list.
617 % The format of the GetNextValueInLinkedList method is:
619 % void *GetNextValueInLinkedList(LinkedListInfo *list_info)
621 % A description of each parameter follows:
623 % o list_info: the linked-list info.
626 MagickExport void *GetNextValueInLinkedList(LinkedListInfo *list_info)
631 assert(list_info != (LinkedListInfo *) NULL);
632 assert(list_info->signature == MagickSignature);
633 if (list_info->debug != MagickFalse)
634 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
635 LockSemaphoreInfo(list_info->semaphore);
636 if (list_info->next == (ElementInfo *) NULL)
638 UnlockSemaphoreInfo(list_info->semaphore);
639 return((void *) NULL);
641 value=list_info->next->value;
642 list_info->next=list_info->next->next;
643 UnlockSemaphoreInfo(list_info->semaphore);
648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652 % 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 %
656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
658 % GetNumberOfEntriesInHashmap() returns the number of entries in the hash-map.
660 % The format of the GetNumberOfEntriesInHashmap method is:
662 % size_t GetNumberOfEntriesInHashmap(const HashmapInfo *hashmap_info)
664 % A description of each parameter follows:
666 % o hashmap_info: the hashmap info.
669 MagickExport size_t GetNumberOfEntriesInHashmap(
670 const HashmapInfo *hashmap_info)
672 assert(hashmap_info != (HashmapInfo *) NULL);
673 assert(hashmap_info->signature == MagickSignature);
674 if (hashmap_info->debug != MagickFalse)
675 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
676 return(hashmap_info->entries);
680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
684 % 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 %
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
690 % GetNumberOfElementsInLinkedList() returns the number of entries in the
693 % The format of the GetNumberOfElementsInLinkedList method is:
695 % size_t GetNumberOfElementsInLinkedList(
696 % const LinkedListInfo *list_info)
698 % A description of each parameter follows:
700 % o list_info: the linked-list info.
703 MagickExport size_t GetNumberOfElementsInLinkedList(
704 const LinkedListInfo *list_info)
706 assert(list_info != (LinkedListInfo *) NULL);
707 assert(list_info->signature == MagickSignature);
708 if (list_info->debug != MagickFalse)
709 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
710 return(list_info->elements);
714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718 % G e t V a l u e F r o m H a s h m a p %
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724 % GetValueFromHashmap() gets an entry from the hash-map by its key.
726 % The format of the GetValueFromHashmap method is:
728 % void *GetValueFromHashmap(HashmapInfo *hashmap_info,const void *key)
730 % A description of each parameter follows:
732 % o hashmap_info: the hashmap info.
737 MagickExport void *GetValueFromHashmap(HashmapInfo *hashmap_info,
752 assert(hashmap_info != (HashmapInfo *) NULL);
753 assert(hashmap_info->signature == MagickSignature);
754 if (hashmap_info->debug != MagickFalse)
755 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
756 if (key == (const void *) NULL)
757 return((void *) NULL);
758 LockSemaphoreInfo(hashmap_info->semaphore);
759 hash=hashmap_info->hash(key);
760 list_info=hashmap_info->map[hash % hashmap_info->capacity];
761 if (list_info != (LinkedListInfo *) NULL)
763 list_info->next=list_info->head;
764 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
765 while (entry != (EntryInfo *) NULL)
767 if (entry->hash == hash)
773 if (hashmap_info->compare !=
774 (MagickBooleanType (*)(const void *,const void *)) NULL)
775 compare=hashmap_info->compare(key,entry->key);
776 if (compare == MagickTrue)
779 UnlockSemaphoreInfo(hashmap_info->semaphore);
783 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
786 UnlockSemaphoreInfo(hashmap_info->semaphore);
787 return((void *) NULL);
791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795 % G e t V a l u e F r o m L i n k e d L i s t %
799 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
801 % GetValueFromLinkedList() gets a value from the linked-list at the specified
804 % The format of the GetValueFromLinkedList method is:
806 % void *GetValueFromLinkedList(LinkedListInfo *list_info,
807 % const size_t index)
809 % A description of each parameter follows:
811 % o list_info: the linked_list info.
813 % o index: the list index.
816 MagickExport void *GetValueFromLinkedList(LinkedListInfo *list_info,
828 assert(list_info != (LinkedListInfo *) NULL);
829 assert(list_info->signature == MagickSignature);
830 if (list_info->debug != MagickFalse)
831 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
832 if (index >= list_info->elements)
833 return((void *) NULL);
834 LockSemaphoreInfo(list_info->semaphore);
837 value=list_info->head->value;
838 UnlockSemaphoreInfo(list_info->semaphore);
841 if (index == (list_info->elements-1))
843 value=list_info->tail->value;
844 UnlockSemaphoreInfo(list_info->semaphore);
847 next=list_info->head;
848 for (i=0; i < (ssize_t) index; i++)
851 UnlockSemaphoreInfo(list_info->semaphore);
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860 % H a s h P o i n t e r T y p e %
864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866 % HashPointerType() finds an entry in a hash-map based on the address of a
869 % The format of the HashPointerType method is:
871 % size_t HashPointerType(const void *pointer)
873 % A description of each parameter follows:
875 % o pointer: compute the hash entry location from this pointer address.
878 MagickExport size_t HashPointerType(const void *pointer)
883 hash=(size_t) pointer;
884 hash+=(~(hash << 9));
892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
896 % H a s h S t r i n g T y p e %
900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902 % HashStringType() finds an entry in a hash-map based on the contents of a
905 % The format of the HashStringType method is:
907 % size_t HashStringType(const void *string)
909 % A description of each parameter follows:
911 % o string: compute the hash entry location from this string.
914 MagickExport size_t HashStringType(const void *string)
931 signature_info=AcquireSignatureInfo();
932 signature=StringToStringInfo((const char *) string);
933 UpdateSignature(signature_info,signature);
934 FinalizeSignature(signature_info);
935 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
937 for (i=0; i < 8; i++)
939 signature=DestroyStringInfo(signature);
940 signature_info=DestroySignatureInfo(signature_info);
945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
949 % H a s h S t r i n g I n f o T y p e %
953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 % Specify the HashStringInfoType() method in NewHashmap() to find an entry
956 % in a hash-map based on the contents of a string.
958 % The format of the HashStringInfoType method is:
960 % size_t HashStringInfoType(const void *string_info)
962 % A description of each parameter follows:
964 % o string_info: compute the hash entry location from this string.
967 MagickExport size_t HashStringInfoType(const void *string_info)
981 signature_info=AcquireSignatureInfo();
982 UpdateSignature(signature_info,(const StringInfo *) string_info);
983 FinalizeSignature(signature_info);
984 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
986 for (i=0; i < 8; i++)
988 signature_info=DestroySignatureInfo(signature_info);
993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997 % I n s e r t V a l u e I n L i n k e d L i s t %
1001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1003 % InsertValueInLinkedList() inserts an element in the linked-list at the
1004 % specified location.
1006 % The format of the InsertValueInLinkedList method is:
1008 % MagickBooleanType InsertValueInLinkedList(ListInfo *list_info,
1009 % const size_t index,const void *value)
1011 % A description of each parameter follows:
1013 % o list_info: the hashmap info.
1015 % o index: the index.
1017 % o value: the value.
1020 MagickExport MagickBooleanType InsertValueInLinkedList(
1021 LinkedListInfo *list_info,const size_t index,const void *value)
1023 register ElementInfo
1029 assert(list_info != (LinkedListInfo *) NULL);
1030 assert(list_info->signature == MagickSignature);
1031 if (list_info->debug != MagickFalse)
1032 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1033 if (value == (const void *) NULL)
1034 return(MagickFalse);
1035 if ((index > list_info->elements) ||
1036 (list_info->elements == list_info->capacity))
1037 return(MagickFalse);
1038 next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
1039 if (next == (ElementInfo *) NULL)
1040 return(MagickFalse);
1041 next->value=(void *) value;
1042 next->next=(ElementInfo *) NULL;
1043 LockSemaphoreInfo(list_info->semaphore);
1044 if (list_info->elements == 0)
1046 if (list_info->next == (ElementInfo *) NULL)
1047 list_info->next=next;
1048 list_info->head=next;
1049 list_info->tail=next;
1055 if (list_info->next == list_info->head)
1056 list_info->next=next;
1057 next->next=list_info->head;
1058 list_info->head=next;
1061 if (index == list_info->elements)
1063 if (list_info->next == (ElementInfo *) NULL)
1064 list_info->next=next;
1065 list_info->tail->next=next;
1066 list_info->tail=next;
1073 element=list_info->head;
1074 next->next=element->next;
1075 for (i=1; i < (ssize_t) index; i++)
1077 element=element->next;
1078 next->next=element->next;
1082 if (list_info->next == next->next)
1083 list_info->next=next;
1086 list_info->elements++;
1087 UnlockSemaphoreInfo(list_info->semaphore);
1092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1096 % 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 %
1100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1102 % InsertValueInSortedLinkedList() inserts a value in the sorted linked-list.
1104 % The format of the InsertValueInSortedLinkedList method is:
1106 % MagickBooleanType InsertValueInSortedLinkedList(ListInfo *list_info,
1107 % int (*compare)(const void *,const void *),void **replace,
1108 % const void *value)
1110 % A description of each parameter follows:
1112 % o list_info: the hashmap info.
1114 % o index: the index.
1116 % o compare: the compare method.
1118 % o replace: return previous element here.
1120 % o value: the value.
1123 MagickExport MagickBooleanType InsertValueInSortedLinkedList(
1124 LinkedListInfo *list_info,int (*compare)(const void *,const void *),
1125 void **replace,const void *value)
1130 register ElementInfo
1136 assert(list_info != (LinkedListInfo *) NULL);
1137 assert(list_info->signature == MagickSignature);
1138 if (list_info->debug != MagickFalse)
1139 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1140 if ((compare == (int (*)(const void *,const void *)) NULL) ||
1141 (value == (const void *) NULL))
1142 return(MagickFalse);
1143 if (list_info->elements == list_info->capacity)
1144 return(MagickFalse);
1145 next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
1146 if (next == (ElementInfo *) NULL)
1147 return(MagickFalse);
1148 next->value=(void *) value;
1149 element=(ElementInfo *) NULL;
1150 LockSemaphoreInfo(list_info->semaphore);
1151 next->next=list_info->head;
1152 while (next->next != (ElementInfo *) NULL)
1154 i=(ssize_t) compare(value,next->next->value);
1155 if ((i < 0) || ((replace != (void **) NULL) && (i == 0)))
1159 *replace=next->next->value;
1160 next->next=next->next->next;
1161 if (element != (ElementInfo *) NULL)
1162 element->next=(ElementInfo *) RelinquishMagickMemory(
1164 list_info->elements--;
1166 if (element != (ElementInfo *) NULL)
1169 list_info->head=next;
1173 next->next=next->next->next;
1175 if (next->next == (ElementInfo *) NULL)
1177 if (element != (ElementInfo *) NULL)
1180 list_info->head=next;
1181 list_info->tail=next;
1183 list_info->elements++;
1184 UnlockSemaphoreInfo(list_info->semaphore);
1189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1193 % I s H a s h m a p E m p t y %
1197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1199 % IsHashmapEmpty() returns MagickTrue if the hash-map is empty.
1201 % The format of the IsHashmapEmpty method is:
1203 % MagickBooleanType IsHashmapEmpty(const HashmapInfo *hashmap_info)
1205 % A description of each parameter follows:
1207 % o hashmap_info: the hashmap info.
1210 MagickExport MagickBooleanType IsHashmapEmpty(const HashmapInfo *hashmap_info)
1212 assert(hashmap_info != (HashmapInfo *) NULL);
1213 assert(hashmap_info->signature == MagickSignature);
1214 if (hashmap_info->debug != MagickFalse)
1215 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1216 return(hashmap_info->entries == 0 ? MagickTrue : MagickFalse);
1220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1224 % I s L i n k e d L i s t E m p t y %
1228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1230 % IsLinkedListEmpty() returns MagickTrue if the linked-list is empty.
1232 % The format of the IsLinkedListEmpty method is:
1234 % MagickBooleanType IsLinkedListEmpty(LinkedListInfo *list_info)
1236 % A description of each parameter follows:
1238 % o list_info: the linked-list info.
1241 MagickExport MagickBooleanType IsLinkedListEmpty(
1242 const LinkedListInfo *list_info)
1244 assert(list_info != (LinkedListInfo *) NULL);
1245 assert(list_info->signature == MagickSignature);
1246 if (list_info->debug != MagickFalse)
1247 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1248 return(list_info->elements == 0 ? MagickTrue : MagickFalse);
1252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1256 % L i n k e d L i s t T o A r r a y %
1260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1262 % LinkedListToArray() converts the linked-list to an array.
1264 % The format of the LinkedListToArray method is:
1266 % MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
1269 % A description of each parameter follows:
1271 % o list_info: the linked-list info.
1273 % o array: the array.
1276 MagickExport MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
1279 register ElementInfo
1285 assert(list_info != (LinkedListInfo *) NULL);
1286 assert(list_info->signature == MagickSignature);
1287 if (list_info->debug != MagickFalse)
1288 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1289 if (array == (void **) NULL)
1290 return(MagickFalse);
1291 LockSemaphoreInfo(list_info->semaphore);
1292 next=list_info->head;
1293 for (i=0; next != (ElementInfo *) NULL; i++)
1295 array[i]=next->value;
1298 UnlockSemaphoreInfo(list_info->semaphore);
1303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1307 % N e w H a s h m a p %
1311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1313 % NewHashmap() returns a pointer to a HashmapInfo structure initialized
1314 % to default values. The capacity is an initial estimate. The hashmap will
1315 % increase capacity dynamically as the demand requires.
1317 % The format of the NewHashmap method is:
1319 % HashmapInfo *NewHashmap(const size_t capacity,
1320 % size_t (*hash)(const void *),
1321 % MagickBooleanType (*compare)(const void *,const void *),
1322 % void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1324 % A description of each parameter follows:
1326 % o capacity: the initial number entries in the hash-map: typically
1327 % SmallHashmapSize, MediumHashmapSize, or LargeHashmapSize. The
1328 % hashmap will dynamically increase its capacity on demand.
1330 % o hash: the hash method, typically HashPointerType(), HashStringType(),
1331 % or HashStringInfoType().
1333 % o compare: the compare method, typically NULL, CompareHashmapString(),
1334 % or CompareHashmapStringInfo().
1336 % o relinquish_key: the key deallocation method, typically
1337 % RelinquishMagickMemory(), called whenever a key is removed from the
1340 % o relinquish_value: the value deallocation method; typically
1341 % RelinquishMagickMemory(), called whenever a value object is removed from
1345 MagickExport HashmapInfo *NewHashmap(const size_t capacity,
1346 size_t (*hash)(const void *),
1347 MagickBooleanType (*compare)(const void *,const void *),
1348 void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1353 hashmap_info=(HashmapInfo *) AcquireMagickMemory(sizeof(*hashmap_info));
1354 if (hashmap_info == (HashmapInfo *) NULL)
1355 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1356 (void) ResetMagickMemory(hashmap_info,0,sizeof(*hashmap_info));
1357 hashmap_info->hash=HashPointerType;
1358 if (hash != (size_t (*)(const void *)) NULL)
1359 hashmap_info->hash=hash;
1360 hashmap_info->compare=(MagickBooleanType (*)(const void *,const void *)) NULL;
1361 if (compare != (MagickBooleanType (*)(const void *,const void *)) NULL)
1362 hashmap_info->compare=compare;
1363 hashmap_info->relinquish_key=relinquish_key;
1364 hashmap_info->relinquish_value=relinquish_value;
1365 hashmap_info->entries=0;
1366 hashmap_info->capacity=capacity;
1367 hashmap_info->map=(LinkedListInfo **) NULL;
1368 if (~capacity >= 1UL)
1369 hashmap_info->map=(LinkedListInfo **) AcquireQuantumMemory((size_t)
1370 capacity+1UL,sizeof(*hashmap_info->map));
1371 if (hashmap_info->map == (LinkedListInfo **) NULL)
1372 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1373 (void) ResetMagickMemory(hashmap_info->map,0,(size_t) capacity*
1374 sizeof(*hashmap_info->map));
1375 hashmap_info->debug=IsEventLogging();
1376 hashmap_info->semaphore=AllocateSemaphoreInfo();
1377 hashmap_info->signature=MagickSignature;
1378 return(hashmap_info);
1382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1386 % N e w L i n k e d L i s t I n f o %
1390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1392 % NewLinkedList() returns a pointer to a LinkedListInfo structure
1393 % initialized to default values.
1395 % The format of the NewLinkedList method is:
1397 % LinkedListInfo *NewLinkedList(const size_t capacity)
1399 % A description of each parameter follows:
1401 % o capacity: the maximum number of elements in the list.
1404 MagickExport LinkedListInfo *NewLinkedList(const size_t capacity)
1409 list_info=(LinkedListInfo *) AcquireMagickMemory(sizeof(*list_info));
1410 if (list_info == (LinkedListInfo *) NULL)
1411 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1412 (void) ResetMagickMemory(list_info,0,sizeof(*list_info));
1413 list_info->capacity=capacity == 0 ? (size_t) (~0) : capacity;
1414 list_info->elements=0;
1415 list_info->head=(ElementInfo *) NULL;
1416 list_info->tail=(ElementInfo *) NULL;
1417 list_info->next=(ElementInfo *) NULL;
1418 list_info->debug=MagickFalse;
1419 list_info->semaphore=AllocateSemaphoreInfo();
1420 list_info->signature=MagickSignature;
1425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1429 % P u t E n t r y I n H a s h m a p %
1433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1435 % PutEntryInHashmap() puts an entry in the hash-map. If the key already
1436 % exists in the map it is first removed.
1438 % The format of the PutEntryInHashmap method is:
1440 % MagickBooleanType PutEntryInHashmap(HashmapInfo *hashmap_info,
1441 % const void *key,const void *value)
1443 % A description of each parameter follows:
1445 % o hashmap_info: the hashmap info.
1449 % o value: the value.
1453 static MagickBooleanType IncreaseHashmapCapacity(HashmapInfo *hashmap_info)
1455 #define MaxCapacities 20
1458 capacities[MaxCapacities] =
1460 17, 31, 61, 131, 257, 509, 1021, 2053, 4099, 8191, 16381, 32771,
1461 65537, 131071, 262147, 524287, 1048573, 2097143, 4194301, 8388617
1475 register ElementInfo
1485 Increase to the next prime capacity.
1487 for (i=0; i < MaxCapacities; i++)
1488 if (hashmap_info->capacity < capacities[i])
1490 if (i >= (MaxCapacities-1))
1491 return(MagickFalse);
1492 capacity=capacities[i+1];
1493 map=(LinkedListInfo **) AcquireQuantumMemory((size_t) capacity+1UL,
1495 if (map == (LinkedListInfo **) NULL)
1496 return(MagickFalse);
1497 (void) ResetMagickMemory(map,0,(size_t) capacity*sizeof(*map));
1499 Copy entries to new hashmap with increased capacity.
1501 for (i=0; i < (ssize_t) hashmap_info->capacity; i++)
1503 list_info=hashmap_info->map[i];
1504 if (list_info == (LinkedListInfo *) NULL)
1506 LockSemaphoreInfo(list_info->semaphore);
1507 for (next=list_info->head; next != (ElementInfo *) NULL; )
1511 entry=(EntryInfo *) element->value;
1512 map_info=map[entry->hash % capacity];
1513 if (map_info == (LinkedListInfo *) NULL)
1515 map_info=NewLinkedList(0);
1516 map[entry->hash % capacity]=map_info;
1518 map_info->next=element;
1519 element->next=map_info->head;
1520 map_info->head=element;
1521 map_info->elements++;
1523 list_info->signature=(~MagickSignature);
1524 UnlockSemaphoreInfo(list_info->semaphore);
1525 DestroySemaphoreInfo(&list_info->semaphore);
1526 list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
1528 hashmap_info->map=(LinkedListInfo **) RelinquishMagickMemory(
1530 hashmap_info->map=map;
1531 hashmap_info->capacity=capacity;
1535 MagickExport MagickBooleanType PutEntryInHashmap(HashmapInfo *hashmap_info,
1536 const void *key,const void *value)
1548 assert(hashmap_info != (HashmapInfo *) NULL);
1549 assert(hashmap_info->signature == MagickSignature);
1550 if (hashmap_info->debug != MagickFalse)
1551 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1552 if ((key == (void *) NULL) || (value == (void *) NULL))
1553 return(MagickFalse);
1554 next=(EntryInfo *) AcquireMagickMemory(sizeof(*next));
1555 if (next == (EntryInfo *) NULL)
1556 return(MagickFalse);
1557 LockSemaphoreInfo(hashmap_info->semaphore);
1558 next->hash=hashmap_info->hash(key);
1559 next->key=(void *) key;
1560 next->value=(void *) value;
1561 list_info=hashmap_info->map[next->hash % hashmap_info->capacity];
1562 if (list_info == (LinkedListInfo *) NULL)
1564 list_info=NewLinkedList(0);
1565 hashmap_info->map[next->hash % hashmap_info->capacity]=list_info;
1569 list_info->next=list_info->head;
1570 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1571 for (i=0; entry != (EntryInfo *) NULL; i++)
1573 if (entry->hash == next->hash)
1579 if (hashmap_info->compare !=
1580 (MagickBooleanType (*)(const void *,const void *)) NULL)
1581 compare=hashmap_info->compare(key,entry->key);
1582 if (compare == MagickTrue)
1584 (void) RemoveElementFromLinkedList(list_info,i);
1585 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
1586 entry->key=hashmap_info->relinquish_key(entry->key);
1587 if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
1588 entry->value=hashmap_info->relinquish_value(entry->value);
1589 entry=(EntryInfo *) RelinquishMagickMemory(entry);
1593 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1596 if (InsertValueInLinkedList(list_info,0,next) == MagickFalse)
1598 next=(EntryInfo *) RelinquishMagickMemory(next);
1599 UnlockSemaphoreInfo(hashmap_info->semaphore);
1600 return(MagickFalse);
1602 if (list_info->elements >= (hashmap_info->capacity-1))
1603 if (IncreaseHashmapCapacity(hashmap_info) == MagickFalse)
1605 UnlockSemaphoreInfo(hashmap_info->semaphore);
1606 return(MagickFalse);
1608 hashmap_info->entries++;
1609 UnlockSemaphoreInfo(hashmap_info->semaphore);
1614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1618 % 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 %
1622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1624 % RemoveElementByValueFromLinkedList() removes an element from the linked-list
1627 % The format of the RemoveElementByValueFromLinkedList method is:
1629 % void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
1630 % const void *value)
1632 % A description of each parameter follows:
1634 % o list_info: the list info.
1636 % o value: the value.
1639 MagickExport void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
1645 assert(list_info != (LinkedListInfo *) NULL);
1646 assert(list_info->signature == MagickSignature);
1647 if (list_info->debug != MagickFalse)
1648 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1649 if ((list_info->elements == 0) || (value == (const void *) NULL))
1650 return((void *) NULL);
1651 LockSemaphoreInfo(list_info->semaphore);
1652 if (value == list_info->head->value)
1654 if (list_info->next == list_info->head)
1655 list_info->next=list_info->head->next;
1656 next=list_info->head;
1657 list_info->head=list_info->head->next;
1658 next=(ElementInfo *) RelinquishMagickMemory(next);
1665 next=list_info->head;
1666 while ((next->next != (ElementInfo *) NULL) &&
1667 (next->next->value != value))
1669 if (next->next == (ElementInfo *) NULL)
1671 UnlockSemaphoreInfo(list_info->semaphore);
1672 return((void *) NULL);
1675 next->next=element->next;
1676 if (element == list_info->tail)
1677 list_info->tail=next;
1678 if (list_info->next == element)
1679 list_info->next=element->next;
1680 element=(ElementInfo *) RelinquishMagickMemory(element);
1682 list_info->elements--;
1683 UnlockSemaphoreInfo(list_info->semaphore);
1684 return((void *) value);
1688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1692 % 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 %
1696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1698 % RemoveElementFromLinkedList() removes an element from the linked-list at the
1699 % specified location.
1701 % The format of the RemoveElementFromLinkedList method is:
1703 % void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
1704 % const size_t index)
1706 % A description of each parameter follows:
1708 % o list_info: the linked-list info.
1710 % o index: the index.
1713 MagickExport void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
1725 assert(list_info != (LinkedListInfo *) NULL);
1726 assert(list_info->signature == MagickSignature);
1727 if (list_info->debug != MagickFalse)
1728 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1729 if (index >= list_info->elements)
1730 return((void *) NULL);
1731 LockSemaphoreInfo(list_info->semaphore);
1734 if (list_info->next == list_info->head)
1735 list_info->next=list_info->head->next;
1736 value=list_info->head->value;
1737 next=list_info->head;
1738 list_info->head=list_info->head->next;
1739 next=(ElementInfo *) RelinquishMagickMemory(next);
1746 next=list_info->head;
1747 for (i=1; i < (ssize_t) index; i++)
1750 next->next=element->next;
1751 if (element == list_info->tail)
1752 list_info->tail=next;
1753 if (list_info->next == element)
1754 list_info->next=element->next;
1755 value=element->value;
1756 element=(ElementInfo *) RelinquishMagickMemory(element);
1758 list_info->elements--;
1759 UnlockSemaphoreInfo(list_info->semaphore);
1764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1768 % R e m o v e E n t r y F r o m H a s h m a p %
1772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1774 % RemoveEntryFromHashmap() removes an entry from the hash-map by its key.
1776 % The format of the RemoveEntryFromHashmap method is:
1778 % void *RemoveEntryFromHashmap(HashmapInfo *hashmap_info,void *key)
1780 % A description of each parameter follows:
1782 % o hashmap_info: the hashmap info.
1787 MagickExport void *RemoveEntryFromHashmap(HashmapInfo *hashmap_info,
1805 assert(hashmap_info != (HashmapInfo *) NULL);
1806 assert(hashmap_info->signature == MagickSignature);
1807 if (hashmap_info->debug != MagickFalse)
1808 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1809 if (key == (const void *) NULL)
1810 return((void *) NULL);
1811 LockSemaphoreInfo(hashmap_info->semaphore);
1812 hash=hashmap_info->hash(key);
1813 list_info=hashmap_info->map[hash % hashmap_info->capacity];
1814 if (list_info != (LinkedListInfo *) NULL)
1816 list_info->next=list_info->head;
1817 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1818 for (i=0; entry != (EntryInfo *) NULL; i++)
1820 if (entry->hash == hash)
1826 if (hashmap_info->compare !=
1827 (MagickBooleanType (*)(const void *,const void *)) NULL)
1828 compare=hashmap_info->compare(key,entry->key);
1829 if (compare == MagickTrue)
1831 entry=(EntryInfo *) RemoveElementFromLinkedList(list_info,i);
1832 if (entry == (EntryInfo *) NULL)
1834 UnlockSemaphoreInfo(hashmap_info->semaphore);
1835 return((void *) NULL);
1837 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
1838 entry->key=hashmap_info->relinquish_key(entry->key);
1840 entry=(EntryInfo *) RelinquishMagickMemory(entry);
1841 hashmap_info->entries--;
1842 UnlockSemaphoreInfo(hashmap_info->semaphore);
1846 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1849 UnlockSemaphoreInfo(hashmap_info->semaphore);
1850 return((void *) NULL);
1854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1858 % 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 %
1862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1864 % RemoveLastElementFromLinkedList() removes the last element from the
1867 % The format of the RemoveLastElementFromLinkedList method is:
1869 % void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
1871 % A description of each parameter follows:
1873 % o list_info: the linked-list info.
1876 MagickExport void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
1881 assert(list_info != (LinkedListInfo *) NULL);
1882 assert(list_info->signature == MagickSignature);
1883 if (list_info->debug != MagickFalse)
1884 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1885 if (list_info->elements == 0)
1886 return((void *) NULL);
1887 LockSemaphoreInfo(list_info->semaphore);
1888 if (list_info->next == list_info->tail)
1889 list_info->next=(ElementInfo *) NULL;
1890 if (list_info->elements == 1UL)
1892 value=list_info->head->value;
1893 list_info->head=(ElementInfo *) NULL;
1894 list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
1901 value=list_info->tail->value;
1902 next=list_info->head;
1903 while (next->next != list_info->tail)
1905 list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
1906 list_info->tail=next;
1907 next->next=(ElementInfo *) NULL;
1909 list_info->elements--;
1910 UnlockSemaphoreInfo(list_info->semaphore);
1915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1919 % R e s e t H a s h m a p I t e r a t o r %
1923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1925 % ResetHashmapIterator() resets the hash-map iterator. Use it in conjunction
1926 % with GetNextKeyInHashmap() to iterate over all the keys in the hash-map.
1928 % The format of the ResetHashmapIterator method is:
1930 % ResetHashmapIterator(HashmapInfo *hashmap_info)
1932 % A description of each parameter follows:
1934 % o hashmap_info: the hashmap info.
1937 MagickExport void ResetHashmapIterator(HashmapInfo *hashmap_info)
1939 assert(hashmap_info != (HashmapInfo *) NULL);
1940 assert(hashmap_info->signature == MagickSignature);
1941 if (hashmap_info->debug != MagickFalse)
1942 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1943 LockSemaphoreInfo(hashmap_info->semaphore);
1944 hashmap_info->next=0;
1945 hashmap_info->head_of_list=MagickFalse;
1946 UnlockSemaphoreInfo(hashmap_info->semaphore);
1950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1954 % R e s e t L i n k e d L i s t I t e r a t o r %
1958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1960 % ResetLinkedListIterator() resets the lined-list iterator. Use it in
1961 % conjunction with GetNextValueInLinkedList() to iterate over all the values
1962 % in the linked-list.
1964 % The format of the ResetLinkedListIterator method is:
1966 % ResetLinkedListIterator(LinkedListInfo *list_info)
1968 % A description of each parameter follows:
1970 % o list_info: the linked-list info.
1973 MagickExport void ResetLinkedListIterator(LinkedListInfo *list_info)
1975 assert(list_info != (LinkedListInfo *) NULL);
1976 assert(list_info->signature == MagickSignature);
1977 if (list_info->debug != MagickFalse)
1978 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1979 LockSemaphoreInfo(list_info->semaphore);
1980 list_info->next=list_info->head;
1981 UnlockSemaphoreInfo(list_info->semaphore);