2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
6 % L IIIII N N K K EEEEE DDDD L IIIII SSSSS TTTTT %
\r
7 % L I NN N K K E D D L I SS T %
\r
8 % L I N N N KKK EEE D D = L I SSS T %
\r
9 % L I N NN K K E D D L I SS T %
\r
10 % LLLLL IIIII N N K K EEEEE DDDD LLLLL IIIII SSSSS T %
\r
13 % MagickCore Linked-list Methods %
\r
20 % Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization %
\r
21 % dedicated to making software imaging solutions freely available. %
\r
23 % You may not use this file except in compliance with the License. You may %
\r
24 % obtain a copy of the License at %
\r
26 % https://www.imagemagick.org/script/license.php %
\r
28 % Unless required by applicable law or agreed to in writing, software %
\r
29 % distributed under the License is distributed on an "AS IS" BASIS, %
\r
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
\r
31 % See the License for the specific language governing permissions and %
\r
32 % limitations under the License. %
\r
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
36 % This module implements the standard handy hash and linked-list methods for
\r
37 % storing and retrieving large numbers of data elements. It is loosely based
\r
38 % on the Java implementation of these algorithms.
\r
43 Include declarations.
\r
45 #include "MagickCore/studio.h"
\r
46 #include "MagickCore/exception.h"
\r
47 #include "MagickCore/exception-private.h"
\r
48 #include "MagickCore/linked-list.h"
\r
49 #include "MagickCore/locale_.h"
\r
50 #include "MagickCore/memory_.h"
\r
51 #include "MagickCore/semaphore.h"
\r
52 #include "MagickCore/signature-private.h"
\r
53 #include "MagickCore/string_.h"
\r
56 Typedef declarations.
\r
58 typedef struct _ElementInfo
\r
67 struct _LinkedListInfo
\r
86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
90 % A p p e n d V a l u e T o L i n k e d L i s t %
\r
94 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
96 % AppendValueToLinkedList() appends a value to the end of the linked-list.
\r
98 % The format of the AppendValueToLinkedList method is:
\r
100 % MagickBooleanType AppendValueToLinkedList(LinkedListInfo *list_info,
\r
101 % const void *value)
\r
103 % A description of each parameter follows:
\r
105 % o list_info: the linked-list info.
\r
107 % o value: the value.
\r
110 MagickExport MagickBooleanType AppendValueToLinkedList(
\r
111 LinkedListInfo *list_info,const void *value)
\r
113 register ElementInfo
\r
116 assert(list_info != (LinkedListInfo *) NULL);
\r
117 assert(list_info->signature == MagickCoreSignature);
\r
118 if (list_info->elements == list_info->capacity)
\r
119 return(MagickFalse);
\r
120 next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
\r
121 if (next == (ElementInfo *) NULL)
\r
122 return(MagickFalse);
\r
123 next->value=(void *) value;
\r
124 next->next=(ElementInfo *) NULL;
\r
125 LockSemaphoreInfo(list_info->semaphore);
\r
126 if (list_info->next == (ElementInfo *) NULL)
\r
127 list_info->next=next;
\r
128 if (list_info->elements == 0)
\r
129 list_info->head=next;
\r
131 list_info->tail->next=next;
\r
132 list_info->tail=next;
\r
133 list_info->elements++;
\r
134 UnlockSemaphoreInfo(list_info->semaphore);
\r
135 return(MagickTrue);
\r
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
143 % C l e a r L i n k e d L i s t %
\r
147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
149 % ClearLinkedList() clears all the elements from the linked-list.
\r
151 % The format of the ClearLinkedList method is:
\r
153 % void ClearLinkedList(LinkedListInfo *list_info,
\r
154 % void *(*relinquish_value)(void *))
\r
156 % A description of each parameter follows:
\r
158 % o list_info: the linked-list info.
\r
160 % o relinquish_value: the value deallocation method; typically
\r
161 % RelinquishMagickMemory().
\r
164 MagickExport void ClearLinkedList(LinkedListInfo *list_info,
\r
165 void *(*relinquish_value)(void *))
\r
170 register ElementInfo
\r
173 assert(list_info != (LinkedListInfo *) NULL);
\r
174 assert(list_info->signature == MagickCoreSignature);
\r
175 LockSemaphoreInfo(list_info->semaphore);
\r
176 next=list_info->head;
\r
177 while (next != (ElementInfo *) NULL)
\r
179 if (relinquish_value != (void *(*)(void *)) NULL)
\r
180 next->value=relinquish_value(next->value);
\r
183 element=(ElementInfo *) RelinquishMagickMemory(element);
\r
185 list_info->head=(ElementInfo *) NULL;
\r
186 list_info->tail=(ElementInfo *) NULL;
\r
187 list_info->next=(ElementInfo *) NULL;
\r
188 list_info->elements=0;
\r
189 UnlockSemaphoreInfo(list_info->semaphore);
\r
193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
197 % D e s t r o y L i n k e d L i s t %
\r
201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
203 % DestroyLinkedList() frees the linked-list and all associated resources.
\r
205 % The format of the DestroyLinkedList method is:
\r
207 % LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
\r
208 % void *(*relinquish_value)(void *))
\r
210 % A description of each parameter follows:
\r
212 % o list_info: the linked-list info.
\r
214 % o relinquish_value: the value deallocation method; typically
\r
215 % RelinquishMagickMemory().
\r
218 MagickExport LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
\r
219 void *(*relinquish_value)(void *))
\r
224 register ElementInfo
\r
227 assert(list_info != (LinkedListInfo *) NULL);
\r
228 assert(list_info->signature == MagickCoreSignature);
\r
229 LockSemaphoreInfo(list_info->semaphore);
\r
230 for (next=list_info->head; next != (ElementInfo *) NULL; )
\r
232 if (relinquish_value != (void *(*)(void *)) NULL)
\r
233 next->value=relinquish_value(next->value);
\r
236 entry=(ElementInfo *) RelinquishMagickMemory(entry);
\r
238 list_info->signature=(~MagickCoreSignature);
\r
239 UnlockSemaphoreInfo(list_info->semaphore);
\r
240 RelinquishSemaphoreInfo(&list_info->semaphore);
\r
241 list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
\r
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
250 % G e t L a s t V a l u e I n L i n k e d L i s t %
\r
254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
256 % GetLastValueInLinkedList() gets the last value in the linked-list.
\r
258 % The format of the GetLastValueInLinkedList method is:
\r
260 % void *GetLastValueInLinkedList(LinkedListInfo *list_info)
\r
262 % A description of each parameter follows:
\r
264 % o list_info: the linked_list info.
\r
267 MagickExport void *GetLastValueInLinkedList(LinkedListInfo *list_info)
\r
272 assert(list_info != (LinkedListInfo *) NULL);
\r
273 assert(list_info->signature == MagickCoreSignature);
\r
274 if (list_info->elements == 0)
\r
275 return((void *) NULL);
\r
276 LockSemaphoreInfo(list_info->semaphore);
\r
277 value=list_info->tail->value;
\r
278 UnlockSemaphoreInfo(list_info->semaphore);
\r
283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
287 % G e t N e x t V a l u e I n L i n k e d L i s t %
\r
291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
293 % GetNextValueInLinkedList() gets the next value in the linked-list.
\r
295 % The format of the GetNextValueInLinkedList method is:
\r
297 % void *GetNextValueInLinkedList(LinkedListInfo *list_info)
\r
299 % A description of each parameter follows:
\r
301 % o list_info: the linked-list info.
\r
304 MagickExport void *GetNextValueInLinkedList(LinkedListInfo *list_info)
\r
309 assert(list_info != (LinkedListInfo *) NULL);
\r
310 assert(list_info->signature == MagickCoreSignature);
\r
311 LockSemaphoreInfo(list_info->semaphore);
\r
312 if (list_info->next == (ElementInfo *) NULL)
\r
314 UnlockSemaphoreInfo(list_info->semaphore);
\r
315 return((void *) NULL);
\r
317 value=list_info->next->value;
\r
318 list_info->next=list_info->next->next;
\r
319 UnlockSemaphoreInfo(list_info->semaphore);
\r
324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
328 % 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 %
\r
332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
334 % GetNumberOfElementsInLinkedList() returns the number of entries in the
\r
337 % The format of the GetNumberOfElementsInLinkedList method is:
\r
339 % size_t GetNumberOfElementsInLinkedList(
\r
340 % const LinkedListInfo *list_info)
\r
342 % A description of each parameter follows:
\r
344 % o list_info: the linked-list info.
\r
347 MagickExport size_t GetNumberOfElementsInLinkedList(
\r
348 const LinkedListInfo *list_info)
\r
350 assert(list_info != (LinkedListInfo *) NULL);
\r
351 assert(list_info->signature == MagickCoreSignature);
\r
352 return(list_info->elements);
\r
356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
360 % G e t V a l u e F r o m L i n k e d L i s t %
\r
364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
366 % GetValueFromLinkedList() gets a value from the linked-list at the specified
\r
369 % The format of the GetValueFromLinkedList method is:
\r
371 % void *GetValueFromLinkedList(LinkedListInfo *list_info,
\r
372 % const size_t index)
\r
374 % A description of each parameter follows:
\r
376 % o list_info: the linked_list info.
\r
378 % o index: the list index.
\r
381 MagickExport void *GetValueFromLinkedList(LinkedListInfo *list_info,
\r
382 const size_t index)
\r
384 register ElementInfo
\r
393 assert(list_info != (LinkedListInfo *) NULL);
\r
394 assert(list_info->signature == MagickCoreSignature);
\r
395 if (index >= list_info->elements)
\r
396 return((void *) NULL);
\r
397 LockSemaphoreInfo(list_info->semaphore);
\r
400 value=list_info->head->value;
\r
401 UnlockSemaphoreInfo(list_info->semaphore);
\r
404 if (index == (list_info->elements-1))
\r
406 value=list_info->tail->value;
\r
407 UnlockSemaphoreInfo(list_info->semaphore);
\r
410 next=list_info->head;
\r
411 for (i=0; i < (ssize_t) index; i++)
\r
414 UnlockSemaphoreInfo(list_info->semaphore);
\r
419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
423 % I n s e r t V a l u e I n L i n k e d L i s t %
\r
427 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
429 % InsertValueInLinkedList() inserts an element in the linked-list at the
\r
430 % specified location.
\r
432 % The format of the InsertValueInLinkedList method is:
\r
434 % MagickBooleanType InsertValueInLinkedList(ListInfo *list_info,
\r
435 % const size_t index,const void *value)
\r
437 % A description of each parameter follows:
\r
439 % o list_info: the hashmap info.
\r
441 % o index: the index.
\r
443 % o value: the value.
\r
446 MagickExport MagickBooleanType InsertValueInLinkedList(
\r
447 LinkedListInfo *list_info,const size_t index,const void *value)
\r
449 register ElementInfo
\r
455 assert(list_info != (LinkedListInfo *) NULL);
\r
456 assert(list_info->signature == MagickCoreSignature);
\r
457 if (value == (const void *) NULL)
\r
458 return(MagickFalse);
\r
459 if ((index > list_info->elements) ||
\r
460 (list_info->elements == list_info->capacity))
\r
461 return(MagickFalse);
\r
462 next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
\r
463 if (next == (ElementInfo *) NULL)
\r
464 return(MagickFalse);
\r
465 next->value=(void *) value;
\r
466 next->next=(ElementInfo *) NULL;
\r
467 LockSemaphoreInfo(list_info->semaphore);
\r
468 if (list_info->elements == 0)
\r
470 if (list_info->next == (ElementInfo *) NULL)
\r
471 list_info->next=next;
\r
472 list_info->head=next;
\r
473 list_info->tail=next;
\r
479 if (list_info->next == list_info->head)
\r
480 list_info->next=next;
\r
481 next->next=list_info->head;
\r
482 list_info->head=next;
\r
485 if (index == list_info->elements)
\r
487 if (list_info->next == (ElementInfo *) NULL)
\r
488 list_info->next=next;
\r
489 list_info->tail->next=next;
\r
490 list_info->tail=next;
\r
497 element=list_info->head;
\r
498 next->next=element->next;
\r
499 for (i=1; i < (ssize_t) index; i++)
\r
501 element=element->next;
\r
502 next->next=element->next;
\r
505 element->next=next;
\r
506 if (list_info->next == next->next)
\r
507 list_info->next=next;
\r
510 list_info->elements++;
\r
511 UnlockSemaphoreInfo(list_info->semaphore);
\r
512 return(MagickTrue);
\r
516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
520 % 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 %
\r
524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
526 % InsertValueInSortedLinkedList() inserts a value in the sorted linked-list.
\r
528 % The format of the InsertValueInSortedLinkedList method is:
\r
530 % MagickBooleanType InsertValueInSortedLinkedList(ListInfo *list_info,
\r
531 % int (*compare)(const void *,const void *),void **replace,
\r
532 % const void *value)
\r
534 % A description of each parameter follows:
\r
536 % o list_info: the hashmap info.
\r
538 % o index: the index.
\r
540 % o compare: the compare method.
\r
542 % o replace: return previous element here.
\r
544 % o value: the value.
\r
547 MagickExport MagickBooleanType InsertValueInSortedLinkedList(
\r
548 LinkedListInfo *list_info,int (*compare)(const void *,const void *),
\r
549 void **replace,const void *value)
\r
554 register ElementInfo
\r
560 assert(list_info != (LinkedListInfo *) NULL);
\r
561 assert(list_info->signature == MagickCoreSignature);
\r
562 if ((compare == (int (*)(const void *,const void *)) NULL) ||
\r
563 (value == (const void *) NULL))
\r
564 return(MagickFalse);
\r
565 if (list_info->elements == list_info->capacity)
\r
566 return(MagickFalse);
\r
567 next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
\r
568 if (next == (ElementInfo *) NULL)
\r
569 return(MagickFalse);
\r
570 next->value=(void *) value;
\r
571 element=(ElementInfo *) NULL;
\r
572 LockSemaphoreInfo(list_info->semaphore);
\r
573 next->next=list_info->head;
\r
574 while (next->next != (ElementInfo *) NULL)
\r
576 i=(ssize_t) compare(value,next->next->value);
\r
577 if ((i < 0) || ((replace != (void **) NULL) && (i == 0)))
\r
581 *replace=next->next->value;
\r
582 next->next=next->next->next;
\r
583 if (element != (ElementInfo *) NULL)
\r
584 element->next=(ElementInfo *) RelinquishMagickMemory(
\r
586 list_info->elements--;
\r
588 if (element != (ElementInfo *) NULL)
\r
589 element->next=next;
\r
591 list_info->head=next;
\r
594 element=next->next;
\r
595 next->next=next->next->next;
\r
597 if (next->next == (ElementInfo *) NULL)
\r
599 if (element != (ElementInfo *) NULL)
\r
600 element->next=next;
\r
602 list_info->head=next;
\r
603 list_info->tail=next;
\r
605 list_info->elements++;
\r
606 UnlockSemaphoreInfo(list_info->semaphore);
\r
607 return(MagickTrue);
\r
611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
615 % I s L i n k e d L i s t E m p t y %
\r
619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
621 % IsLinkedListEmpty() returns MagickTrue if the linked-list is empty.
\r
623 % The format of the IsLinkedListEmpty method is:
\r
625 % MagickBooleanType IsLinkedListEmpty(LinkedListInfo *list_info)
\r
627 % A description of each parameter follows:
\r
629 % o list_info: the linked-list info.
\r
632 MagickExport MagickBooleanType IsLinkedListEmpty(
\r
633 const LinkedListInfo *list_info)
\r
635 assert(list_info != (LinkedListInfo *) NULL);
\r
636 assert(list_info->signature == MagickCoreSignature);
\r
637 return(list_info->elements == 0 ? MagickTrue : MagickFalse);
\r
641 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
645 % L i n k e d L i s t T o A r r a y %
\r
649 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
651 % LinkedListToArray() converts the linked-list to an array.
\r
653 % The format of the LinkedListToArray method is:
\r
655 % MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
\r
658 % A description of each parameter follows:
\r
660 % o list_info: the linked-list info.
\r
662 % o array: the array.
\r
665 MagickExport MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
\r
668 register ElementInfo
\r
674 assert(list_info != (LinkedListInfo *) NULL);
\r
675 assert(list_info->signature == MagickCoreSignature);
\r
676 if (array == (void **) NULL)
\r
677 return(MagickFalse);
\r
678 LockSemaphoreInfo(list_info->semaphore);
\r
679 next=list_info->head;
\r
680 for (i=0; next != (ElementInfo *) NULL; i++)
\r
682 array[i]=next->value;
\r
685 UnlockSemaphoreInfo(list_info->semaphore);
\r
686 return(MagickTrue);
\r
690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
694 % N e w L i n k e d L i s t I n f o %
\r
698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
700 % NewLinkedList() returns a pointer to a LinkedListInfo structure
\r
701 % initialized to default values.
\r
703 % The format of the NewLinkedList method is:
\r
705 % LinkedListInfo *NewLinkedList(const size_t capacity)
\r
707 % A description of each parameter follows:
\r
709 % o capacity: the maximum number of elements in the list.
\r
712 MagickExport LinkedListInfo *NewLinkedList(const size_t capacity)
\r
717 list_info=(LinkedListInfo *) AcquireMagickMemory(sizeof(*list_info));
\r
718 if (list_info == (LinkedListInfo *) NULL)
\r
719 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
\r
720 (void) ResetMagickMemory(list_info,0,sizeof(*list_info));
\r
721 list_info->capacity=capacity == 0 ? (size_t) (~0) : capacity;
\r
722 list_info->elements=0;
\r
723 list_info->head=(ElementInfo *) NULL;
\r
724 list_info->tail=(ElementInfo *) NULL;
\r
725 list_info->next=(ElementInfo *) NULL;
\r
726 list_info->semaphore=AcquireSemaphoreInfo();
\r
727 list_info->signature=MagickCoreSignature;
\r
732 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
736 % 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 %
\r
740 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
742 % RemoveElementByValueFromLinkedList() removes an element from the linked-list
\r
745 % The format of the RemoveElementByValueFromLinkedList method is:
\r
747 % void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
\r
748 % const void *value)
\r
750 % A description of each parameter follows:
\r
752 % o list_info: the list info.
\r
754 % o value: the value.
\r
757 MagickExport void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
\r
763 assert(list_info != (LinkedListInfo *) NULL);
\r
764 assert(list_info->signature == MagickCoreSignature);
\r
765 if ((list_info->elements == 0) || (value == (const void *) NULL))
\r
766 return((void *) NULL);
\r
767 LockSemaphoreInfo(list_info->semaphore);
\r
768 if (value == list_info->head->value)
\r
770 if (list_info->next == list_info->head)
\r
771 list_info->next=list_info->head->next;
\r
772 next=list_info->head;
\r
773 list_info->head=list_info->head->next;
\r
774 next=(ElementInfo *) RelinquishMagickMemory(next);
\r
781 next=list_info->head;
\r
782 while ((next->next != (ElementInfo *) NULL) &&
\r
783 (next->next->value != value))
\r
785 if (next->next == (ElementInfo *) NULL)
\r
787 UnlockSemaphoreInfo(list_info->semaphore);
\r
788 return((void *) NULL);
\r
790 element=next->next;
\r
791 next->next=element->next;
\r
792 if (element == list_info->tail)
\r
793 list_info->tail=next;
\r
794 if (list_info->next == element)
\r
795 list_info->next=element->next;
\r
796 element=(ElementInfo *) RelinquishMagickMemory(element);
\r
798 list_info->elements--;
\r
799 UnlockSemaphoreInfo(list_info->semaphore);
\r
800 return((void *) value);
\r
804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
808 % 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 %
\r
812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
814 % RemoveElementFromLinkedList() removes an element from the linked-list at the
\r
815 % specified location.
\r
817 % The format of the RemoveElementFromLinkedList method is:
\r
819 % void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
\r
820 % const size_t index)
\r
822 % A description of each parameter follows:
\r
824 % o list_info: the linked-list info.
\r
826 % o index: the index.
\r
829 MagickExport void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
\r
830 const size_t index)
\r
841 assert(list_info != (LinkedListInfo *) NULL);
\r
842 assert(list_info->signature == MagickCoreSignature);
\r
843 if (index >= list_info->elements)
\r
844 return((void *) NULL);
\r
845 LockSemaphoreInfo(list_info->semaphore);
\r
848 if (list_info->next == list_info->head)
\r
849 list_info->next=list_info->head->next;
\r
850 value=list_info->head->value;
\r
851 next=list_info->head;
\r
852 list_info->head=list_info->head->next;
\r
853 next=(ElementInfo *) RelinquishMagickMemory(next);
\r
860 next=list_info->head;
\r
861 for (i=1; i < (ssize_t) index; i++)
\r
863 element=next->next;
\r
864 next->next=element->next;
\r
865 if (element == list_info->tail)
\r
866 list_info->tail=next;
\r
867 if (list_info->next == element)
\r
868 list_info->next=element->next;
\r
869 value=element->value;
\r
870 element=(ElementInfo *) RelinquishMagickMemory(element);
\r
872 list_info->elements--;
\r
873 UnlockSemaphoreInfo(list_info->semaphore);
\r
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
882 % 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 %
\r
886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
888 % RemoveLastElementFromLinkedList() removes the last element from the
\r
891 % The format of the RemoveLastElementFromLinkedList method is:
\r
893 % void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
\r
895 % A description of each parameter follows:
\r
897 % o list_info: the linked-list info.
\r
900 MagickExport void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
\r
905 assert(list_info != (LinkedListInfo *) NULL);
\r
906 assert(list_info->signature == MagickCoreSignature);
\r
907 if (list_info->elements == 0)
\r
908 return((void *) NULL);
\r
909 LockSemaphoreInfo(list_info->semaphore);
\r
910 if (list_info->next == list_info->tail)
\r
911 list_info->next=(ElementInfo *) NULL;
\r
912 if (list_info->elements == 1UL)
\r
914 value=list_info->head->value;
\r
915 list_info->head=(ElementInfo *) NULL;
\r
916 list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
\r
923 value=list_info->tail->value;
\r
924 next=list_info->head;
\r
925 while (next->next != list_info->tail)
\r
927 list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
\r
928 list_info->tail=next;
\r
929 next->next=(ElementInfo *) NULL;
\r
931 list_info->elements--;
\r
932 UnlockSemaphoreInfo(list_info->semaphore);
\r
937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
941 % R e s e t L i n k e d L i s t I t e r a t o r %
\r
945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\r
947 % ResetLinkedListIterator() resets the lined-list iterator. Use it in
\r
948 % conjunction with GetNextValueInLinkedList() to iterate over all the values
\r
949 % in the linked-list.
\r
951 % The format of the ResetLinkedListIterator method is:
\r
953 % ResetLinkedListIterator(LinkedListInfo *list_info)
\r
955 % A description of each parameter follows:
\r
957 % o list_info: the linked-list info.
\r
960 MagickExport void ResetLinkedListIterator(LinkedListInfo *list_info)
\r
962 assert(list_info != (LinkedListInfo *) NULL);
\r
963 assert(list_info->signature == MagickCoreSignature);
\r
964 LockSemaphoreInfo(list_info->semaphore);
\r
965 list_info->next=list_info->head;
\r
966 UnlockSemaphoreInfo(list_info->semaphore);
\r