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-2013 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 (IfMagickTrue(list_info->debug))
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 (IfMagickTrue(list_info->debug))
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(IsMagickTrue(LocaleCompare(p,q)));
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,
309 return(IsMagickTrue(LocaleCompare((const char *)target,
310 (const char *)source)));
314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318 % D e s t r o y H a s h m a p %
322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
324 % DestroyHashmap() frees the hash-map and all associated resources.
326 % The format of the DestroyHashmap method is:
328 % HashmapInfo *DestroyHashmap(HashmapInfo *hashmap_info)
330 % A description of each parameter follows:
332 % o hashmap_info: the hashmap info.
335 MagickExport HashmapInfo *DestroyHashmap(HashmapInfo *hashmap_info)
346 assert(hashmap_info != (HashmapInfo *) NULL);
347 assert(hashmap_info->signature == MagickSignature);
348 if (IfMagickTrue(hashmap_info->debug))
349 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
350 LockSemaphoreInfo(hashmap_info->semaphore);
351 for (i=0; i < (ssize_t) hashmap_info->capacity; i++)
353 list_info=hashmap_info->map[i];
354 if (list_info != (LinkedListInfo *) NULL)
356 list_info->next=list_info->head;
357 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
358 while (entry != (EntryInfo *) NULL)
360 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
361 entry->key=hashmap_info->relinquish_key(entry->key);
362 if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
363 entry->value=hashmap_info->relinquish_value(entry->value);
364 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
367 if (list_info != (LinkedListInfo *) NULL)
368 list_info=DestroyLinkedList(list_info,RelinquishMagickMemory);
370 hashmap_info->map=(LinkedListInfo **) RelinquishMagickMemory(
372 hashmap_info->signature=(~MagickSignature);
373 UnlockSemaphoreInfo(hashmap_info->semaphore);
374 DestroySemaphoreInfo(&hashmap_info->semaphore);
375 hashmap_info=(HashmapInfo *) RelinquishMagickMemory(hashmap_info);
376 return(hashmap_info);
380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384 % D e s t r o y L i n k e d L i s t %
388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
390 % DestroyLinkedList() frees the linked-list and all associated resources.
392 % The format of the DestroyLinkedList method is:
394 % LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
395 % void *(*relinquish_value)(void *))
397 % A description of each parameter follows:
399 % o list_info: the linked-list info.
401 % o relinquish_value: the value deallocation method; typically
402 % RelinquishMagickMemory().
405 MagickExport LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
406 void *(*relinquish_value)(void *))
414 assert(list_info != (LinkedListInfo *) NULL);
415 assert(list_info->signature == MagickSignature);
416 if (IfMagickTrue(list_info->debug))
417 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
418 LockSemaphoreInfo(list_info->semaphore);
419 for (next=list_info->head; next != (ElementInfo *) NULL; )
421 if (relinquish_value != (void *(*)(void *)) NULL)
422 next->value=relinquish_value(next->value);
425 entry=(ElementInfo *) RelinquishMagickMemory(entry);
427 list_info->signature=(~MagickSignature);
428 UnlockSemaphoreInfo(list_info->semaphore);
429 DestroySemaphoreInfo(&list_info->semaphore);
430 list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
435 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439 % G e t L a s t V a l u e I n L i n k e d L i s t %
443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445 % GetLastValueInLinkedList() gets the last value in the linked-list.
447 % The format of the GetLastValueInLinkedList method is:
449 % void *GetLastValueInLinkedList(LinkedListInfo *list_info)
451 % A description of each parameter follows:
453 % o list_info: the linked_list info.
456 MagickExport void *GetLastValueInLinkedList(LinkedListInfo *list_info)
461 assert(list_info != (LinkedListInfo *) NULL);
462 assert(list_info->signature == MagickSignature);
463 if (IfMagickTrue(list_info->debug))
464 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
465 if (list_info->elements == 0)
466 return((void *) NULL);
467 LockSemaphoreInfo(list_info->semaphore);
468 value=list_info->tail->value;
469 UnlockSemaphoreInfo(list_info->semaphore);
474 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
478 % G e t N e x t K e y I n H a s h m a p %
482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484 % GetNextKeyInHashmap() gets the next key in the hash-map.
486 % The format of the GetNextKeyInHashmap method is:
488 % void *GetNextKeyInHashmap(HashmapInfo *hashmap_info)
490 % A description of each parameter follows:
492 % o hashmap_info: the hashmap info.
495 MagickExport void *GetNextKeyInHashmap(HashmapInfo *hashmap_info)
506 assert(hashmap_info != (HashmapInfo *) NULL);
507 assert(hashmap_info->signature == MagickSignature);
508 if (IfMagickTrue(hashmap_info->debug))
509 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
510 LockSemaphoreInfo(hashmap_info->semaphore);
511 while (hashmap_info->next < hashmap_info->capacity)
513 list_info=hashmap_info->map[hashmap_info->next];
514 if (list_info != (LinkedListInfo *) NULL)
516 if (IfMagickFalse(hashmap_info->head_of_list))
518 list_info->next=list_info->head;
519 hashmap_info->head_of_list=MagickTrue;
521 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
522 if (entry != (EntryInfo *) NULL)
525 UnlockSemaphoreInfo(hashmap_info->semaphore);
528 hashmap_info->head_of_list=MagickFalse;
530 hashmap_info->next++;
532 UnlockSemaphoreInfo(hashmap_info->semaphore);
533 return((void *) NULL);
537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
541 % G e t N e x t V a l u e I n H a s h m a p %
545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
547 % GetNextValueInHashmap() gets the next value in the hash-map.
549 % The format of the GetNextValueInHashmap method is:
551 % void *GetNextValueInHashmap(HashmapInfo *hashmap_info)
553 % A description of each parameter follows:
555 % o hashmap_info: the hashmap info.
558 MagickExport void *GetNextValueInHashmap(HashmapInfo *hashmap_info)
569 assert(hashmap_info != (HashmapInfo *) NULL);
570 assert(hashmap_info->signature == MagickSignature);
571 if (IfMagickTrue(hashmap_info->debug))
572 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
573 LockSemaphoreInfo(hashmap_info->semaphore);
574 while (hashmap_info->next < hashmap_info->capacity)
576 list_info=hashmap_info->map[hashmap_info->next];
577 if (list_info != (LinkedListInfo *) NULL)
579 if (IfMagickFalse(hashmap_info->head_of_list))
581 list_info->next=list_info->head;
582 hashmap_info->head_of_list=MagickTrue;
584 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
585 if (entry != (EntryInfo *) NULL)
588 UnlockSemaphoreInfo(hashmap_info->semaphore);
591 hashmap_info->head_of_list=MagickFalse;
593 hashmap_info->next++;
595 UnlockSemaphoreInfo(hashmap_info->semaphore);
596 return((void *) NULL);
600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
604 % G e t N e x t V a l u e I n L i n k e d L i s t %
608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610 % GetNextValueInLinkedList() gets the next value in the linked-list.
612 % The format of the GetNextValueInLinkedList method is:
614 % void *GetNextValueInLinkedList(LinkedListInfo *list_info)
616 % A description of each parameter follows:
618 % o list_info: the linked-list info.
621 MagickExport void *GetNextValueInLinkedList(LinkedListInfo *list_info)
626 assert(list_info != (LinkedListInfo *) NULL);
627 assert(list_info->signature == MagickSignature);
628 if (IfMagickTrue(list_info->debug))
629 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
630 LockSemaphoreInfo(list_info->semaphore);
631 if (list_info->next == (ElementInfo *) NULL)
633 UnlockSemaphoreInfo(list_info->semaphore);
634 return((void *) NULL);
636 value=list_info->next->value;
637 list_info->next=list_info->next->next;
638 UnlockSemaphoreInfo(list_info->semaphore);
643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
647 % 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 %
651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
653 % GetNumberOfEntriesInHashmap() returns the number of entries in the hash-map.
655 % The format of the GetNumberOfEntriesInHashmap method is:
657 % size_t GetNumberOfEntriesInHashmap(const HashmapInfo *hashmap_info)
659 % A description of each parameter follows:
661 % o hashmap_info: the hashmap info.
664 MagickExport size_t GetNumberOfEntriesInHashmap(
665 const HashmapInfo *hashmap_info)
667 assert(hashmap_info != (HashmapInfo *) NULL);
668 assert(hashmap_info->signature == MagickSignature);
669 if (IfMagickTrue(hashmap_info->debug))
670 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
671 return(hashmap_info->entries);
675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
679 % 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 %
683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
685 % GetNumberOfElementsInLinkedList() returns the number of entries in the
688 % The format of the GetNumberOfElementsInLinkedList method is:
690 % size_t GetNumberOfElementsInLinkedList(
691 % const LinkedListInfo *list_info)
693 % A description of each parameter follows:
695 % o list_info: the linked-list info.
698 MagickExport size_t GetNumberOfElementsInLinkedList(
699 const LinkedListInfo *list_info)
701 assert(list_info != (LinkedListInfo *) NULL);
702 assert(list_info->signature == MagickSignature);
703 if (IfMagickTrue(list_info->debug))
704 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
705 return(list_info->elements);
709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713 % G e t V a l u e F r o m H a s h m a p %
717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719 % GetValueFromHashmap() gets an entry from the hash-map by its key.
721 % The format of the GetValueFromHashmap method is:
723 % void *GetValueFromHashmap(HashmapInfo *hashmap_info,const void *key)
725 % A description of each parameter follows:
727 % o hashmap_info: the hashmap info.
732 MagickExport void *GetValueFromHashmap(HashmapInfo *hashmap_info,
747 assert(hashmap_info != (HashmapInfo *) NULL);
748 assert(hashmap_info->signature == MagickSignature);
749 if (IfMagickTrue(hashmap_info->debug))
750 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
751 if (key == (const void *) NULL)
752 return((void *) NULL);
753 LockSemaphoreInfo(hashmap_info->semaphore);
754 hash=hashmap_info->hash(key);
755 list_info=hashmap_info->map[hash % hashmap_info->capacity];
756 if (list_info != (LinkedListInfo *) NULL)
758 list_info->next=list_info->head;
759 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
760 while (entry != (EntryInfo *) NULL)
762 if (entry->hash == hash)
768 if (hashmap_info->compare !=
769 (MagickBooleanType (*)(const void *,const void *)) NULL)
770 compare=hashmap_info->compare(key,entry->key);
771 if (IfMagickTrue(compare))
774 UnlockSemaphoreInfo(hashmap_info->semaphore);
778 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
781 UnlockSemaphoreInfo(hashmap_info->semaphore);
782 return((void *) NULL);
786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
790 % G e t V a l u e F r o m L i n k e d L i s t %
794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796 % GetValueFromLinkedList() gets a value from the linked-list at the specified
799 % The format of the GetValueFromLinkedList method is:
801 % void *GetValueFromLinkedList(LinkedListInfo *list_info,
802 % const size_t index)
804 % A description of each parameter follows:
806 % o list_info: the linked_list info.
808 % o index: the list index.
811 MagickExport void *GetValueFromLinkedList(LinkedListInfo *list_info,
823 assert(list_info != (LinkedListInfo *) NULL);
824 assert(list_info->signature == MagickSignature);
825 if (IfMagickTrue(list_info->debug))
826 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
827 if (index >= list_info->elements)
828 return((void *) NULL);
829 LockSemaphoreInfo(list_info->semaphore);
832 value=list_info->head->value;
833 UnlockSemaphoreInfo(list_info->semaphore);
836 if (index == (list_info->elements-1))
838 value=list_info->tail->value;
839 UnlockSemaphoreInfo(list_info->semaphore);
842 next=list_info->head;
843 for (i=0; i < (ssize_t) index; i++)
846 UnlockSemaphoreInfo(list_info->semaphore);
851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
855 % H a s h P o i n t e r T y p e %
859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861 % HashPointerType() finds an entry in a hash-map based on the address of a
864 % The format of the HashPointerType method is:
866 % size_t HashPointerType(const void *pointer)
868 % A description of each parameter follows:
870 % o pointer: compute the hash entry location from this pointer address.
873 MagickExport size_t HashPointerType(const void *pointer)
878 hash=(size_t) pointer;
879 hash+=(~(hash << 9));
887 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891 % H a s h S t r i n g T y p e %
895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
897 % HashStringType() finds an entry in a hash-map based on the contents of a
900 % The format of the HashStringType method is:
902 % size_t HashStringType(const void *string)
904 % A description of each parameter follows:
906 % o string: compute the hash entry location from this string.
909 MagickExport size_t HashStringType(const void *string)
926 signature_info=AcquireSignatureInfo();
927 signature=StringToStringInfo((const char *) string);
928 UpdateSignature(signature_info,signature);
929 FinalizeSignature(signature_info);
930 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
932 for (i=0; i < 8; i++)
934 signature=DestroyStringInfo(signature);
935 signature_info=DestroySignatureInfo(signature_info);
940 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944 % H a s h S t r i n g I n f o T y p e %
948 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
950 % Specify the HashStringInfoType() method in NewHashmap() to find an entry
951 % in a hash-map based on the contents of a string.
953 % The format of the HashStringInfoType method is:
955 % size_t HashStringInfoType(const void *string_info)
957 % A description of each parameter follows:
959 % o string_info: compute the hash entry location from this string.
962 MagickExport size_t HashStringInfoType(const void *string_info)
976 signature_info=AcquireSignatureInfo();
977 UpdateSignature(signature_info,(const StringInfo *) string_info);
978 FinalizeSignature(signature_info);
979 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
981 for (i=0; i < 8; i++)
983 signature_info=DestroySignatureInfo(signature_info);
988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
992 % I n s e r t V a l u e I n L i n k e d L i s t %
996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
998 % InsertValueInLinkedList() inserts an element in the linked-list at the
999 % specified location.
1001 % The format of the InsertValueInLinkedList method is:
1003 % MagickBooleanType InsertValueInLinkedList(ListInfo *list_info,
1004 % const size_t index,const void *value)
1006 % A description of each parameter follows:
1008 % o list_info: the hashmap info.
1010 % o index: the index.
1012 % o value: the value.
1015 MagickExport MagickBooleanType InsertValueInLinkedList(
1016 LinkedListInfo *list_info,const size_t index,const void *value)
1018 register ElementInfo
1024 assert(list_info != (LinkedListInfo *) NULL);
1025 assert(list_info->signature == MagickSignature);
1026 if (IfMagickTrue(list_info->debug))
1027 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1028 if (value == (const void *) NULL)
1029 return(MagickFalse);
1030 if ((index > list_info->elements) ||
1031 (list_info->elements == list_info->capacity))
1032 return(MagickFalse);
1033 next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
1034 if (next == (ElementInfo *) NULL)
1035 return(MagickFalse);
1036 next->value=(void *) value;
1037 next->next=(ElementInfo *) NULL;
1038 LockSemaphoreInfo(list_info->semaphore);
1039 if (list_info->elements == 0)
1041 if (list_info->next == (ElementInfo *) NULL)
1042 list_info->next=next;
1043 list_info->head=next;
1044 list_info->tail=next;
1050 if (list_info->next == list_info->head)
1051 list_info->next=next;
1052 next->next=list_info->head;
1053 list_info->head=next;
1056 if (index == list_info->elements)
1058 if (list_info->next == (ElementInfo *) NULL)
1059 list_info->next=next;
1060 list_info->tail->next=next;
1061 list_info->tail=next;
1068 element=list_info->head;
1069 next->next=element->next;
1070 for (i=1; i < (ssize_t) index; i++)
1072 element=element->next;
1073 next->next=element->next;
1077 if (list_info->next == next->next)
1078 list_info->next=next;
1081 list_info->elements++;
1082 UnlockSemaphoreInfo(list_info->semaphore);
1087 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1091 % 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 %
1095 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1097 % InsertValueInSortedLinkedList() inserts a value in the sorted linked-list.
1099 % The format of the InsertValueInSortedLinkedList method is:
1101 % MagickBooleanType InsertValueInSortedLinkedList(ListInfo *list_info,
1102 % int (*compare)(const void *,const void *),void **replace,
1103 % const void *value)
1105 % A description of each parameter follows:
1107 % o list_info: the hashmap info.
1109 % o index: the index.
1111 % o compare: the compare method.
1113 % o replace: return previous element here.
1115 % o value: the value.
1118 MagickExport MagickBooleanType InsertValueInSortedLinkedList(
1119 LinkedListInfo *list_info,int (*compare)(const void *,const void *),
1120 void **replace,const void *value)
1125 register ElementInfo
1131 assert(list_info != (LinkedListInfo *) NULL);
1132 assert(list_info->signature == MagickSignature);
1133 if (IfMagickTrue(list_info->debug))
1134 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1135 if ((compare == (int (*)(const void *,const void *)) NULL) ||
1136 (value == (const void *) NULL))
1137 return(MagickFalse);
1138 if (list_info->elements == list_info->capacity)
1139 return(MagickFalse);
1140 next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
1141 if (next == (ElementInfo *) NULL)
1142 return(MagickFalse);
1143 next->value=(void *) value;
1144 element=(ElementInfo *) NULL;
1145 LockSemaphoreInfo(list_info->semaphore);
1146 next->next=list_info->head;
1147 while (next->next != (ElementInfo *) NULL)
1149 i=(ssize_t) compare(value,next->next->value);
1150 if ((i < 0) || ((replace != (void **) NULL) && (i == 0)))
1154 *replace=next->next->value;
1155 next->next=next->next->next;
1156 if (element != (ElementInfo *) NULL)
1157 element->next=(ElementInfo *) RelinquishMagickMemory(
1159 list_info->elements--;
1161 if (element != (ElementInfo *) NULL)
1164 list_info->head=next;
1168 next->next=next->next->next;
1170 if (next->next == (ElementInfo *) NULL)
1172 if (element != (ElementInfo *) NULL)
1175 list_info->head=next;
1176 list_info->tail=next;
1178 list_info->elements++;
1179 UnlockSemaphoreInfo(list_info->semaphore);
1184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1188 % I s H a s h m a p E m p t y %
1192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1194 % IsHashmapEmpty() returns MagickTrue if the hash-map is empty.
1196 % The format of the IsHashmapEmpty method is:
1198 % MagickBooleanType IsHashmapEmpty(const HashmapInfo *hashmap_info)
1200 % A description of each parameter follows:
1202 % o hashmap_info: the hashmap info.
1205 MagickExport MagickBooleanType IsHashmapEmpty(const HashmapInfo *hashmap_info)
1207 assert(hashmap_info != (HashmapInfo *) NULL);
1208 assert(hashmap_info->signature == MagickSignature);
1209 if (IfMagickTrue(hashmap_info->debug))
1210 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1211 return(IsMagickTrue(hashmap_info->entries == 0));
1215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1219 % I s L i n k e d L i s t E m p t y %
1223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1225 % IsLinkedListEmpty() returns MagickTrue if the linked-list is empty.
1227 % The format of the IsLinkedListEmpty method is:
1229 % MagickBooleanType IsLinkedListEmpty(LinkedListInfo *list_info)
1231 % A description of each parameter follows:
1233 % o list_info: the linked-list info.
1236 MagickExport MagickBooleanType IsLinkedListEmpty(
1237 const LinkedListInfo *list_info)
1239 assert(list_info != (LinkedListInfo *) NULL);
1240 assert(list_info->signature == MagickSignature);
1241 if (IfMagickTrue(list_info->debug))
1242 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1243 return(IsMagickTrue(list_info->elements == 0));
1247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1251 % L i n k e d L i s t T o A r r a y %
1255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1257 % LinkedListToArray() converts the linked-list to an array.
1259 % The format of the LinkedListToArray method is:
1261 % MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
1264 % A description of each parameter follows:
1266 % o list_info: the linked-list info.
1268 % o array: the array.
1271 MagickExport MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
1274 register ElementInfo
1280 assert(list_info != (LinkedListInfo *) NULL);
1281 assert(list_info->signature == MagickSignature);
1282 if (IfMagickTrue(list_info->debug))
1283 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1284 if (array == (void **) NULL)
1285 return(MagickFalse);
1286 LockSemaphoreInfo(list_info->semaphore);
1287 next=list_info->head;
1288 for (i=0; next != (ElementInfo *) NULL; i++)
1290 array[i]=next->value;
1293 UnlockSemaphoreInfo(list_info->semaphore);
1298 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1302 % N e w H a s h m a p %
1306 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1308 % NewHashmap() returns a pointer to a HashmapInfo structure initialized
1309 % to default values. The capacity is an initial estimate. The hashmap will
1310 % increase capacity dynamically as the demand requires.
1312 % The format of the NewHashmap method is:
1314 % HashmapInfo *NewHashmap(const size_t capacity,
1315 % size_t (*hash)(const void *),
1316 % MagickBooleanType (*compare)(const void *,const void *),
1317 % void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1319 % A description of each parameter follows:
1321 % o capacity: the initial number entries in the hash-map: typically
1322 % SmallHashmapSize, MediumHashmapSize, or LargeHashmapSize. The
1323 % hashmap will dynamically increase its capacity on demand.
1325 % o hash: the hash method, typically HashPointerType(), HashStringType(),
1326 % or HashStringInfoType().
1328 % o compare: the compare method, typically NULL, CompareHashmapString(),
1329 % or CompareHashmapStringInfo().
1331 % o relinquish_key: the key deallocation method, typically
1332 % RelinquishMagickMemory(), called whenever a key is removed from the
1335 % o relinquish_value: the value deallocation method; typically
1336 % RelinquishMagickMemory(), called whenever a value object is removed from
1340 MagickExport HashmapInfo *NewHashmap(const size_t capacity,
1341 size_t (*hash)(const void *),
1342 MagickBooleanType (*compare)(const void *,const void *),
1343 void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1348 hashmap_info=(HashmapInfo *) AcquireMagickMemory(sizeof(*hashmap_info));
1349 if (hashmap_info == (HashmapInfo *) NULL)
1350 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1351 (void) ResetMagickMemory(hashmap_info,0,sizeof(*hashmap_info));
1352 hashmap_info->hash=HashPointerType;
1353 if (hash != (size_t (*)(const void *)) NULL)
1354 hashmap_info->hash=hash;
1355 hashmap_info->compare=(MagickBooleanType (*)(const void *,const void *)) NULL;
1356 if (compare != (MagickBooleanType (*)(const void *,const void *)) NULL)
1357 hashmap_info->compare=compare;
1358 hashmap_info->relinquish_key=relinquish_key;
1359 hashmap_info->relinquish_value=relinquish_value;
1360 hashmap_info->entries=0;
1361 hashmap_info->capacity=capacity;
1362 hashmap_info->map=(LinkedListInfo **) NULL;
1363 if (~capacity >= 1UL)
1364 hashmap_info->map=(LinkedListInfo **) AcquireQuantumMemory((size_t)
1365 capacity+1UL,sizeof(*hashmap_info->map));
1366 if (hashmap_info->map == (LinkedListInfo **) NULL)
1367 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1368 (void) ResetMagickMemory(hashmap_info->map,0,(size_t) capacity*
1369 sizeof(*hashmap_info->map));
1370 hashmap_info->debug=IsEventLogging();
1371 hashmap_info->semaphore=AllocateSemaphoreInfo();
1372 hashmap_info->signature=MagickSignature;
1373 return(hashmap_info);
1377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1381 % N e w L i n k e d L i s t I n f o %
1385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387 % NewLinkedList() returns a pointer to a LinkedListInfo structure
1388 % initialized to default values.
1390 % The format of the NewLinkedList method is:
1392 % LinkedListInfo *NewLinkedList(const size_t capacity)
1394 % A description of each parameter follows:
1396 % o capacity: the maximum number of elements in the list.
1399 MagickExport LinkedListInfo *NewLinkedList(const size_t capacity)
1404 list_info=(LinkedListInfo *) AcquireMagickMemory(sizeof(*list_info));
1405 if (list_info == (LinkedListInfo *) NULL)
1406 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1407 (void) ResetMagickMemory(list_info,0,sizeof(*list_info));
1408 list_info->capacity=capacity == 0 ? (size_t) (~0) : capacity;
1409 list_info->elements=0;
1410 list_info->head=(ElementInfo *) NULL;
1411 list_info->tail=(ElementInfo *) NULL;
1412 list_info->next=(ElementInfo *) NULL;
1413 list_info->debug=MagickFalse;
1414 list_info->semaphore=AllocateSemaphoreInfo();
1415 list_info->signature=MagickSignature;
1420 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1424 % P u t E n t r y I n H a s h m a p %
1428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1430 % PutEntryInHashmap() puts an entry in the hash-map. If the key already
1431 % exists in the map it is first removed.
1433 % The format of the PutEntryInHashmap method is:
1435 % MagickBooleanType PutEntryInHashmap(HashmapInfo *hashmap_info,
1436 % const void *key,const void *value)
1438 % A description of each parameter follows:
1440 % o hashmap_info: the hashmap info.
1444 % o value: the value.
1448 static MagickBooleanType IncreaseHashmapCapacity(HashmapInfo *hashmap_info)
1450 #define MaxCapacities 20
1453 capacities[MaxCapacities] =
1455 17, 31, 61, 131, 257, 509, 1021, 2053, 4099, 8191, 16381, 32771,
1456 65537, 131071, 262147, 524287, 1048573, 2097143, 4194301, 8388617
1470 register ElementInfo
1480 Increase to the next prime capacity.
1482 for (i=0; i < MaxCapacities; i++)
1483 if (hashmap_info->capacity < capacities[i])
1485 if (i >= (MaxCapacities-1))
1486 return(MagickFalse);
1487 capacity=capacities[i+1];
1488 map=(LinkedListInfo **) AcquireQuantumMemory((size_t) capacity+1UL,
1490 if (map == (LinkedListInfo **) NULL)
1491 return(MagickFalse);
1492 (void) ResetMagickMemory(map,0,(size_t) capacity*sizeof(*map));
1494 Copy entries to new hashmap with increased capacity.
1496 for (i=0; i < (ssize_t) hashmap_info->capacity; i++)
1498 list_info=hashmap_info->map[i];
1499 if (list_info == (LinkedListInfo *) NULL)
1501 LockSemaphoreInfo(list_info->semaphore);
1502 for (next=list_info->head; next != (ElementInfo *) NULL; )
1506 entry=(EntryInfo *) element->value;
1507 map_info=map[entry->hash % capacity];
1508 if (map_info == (LinkedListInfo *) NULL)
1510 map_info=NewLinkedList(0);
1511 map[entry->hash % capacity]=map_info;
1513 map_info->next=element;
1514 element->next=map_info->head;
1515 map_info->head=element;
1516 map_info->elements++;
1518 list_info->signature=(~MagickSignature);
1519 UnlockSemaphoreInfo(list_info->semaphore);
1520 DestroySemaphoreInfo(&list_info->semaphore);
1521 list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
1523 hashmap_info->map=(LinkedListInfo **) RelinquishMagickMemory(
1525 hashmap_info->map=map;
1526 hashmap_info->capacity=capacity;
1530 MagickExport MagickBooleanType PutEntryInHashmap(HashmapInfo *hashmap_info,
1531 const void *key,const void *value)
1543 assert(hashmap_info != (HashmapInfo *) NULL);
1544 assert(hashmap_info->signature == MagickSignature);
1545 if (IfMagickTrue(hashmap_info->debug))
1546 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1547 if ((key == (void *) NULL) || (value == (void *) NULL))
1548 return(MagickFalse);
1549 next=(EntryInfo *) AcquireMagickMemory(sizeof(*next));
1550 if (next == (EntryInfo *) NULL)
1551 return(MagickFalse);
1552 LockSemaphoreInfo(hashmap_info->semaphore);
1553 next->hash=hashmap_info->hash(key);
1554 next->key=(void *) key;
1555 next->value=(void *) value;
1556 list_info=hashmap_info->map[next->hash % hashmap_info->capacity];
1557 if (list_info == (LinkedListInfo *) NULL)
1559 list_info=NewLinkedList(0);
1560 hashmap_info->map[next->hash % hashmap_info->capacity]=list_info;
1564 list_info->next=list_info->head;
1565 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1566 for (i=0; entry != (EntryInfo *) NULL; i++)
1568 if (entry->hash == next->hash)
1574 if (hashmap_info->compare !=
1575 (MagickBooleanType (*)(const void *,const void *)) NULL)
1576 compare=hashmap_info->compare(key,entry->key);
1577 if( IfMagickTrue(compare) )
1579 (void) RemoveElementFromLinkedList(list_info,i);
1580 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
1581 entry->key=hashmap_info->relinquish_key(entry->key);
1582 if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
1583 entry->value=hashmap_info->relinquish_value(entry->value);
1584 entry=(EntryInfo *) RelinquishMagickMemory(entry);
1588 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1591 if (IfMagickFalse(InsertValueInLinkedList(list_info,0,next)))
1593 next=(EntryInfo *) RelinquishMagickMemory(next);
1594 UnlockSemaphoreInfo(hashmap_info->semaphore);
1595 return(MagickFalse);
1597 if (list_info->elements >= (hashmap_info->capacity-1))
1598 if (IfMagickFalse(IncreaseHashmapCapacity(hashmap_info)))
1600 UnlockSemaphoreInfo(hashmap_info->semaphore);
1601 return(MagickFalse);
1603 hashmap_info->entries++;
1604 UnlockSemaphoreInfo(hashmap_info->semaphore);
1609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1613 % 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 %
1617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1619 % RemoveElementByValueFromLinkedList() removes an element from the linked-list
1622 % The format of the RemoveElementByValueFromLinkedList method is:
1624 % void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
1625 % const void *value)
1627 % A description of each parameter follows:
1629 % o list_info: the list info.
1631 % o value: the value.
1634 MagickExport void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
1640 assert(list_info != (LinkedListInfo *) NULL);
1641 assert(list_info->signature == MagickSignature);
1642 if (IfMagickTrue(list_info->debug))
1643 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1644 if ((list_info->elements == 0) || (value == (const void *) NULL))
1645 return((void *) NULL);
1646 LockSemaphoreInfo(list_info->semaphore);
1647 if (value == list_info->head->value)
1649 if (list_info->next == list_info->head)
1650 list_info->next=list_info->head->next;
1651 next=list_info->head;
1652 list_info->head=list_info->head->next;
1653 next=(ElementInfo *) RelinquishMagickMemory(next);
1660 next=list_info->head;
1661 while ((next->next != (ElementInfo *) NULL) &&
1662 (next->next->value != value))
1664 if (next->next == (ElementInfo *) NULL)
1666 UnlockSemaphoreInfo(list_info->semaphore);
1667 return((void *) NULL);
1670 next->next=element->next;
1671 if (element == list_info->tail)
1672 list_info->tail=next;
1673 if (list_info->next == element)
1674 list_info->next=element->next;
1675 element=(ElementInfo *) RelinquishMagickMemory(element);
1677 list_info->elements--;
1678 UnlockSemaphoreInfo(list_info->semaphore);
1679 return((void *) value);
1683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1687 % 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 %
1691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1693 % RemoveElementFromLinkedList() removes an element from the linked-list at the
1694 % specified location.
1696 % The format of the RemoveElementFromLinkedList method is:
1698 % void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
1699 % const size_t index)
1701 % A description of each parameter follows:
1703 % o list_info: the linked-list info.
1705 % o index: the index.
1708 MagickExport void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
1720 assert(list_info != (LinkedListInfo *) NULL);
1721 assert(list_info->signature == MagickSignature);
1722 if (IfMagickTrue(list_info->debug))
1723 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1724 if (index >= list_info->elements)
1725 return((void *) NULL);
1726 LockSemaphoreInfo(list_info->semaphore);
1729 if (list_info->next == list_info->head)
1730 list_info->next=list_info->head->next;
1731 value=list_info->head->value;
1732 next=list_info->head;
1733 list_info->head=list_info->head->next;
1734 next=(ElementInfo *) RelinquishMagickMemory(next);
1741 next=list_info->head;
1742 for (i=1; i < (ssize_t) index; i++)
1745 next->next=element->next;
1746 if (element == list_info->tail)
1747 list_info->tail=next;
1748 if (list_info->next == element)
1749 list_info->next=element->next;
1750 value=element->value;
1751 element=(ElementInfo *) RelinquishMagickMemory(element);
1753 list_info->elements--;
1754 UnlockSemaphoreInfo(list_info->semaphore);
1759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1763 % R e m o v e E n t r y F r o m H a s h m a p %
1767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1769 % RemoveEntryFromHashmap() removes an entry from the hash-map by its key.
1771 % The format of the RemoveEntryFromHashmap method is:
1773 % void *RemoveEntryFromHashmap(HashmapInfo *hashmap_info,void *key)
1775 % A description of each parameter follows:
1777 % o hashmap_info: the hashmap info.
1782 MagickExport void *RemoveEntryFromHashmap(HashmapInfo *hashmap_info,
1800 assert(hashmap_info != (HashmapInfo *) NULL);
1801 assert(hashmap_info->signature == MagickSignature);
1802 if (IfMagickTrue(hashmap_info->debug))
1803 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1804 if (key == (const void *) NULL)
1805 return((void *) NULL);
1806 LockSemaphoreInfo(hashmap_info->semaphore);
1807 hash=hashmap_info->hash(key);
1808 list_info=hashmap_info->map[hash % hashmap_info->capacity];
1809 if (list_info != (LinkedListInfo *) NULL)
1811 list_info->next=list_info->head;
1812 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1813 for (i=0; entry != (EntryInfo *) NULL; i++)
1815 if (entry->hash == hash)
1821 if (hashmap_info->compare !=
1822 (MagickBooleanType (*)(const void *,const void *)) NULL)
1823 compare=hashmap_info->compare(key,entry->key);
1824 if( IfMagickTrue(compare) )
1826 entry=(EntryInfo *) RemoveElementFromLinkedList(list_info,i);
1827 if (entry == (EntryInfo *) NULL)
1829 UnlockSemaphoreInfo(hashmap_info->semaphore);
1830 return((void *) NULL);
1832 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
1833 entry->key=hashmap_info->relinquish_key(entry->key);
1835 entry=(EntryInfo *) RelinquishMagickMemory(entry);
1836 hashmap_info->entries--;
1837 UnlockSemaphoreInfo(hashmap_info->semaphore);
1841 entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1844 UnlockSemaphoreInfo(hashmap_info->semaphore);
1845 return((void *) NULL);
1849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1853 % 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 %
1857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1859 % RemoveLastElementFromLinkedList() removes the last element from the
1862 % The format of the RemoveLastElementFromLinkedList method is:
1864 % void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
1866 % A description of each parameter follows:
1868 % o list_info: the linked-list info.
1871 MagickExport void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
1876 assert(list_info != (LinkedListInfo *) NULL);
1877 assert(list_info->signature == MagickSignature);
1878 if (IfMagickTrue(list_info->debug))
1879 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1880 if (list_info->elements == 0)
1881 return((void *) NULL);
1882 LockSemaphoreInfo(list_info->semaphore);
1883 if (list_info->next == list_info->tail)
1884 list_info->next=(ElementInfo *) NULL;
1885 if (list_info->elements == 1UL)
1887 value=list_info->head->value;
1888 list_info->head=(ElementInfo *) NULL;
1889 list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
1896 value=list_info->tail->value;
1897 next=list_info->head;
1898 while (next->next != list_info->tail)
1900 list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
1901 list_info->tail=next;
1902 next->next=(ElementInfo *) NULL;
1904 list_info->elements--;
1905 UnlockSemaphoreInfo(list_info->semaphore);
1910 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1914 % R e s e t H a s h m a p I t e r a t o r %
1918 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1920 % ResetHashmapIterator() resets the hash-map iterator. Use it in conjunction
1921 % with GetNextKeyInHashmap() to iterate over all the keys in the hash-map.
1923 % The format of the ResetHashmapIterator method is:
1925 % ResetHashmapIterator(HashmapInfo *hashmap_info)
1927 % A description of each parameter follows:
1929 % o hashmap_info: the hashmap info.
1932 MagickExport void ResetHashmapIterator(HashmapInfo *hashmap_info)
1934 assert(hashmap_info != (HashmapInfo *) NULL);
1935 assert(hashmap_info->signature == MagickSignature);
1936 if (IfMagickTrue(hashmap_info->debug))
1937 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1938 LockSemaphoreInfo(hashmap_info->semaphore);
1939 hashmap_info->next=0;
1940 hashmap_info->head_of_list=MagickFalse;
1941 UnlockSemaphoreInfo(hashmap_info->semaphore);
1945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1949 % R e s e t L i n k e d L i s t I t e r a t o r %
1953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1955 % ResetLinkedListIterator() resets the lined-list iterator. Use it in
1956 % conjunction with GetNextValueInLinkedList() to iterate over all the values
1957 % in the linked-list.
1959 % The format of the ResetLinkedListIterator method is:
1961 % ResetLinkedListIterator(LinkedListInfo *list_info)
1963 % A description of each parameter follows:
1965 % o list_info: the linked-list info.
1968 MagickExport void ResetLinkedListIterator(LinkedListInfo *list_info)
1970 assert(list_info != (LinkedListInfo *) NULL);
1971 assert(list_info->signature == MagickSignature);
1972 if (IfMagickTrue(list_info->debug))
1973 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1974 LockSemaphoreInfo(list_info->semaphore);
1975 list_info->next=list_info->head;
1976 UnlockSemaphoreInfo(list_info->semaphore);