-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% L IIIII N N K K EEEEE DDDD L IIIII SSSSS TTTTT %\r
-% L I NN N K K E D D L I SS T %\r
-% L I N N N KKK EEE D D = L I SSS T %\r
-% L I N NN K K E D D L I SS T %\r
-% LLLLL IIIII N N K K EEEEE DDDD LLLLL IIIII SSSSS T %\r
-% %\r
-% %\r
-% MagickCore Linked-list Methods %\r
-% %\r
-% Software Design %\r
-% Cristy %\r
-% December 2002 %\r
-% %\r
-% %\r
-% Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %\r
-% dedicated to making software imaging solutions freely available. %\r
-% %\r
-% You may not use this file except in compliance with the License. You may %\r
-% obtain a copy of the License at %\r
-% %\r
-% https://imagemagick.org/script/license.php %\r
-% %\r
-% Unless required by applicable law or agreed to in writing, software %\r
-% distributed under the License is distributed on an "AS IS" BASIS, %\r
-% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %\r
-% See the License for the specific language governing permissions and %\r
-% limitations under the License. %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% This module implements the standard handy hash and linked-list methods for\r
-% storing and retrieving large numbers of data elements. It is loosely based\r
-% on the Java implementation of these algorithms.\r
-%\r
-*/\r
-\f\r
-/*\r
- Include declarations.\r
-*/\r
-#include "MagickCore/studio.h"\r
-#include "MagickCore/exception.h"\r
-#include "MagickCore/exception-private.h"\r
-#include "MagickCore/linked-list.h"\r
-#include "MagickCore/locale_.h"\r
-#include "MagickCore/memory_.h"\r
-#include "MagickCore/memory-private.h"\r
-#include "MagickCore/semaphore.h"\r
-#include "MagickCore/signature-private.h"\r
-#include "MagickCore/string_.h"\r
-\f\r
-/*\r
- Typedef declarations.\r
-*/\r
-typedef struct _ElementInfo\r
-{\r
- void\r
- *value;\r
-\r
- struct _ElementInfo\r
- *next;\r
-} ElementInfo;\r
-\r
-struct _LinkedListInfo\r
-{\r
- size_t\r
- capacity,\r
- elements;\r
-\r
- ElementInfo\r
- *head,\r
- *tail,\r
- *next;\r
-\r
- SemaphoreInfo\r
- *semaphore;\r
-\r
- size_t\r
- signature;\r
-};\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% A p p e n d V a l u e T o L i n k e d L i s t %\r
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% AppendValueToLinkedList() appends a value to the end of the linked-list.\r
-%\r
-% The format of the AppendValueToLinkedList method is:\r
-%\r
-% MagickBooleanType AppendValueToLinkedList(LinkedListInfo *list_info,\r
-% const void *value)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked-list info.\r
-%\r
-% o value: the value.\r
-%\r
-*/\r
-MagickExport MagickBooleanType AppendValueToLinkedList(\r
- LinkedListInfo *list_info,const void *value)\r
-{\r
- register ElementInfo\r
- *next;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- if (list_info->elements == list_info->capacity)\r
- return(MagickFalse);\r
- next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));\r
- if (next == (ElementInfo *) NULL)\r
- return(MagickFalse);\r
- next->value=(void *) value;\r
- next->next=(ElementInfo *) NULL;\r
- LockSemaphoreInfo(list_info->semaphore);\r
- if (list_info->next == (ElementInfo *) NULL)\r
- list_info->next=next;\r
- if (list_info->elements == 0)\r
- list_info->head=next;\r
- else\r
- list_info->tail->next=next;\r
- list_info->tail=next;\r
- list_info->elements++;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(MagickTrue);\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% C l e a r L i n k e d L i s t %\r
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% ClearLinkedList() clears all the elements from the linked-list.\r
-%\r
-% The format of the ClearLinkedList method is:\r
-%\r
-% void ClearLinkedList(LinkedListInfo *list_info,\r
-% void *(*relinquish_value)(void *))\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked-list info.\r
-%\r
-% o relinquish_value: the value deallocation method; typically\r
-% RelinquishMagickMemory().\r
-%\r
-*/\r
-MagickExport void ClearLinkedList(LinkedListInfo *list_info,\r
- void *(*relinquish_value)(void *))\r
-{\r
- ElementInfo\r
- *element;\r
-\r
- register ElementInfo\r
- *next;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- LockSemaphoreInfo(list_info->semaphore);\r
- next=list_info->head;\r
- while (next != (ElementInfo *) NULL)\r
- {\r
- if (relinquish_value != (void *(*)(void *)) NULL)\r
- next->value=relinquish_value(next->value);\r
- element=next;\r
- next=next->next;\r
- element=(ElementInfo *) RelinquishMagickMemory(element);\r
- }\r
- list_info->head=(ElementInfo *) NULL;\r
- list_info->tail=(ElementInfo *) NULL;\r
- list_info->next=(ElementInfo *) NULL;\r
- list_info->elements=0;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
-}\r
-\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% D e s t r o y L i n k e d L i s t %\r
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% DestroyLinkedList() frees the linked-list and all associated resources.\r
-%\r
-% The format of the DestroyLinkedList method is:\r
-%\r
-% LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,\r
-% void *(*relinquish_value)(void *))\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked-list info.\r
-%\r
-% o relinquish_value: the value deallocation method; typically\r
-% RelinquishMagickMemory().\r
-%\r
-*/\r
-MagickExport LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,\r
- void *(*relinquish_value)(void *))\r
-{\r
- ElementInfo\r
- *entry;\r
-\r
- register ElementInfo\r
- *next;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- LockSemaphoreInfo(list_info->semaphore);\r
- for (next=list_info->head; next != (ElementInfo *) NULL; )\r
- {\r
- if (relinquish_value != (void *(*)(void *)) NULL)\r
- next->value=relinquish_value(next->value);\r
- entry=next;\r
- next=next->next;\r
- entry=(ElementInfo *) RelinquishMagickMemory(entry);\r
- }\r
- list_info->signature=(~MagickCoreSignature);\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- RelinquishSemaphoreInfo(&list_info->semaphore);\r
- list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);\r
- return(list_info);\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% 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
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% GetLastValueInLinkedList() gets the last value in the linked-list.\r
-%\r
-% The format of the GetLastValueInLinkedList method is:\r
-%\r
-% void *GetLastValueInLinkedList(LinkedListInfo *list_info)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked_list info.\r
-%\r
-*/\r
-MagickExport void *GetLastValueInLinkedList(LinkedListInfo *list_info)\r
-{\r
- void\r
- *value;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- if (list_info->elements == 0)\r
- return((void *) NULL);\r
- LockSemaphoreInfo(list_info->semaphore);\r
- value=list_info->tail->value;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(value);\r
-}\r
-\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% 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
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% GetNextValueInLinkedList() gets the next value in the linked-list.\r
-%\r
-% The format of the GetNextValueInLinkedList method is:\r
-%\r
-% void *GetNextValueInLinkedList(LinkedListInfo *list_info)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked-list info.\r
-%\r
-*/\r
-MagickExport void *GetNextValueInLinkedList(LinkedListInfo *list_info)\r
-{\r
- void\r
- *value;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- LockSemaphoreInfo(list_info->semaphore);\r
- if (list_info->next == (ElementInfo *) NULL)\r
- {\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return((void *) NULL);\r
- }\r
- value=list_info->next->value;\r
- list_info->next=list_info->next->next;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(value);\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% 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
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% GetNumberOfElementsInLinkedList() returns the number of entries in the\r
-% linked-list.\r
-%\r
-% The format of the GetNumberOfElementsInLinkedList method is:\r
-%\r
-% size_t GetNumberOfElementsInLinkedList(\r
-% const LinkedListInfo *list_info)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked-list info.\r
-%\r
-*/\r
-MagickExport size_t GetNumberOfElementsInLinkedList(\r
- const LinkedListInfo *list_info)\r
-{\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- return(list_info->elements);\r
-}\r
-\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% G e t V a l u e F r o m L i n k e d L i s t %\r
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% GetValueFromLinkedList() gets a value from the linked-list at the specified\r
-% location.\r
-%\r
-% The format of the GetValueFromLinkedList method is:\r
-%\r
-% void *GetValueFromLinkedList(LinkedListInfo *list_info,\r
-% const size_t index)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked_list info.\r
-%\r
-% o index: the list index.\r
-%\r
-*/\r
-MagickExport void *GetValueFromLinkedList(LinkedListInfo *list_info,\r
- const size_t index)\r
-{\r
- register ElementInfo\r
- *next;\r
-\r
- register ssize_t\r
- i;\r
-\r
- void\r
- *value;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- if (index >= list_info->elements)\r
- return((void *) NULL);\r
- LockSemaphoreInfo(list_info->semaphore);\r
- if (index == 0)\r
- {\r
- value=list_info->head->value;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(value);\r
- }\r
- if (index == (list_info->elements-1))\r
- {\r
- value=list_info->tail->value;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(value);\r
- }\r
- next=list_info->head;\r
- for (i=0; i < (ssize_t) index; i++)\r
- next=next->next;\r
- value=next->value;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(value);\r
-}\r
-\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% I n s e r t V a l u e I n L i n k e d L i s t %\r
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% InsertValueInLinkedList() inserts an element in the linked-list at the\r
-% specified location.\r
-%\r
-% The format of the InsertValueInLinkedList method is:\r
-%\r
-% MagickBooleanType InsertValueInLinkedList(ListInfo *list_info,\r
-% const size_t index,const void *value)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the hashmap info.\r
-%\r
-% o index: the index.\r
-%\r
-% o value: the value.\r
-%\r
-*/\r
-MagickExport MagickBooleanType InsertValueInLinkedList(\r
- LinkedListInfo *list_info,const size_t index,const void *value)\r
-{\r
- register ElementInfo\r
- *next;\r
-\r
- register ssize_t\r
- i;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- if (value == (const void *) NULL)\r
- return(MagickFalse);\r
- if ((index > list_info->elements) ||\r
- (list_info->elements == list_info->capacity))\r
- return(MagickFalse);\r
- next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));\r
- if (next == (ElementInfo *) NULL)\r
- return(MagickFalse);\r
- next->value=(void *) value;\r
- next->next=(ElementInfo *) NULL;\r
- LockSemaphoreInfo(list_info->semaphore);\r
- if (list_info->elements == 0)\r
- {\r
- if (list_info->next == (ElementInfo *) NULL)\r
- list_info->next=next;\r
- list_info->head=next;\r
- list_info->tail=next;\r
- }\r
- else\r
- {\r
- if (index == 0)\r
- {\r
- if (list_info->next == list_info->head)\r
- list_info->next=next;\r
- next->next=list_info->head;\r
- list_info->head=next;\r
- }\r
- else\r
- if (index == list_info->elements)\r
- {\r
- if (list_info->next == (ElementInfo *) NULL)\r
- list_info->next=next;\r
- list_info->tail->next=next;\r
- list_info->tail=next;\r
- }\r
- else\r
- {\r
- ElementInfo\r
- *element;\r
-\r
- element=list_info->head;\r
- next->next=element->next;\r
- for (i=1; i < (ssize_t) index; i++)\r
- {\r
- element=element->next;\r
- next->next=element->next;\r
- }\r
- next=next->next;\r
- element->next=next;\r
- if (list_info->next == next->next)\r
- list_info->next=next;\r
- }\r
- }\r
- list_info->elements++;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(MagickTrue);\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% 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
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% InsertValueInSortedLinkedList() inserts a value in the sorted linked-list.\r
-%\r
-% The format of the InsertValueInSortedLinkedList method is:\r
-%\r
-% MagickBooleanType InsertValueInSortedLinkedList(ListInfo *list_info,\r
-% int (*compare)(const void *,const void *),void **replace,\r
-% const void *value)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the hashmap info.\r
-%\r
-% o index: the index.\r
-%\r
-% o compare: the compare method.\r
-%\r
-% o replace: return previous element here.\r
-%\r
-% o value: the value.\r
-%\r
-*/\r
-MagickExport MagickBooleanType InsertValueInSortedLinkedList(\r
- LinkedListInfo *list_info,int (*compare)(const void *,const void *),\r
- void **replace,const void *value)\r
-{\r
- ElementInfo\r
- *element;\r
-\r
- register ElementInfo\r
- *next;\r
-\r
- register ssize_t\r
- i;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- if ((compare == (int (*)(const void *,const void *)) NULL) ||\r
- (value == (const void *) NULL))\r
- return(MagickFalse);\r
- if (list_info->elements == list_info->capacity)\r
- return(MagickFalse);\r
- next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));\r
- if (next == (ElementInfo *) NULL)\r
- return(MagickFalse);\r
- next->value=(void *) value;\r
- element=(ElementInfo *) NULL;\r
- LockSemaphoreInfo(list_info->semaphore);\r
- next->next=list_info->head;\r
- while (next->next != (ElementInfo *) NULL)\r
- {\r
- i=(ssize_t) compare(value,next->next->value);\r
- if ((i < 0) || ((replace != (void **) NULL) && (i == 0)))\r
- {\r
- if (i == 0)\r
- {\r
- *replace=next->next->value;\r
- next->next=next->next->next;\r
- if (element != (ElementInfo *) NULL)\r
- element->next=(ElementInfo *) RelinquishMagickMemory(\r
- element->next);\r
- list_info->elements--;\r
- }\r
- if (element != (ElementInfo *) NULL)\r
- element->next=next;\r
- else\r
- list_info->head=next;\r
- break;\r
- }\r
- element=next->next;\r
- next->next=next->next->next;\r
- }\r
- if (next->next == (ElementInfo *) NULL)\r
- {\r
- if (element != (ElementInfo *) NULL)\r
- element->next=next;\r
- else\r
- list_info->head=next;\r
- list_info->tail=next;\r
- }\r
- list_info->elements++;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(MagickTrue);\r
-}\r
-\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% I s L i n k e d L i s t E m p t y %\r
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% IsLinkedListEmpty() returns MagickTrue if the linked-list is empty.\r
-%\r
-% The format of the IsLinkedListEmpty method is:\r
-%\r
-% MagickBooleanType IsLinkedListEmpty(LinkedListInfo *list_info)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked-list info.\r
-%\r
-*/\r
-MagickExport MagickBooleanType IsLinkedListEmpty(\r
- const LinkedListInfo *list_info)\r
-{\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- return(list_info->elements == 0 ? MagickTrue : MagickFalse);\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% L i n k e d L i s t T o A r r a y %\r
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% LinkedListToArray() converts the linked-list to an array.\r
-%\r
-% The format of the LinkedListToArray method is:\r
-%\r
-% MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,\r
-% void **array)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked-list info.\r
-%\r
-% o array: the array.\r
-%\r
-*/\r
-MagickExport MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,\r
- void **array)\r
-{\r
- register ElementInfo\r
- *next;\r
-\r
- register ssize_t\r
- i;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- if (array == (void **) NULL)\r
- return(MagickFalse);\r
- LockSemaphoreInfo(list_info->semaphore);\r
- next=list_info->head;\r
- for (i=0; next != (ElementInfo *) NULL; i++)\r
- {\r
- array[i]=next->value;\r
- next=next->next;\r
- }\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(MagickTrue);\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% N e w L i n k e d L i s t I n f o %\r
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% NewLinkedList() returns a pointer to a LinkedListInfo structure\r
-% initialized to default values.\r
-%\r
-% The format of the NewLinkedList method is:\r
-%\r
-% LinkedListInfo *NewLinkedList(const size_t capacity)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o capacity: the maximum number of elements in the list.\r
-%\r
-*/\r
-MagickExport LinkedListInfo *NewLinkedList(const size_t capacity)\r
-{\r
- LinkedListInfo\r
- *list_info;\r
-\r
- list_info=(LinkedListInfo *) AcquireCriticalMemory(sizeof(*list_info));\r
- (void) memset(list_info,0,sizeof(*list_info));\r
- list_info->capacity=capacity == 0 ? (size_t) (~0) : capacity;\r
- list_info->elements=0;\r
- list_info->head=(ElementInfo *) NULL;\r
- list_info->tail=(ElementInfo *) NULL;\r
- list_info->next=(ElementInfo *) NULL;\r
- list_info->semaphore=AcquireSemaphoreInfo();\r
- list_info->signature=MagickCoreSignature;\r
- return(list_info);\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% 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
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% RemoveElementByValueFromLinkedList() removes an element from the linked-list\r
-% by value.\r
-%\r
-% The format of the RemoveElementByValueFromLinkedList method is:\r
-%\r
-% void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,\r
-% const void *value)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the list info.\r
-%\r
-% o value: the value.\r
-%\r
-*/\r
-MagickExport void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,\r
- const void *value)\r
-{\r
- ElementInfo\r
- *next;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- if ((list_info->elements == 0) || (value == (const void *) NULL))\r
- return((void *) NULL);\r
- LockSemaphoreInfo(list_info->semaphore);\r
- if (value == list_info->head->value)\r
- {\r
- if (list_info->next == list_info->head)\r
- list_info->next=list_info->head->next;\r
- next=list_info->head;\r
- list_info->head=list_info->head->next;\r
- next=(ElementInfo *) RelinquishMagickMemory(next);\r
- }\r
- else\r
- {\r
- ElementInfo\r
- *element;\r
-\r
- next=list_info->head;\r
- while ((next->next != (ElementInfo *) NULL) &&\r
- (next->next->value != value))\r
- next=next->next;\r
- if (next->next == (ElementInfo *) NULL)\r
- {\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return((void *) NULL);\r
- }\r
- element=next->next;\r
- next->next=element->next;\r
- if (element == list_info->tail)\r
- list_info->tail=next;\r
- if (list_info->next == element)\r
- list_info->next=element->next;\r
- element=(ElementInfo *) RelinquishMagickMemory(element);\r
- }\r
- list_info->elements--;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return((void *) value);\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% 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
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% RemoveElementFromLinkedList() removes an element from the linked-list at the\r
-% specified location.\r
-%\r
-% The format of the RemoveElementFromLinkedList method is:\r
-%\r
-% void *RemoveElementFromLinkedList(LinkedListInfo *list_info,\r
-% const size_t index)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked-list info.\r
-%\r
-% o index: the index.\r
-%\r
-*/\r
-MagickExport void *RemoveElementFromLinkedList(LinkedListInfo *list_info,\r
- const size_t index)\r
-{\r
- ElementInfo\r
- *next;\r
-\r
- register ssize_t\r
- i;\r
-\r
- void\r
- *value;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- if (index >= list_info->elements)\r
- return((void *) NULL);\r
- LockSemaphoreInfo(list_info->semaphore);\r
- if (index == 0)\r
- {\r
- if (list_info->next == list_info->head)\r
- list_info->next=list_info->head->next;\r
- value=list_info->head->value;\r
- next=list_info->head;\r
- list_info->head=list_info->head->next;\r
- next=(ElementInfo *) RelinquishMagickMemory(next);\r
- }\r
- else\r
- {\r
- ElementInfo\r
- *element;\r
-\r
- next=list_info->head;\r
- for (i=1; i < (ssize_t) index; i++)\r
- next=next->next;\r
- element=next->next;\r
- next->next=element->next;\r
- if (element == list_info->tail)\r
- list_info->tail=next;\r
- if (list_info->next == element)\r
- list_info->next=element->next;\r
- value=element->value;\r
- element=(ElementInfo *) RelinquishMagickMemory(element);\r
- }\r
- list_info->elements--;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(value);\r
-}\r
-\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% 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
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% RemoveLastElementFromLinkedList() removes the last element from the\r
-% linked-list.\r
-%\r
-% The format of the RemoveLastElementFromLinkedList method is:\r
-%\r
-% void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked-list info.\r
-%\r
-*/\r
-MagickExport void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)\r
-{\r
- void\r
- *value;\r
-\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- if (list_info->elements == 0)\r
- return((void *) NULL);\r
- LockSemaphoreInfo(list_info->semaphore);\r
- if (list_info->next == list_info->tail)\r
- list_info->next=(ElementInfo *) NULL;\r
- if (list_info->elements == 1UL)\r
- {\r
- value=list_info->head->value;\r
- list_info->head=(ElementInfo *) NULL;\r
- list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);\r
- }\r
- else\r
- {\r
- ElementInfo\r
- *next;\r
-\r
- value=list_info->tail->value;\r
- next=list_info->head;\r
- while (next->next != list_info->tail)\r
- next=next->next;\r
- list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);\r
- list_info->tail=next;\r
- next->next=(ElementInfo *) NULL;\r
- }\r
- list_info->elements--;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
- return(value);\r
-}\r
-\f\r
-/*\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-% %\r
-% %\r
-% %\r
-% R e s e t L i n k e d L i s t I t e r a t o r %\r
-% %\r
-% %\r
-% %\r
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r
-%\r
-% ResetLinkedListIterator() resets the lined-list iterator. Use it in\r
-% conjunction with GetNextValueInLinkedList() to iterate over all the values\r
-% in the linked-list.\r
-%\r
-% The format of the ResetLinkedListIterator method is:\r
-%\r
-% ResetLinkedListIterator(LinkedListInfo *list_info)\r
-%\r
-% A description of each parameter follows:\r
-%\r
-% o list_info: the linked-list info.\r
-%\r
-*/\r
-MagickExport void ResetLinkedListIterator(LinkedListInfo *list_info)\r
-{\r
- assert(list_info != (LinkedListInfo *) NULL);\r
- assert(list_info->signature == MagickCoreSignature);\r
- LockSemaphoreInfo(list_info->semaphore);\r
- list_info->next=list_info->head;\r
- UnlockSemaphoreInfo(list_info->semaphore);\r
-}\r
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% L IIIII N N K K EEEEE DDDD L IIIII SSSSS TTTTT %
+% L I NN N K K E D D L I SS T %
+% L I N N N KKK EEE D D = L I SSS T %
+% L I N NN K K E D D L I SS T %
+% LLLLL IIIII N N K K EEEEE DDDD LLLLL IIIII SSSSS T %
+% %
+% %
+% MagickCore Linked-list Methods %
+% %
+% Software Design %
+% Cristy %
+% December 2002 %
+% %
+% %
+% Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
+% dedicated to making software imaging solutions freely available. %
+% %
+% You may not use this file except in compliance with the License. You may %
+% obtain a copy of the License at %
+% %
+% https://imagemagick.org/script/license.php %
+% %
+% Unless required by applicable law or agreed to in writing, software %
+% distributed under the License is distributed on an "AS IS" BASIS, %
+% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
+% See the License for the specific language governing permissions and %
+% limitations under the License. %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% This module implements the standard handy hash and linked-list methods for
+% storing and retrieving large numbers of data elements. It is loosely based
+% on the Java implementation of these algorithms.
+%
+*/
+\f
+/*
+ Include declarations.
+*/
+#include "MagickCore/studio.h"
+#include "MagickCore/exception.h"
+#include "MagickCore/exception-private.h"
+#include "MagickCore/linked-list.h"
+#include "MagickCore/locale_.h"
+#include "MagickCore/memory_.h"
+#include "MagickCore/memory-private.h"
+#include "MagickCore/semaphore.h"
+#include "MagickCore/signature-private.h"
+#include "MagickCore/string_.h"
+\f
+/*
+ Typedef declarations.
+*/
+typedef struct _ElementInfo
+{
+ void
+ *value;
+
+ struct _ElementInfo
+ *next;
+} ElementInfo;
+
+struct _LinkedListInfo
+{
+ size_t
+ capacity,
+ elements;
+
+ ElementInfo
+ *head,
+ *tail,
+ *next;
+
+ SemaphoreInfo
+ *semaphore;
+
+ size_t
+ signature;
+};
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% A p p e n d V a l u e T o L i n k e d L i s t %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% AppendValueToLinkedList() appends a value to the end of the linked-list.
+%
+% The format of the AppendValueToLinkedList method is:
+%
+% MagickBooleanType AppendValueToLinkedList(LinkedListInfo *list_info,
+% const void *value)
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked-list info.
+%
+% o value: the value.
+%
+*/
+MagickExport MagickBooleanType AppendValueToLinkedList(
+ LinkedListInfo *list_info,const void *value)
+{
+ register ElementInfo
+ *next;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ if (list_info->elements == list_info->capacity)
+ return(MagickFalse);
+ next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
+ if (next == (ElementInfo *) NULL)
+ return(MagickFalse);
+ next->value=(void *) value;
+ next->next=(ElementInfo *) NULL;
+ LockSemaphoreInfo(list_info->semaphore);
+ if (list_info->next == (ElementInfo *) NULL)
+ list_info->next=next;
+ if (list_info->elements == 0)
+ list_info->head=next;
+ else
+ list_info->tail->next=next;
+ list_info->tail=next;
+ list_info->elements++;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(MagickTrue);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% C l e a r L i n k e d L i s t %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ClearLinkedList() clears all the elements from the linked-list.
+%
+% The format of the ClearLinkedList method is:
+%
+% void ClearLinkedList(LinkedListInfo *list_info,
+% void *(*relinquish_value)(void *))
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked-list info.
+%
+% o relinquish_value: the value deallocation method; typically
+% RelinquishMagickMemory().
+%
+*/
+MagickExport void ClearLinkedList(LinkedListInfo *list_info,
+ void *(*relinquish_value)(void *))
+{
+ ElementInfo
+ *element;
+
+ register ElementInfo
+ *next;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ LockSemaphoreInfo(list_info->semaphore);
+ next=list_info->head;
+ while (next != (ElementInfo *) NULL)
+ {
+ if (relinquish_value != (void *(*)(void *)) NULL)
+ next->value=relinquish_value(next->value);
+ element=next;
+ next=next->next;
+ element=(ElementInfo *) RelinquishMagickMemory(element);
+ }
+ list_info->head=(ElementInfo *) NULL;
+ list_info->tail=(ElementInfo *) NULL;
+ list_info->next=(ElementInfo *) NULL;
+ list_info->elements=0;
+ UnlockSemaphoreInfo(list_info->semaphore);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% D e s t r o y L i n k e d L i s t %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% DestroyLinkedList() frees the linked-list and all associated resources.
+%
+% The format of the DestroyLinkedList method is:
+%
+% LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
+% void *(*relinquish_value)(void *))
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked-list info.
+%
+% o relinquish_value: the value deallocation method; typically
+% RelinquishMagickMemory().
+%
+*/
+MagickExport LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
+ void *(*relinquish_value)(void *))
+{
+ ElementInfo
+ *entry;
+
+ register ElementInfo
+ *next;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ LockSemaphoreInfo(list_info->semaphore);
+ for (next=list_info->head; next != (ElementInfo *) NULL; )
+ {
+ if (relinquish_value != (void *(*)(void *)) NULL)
+ next->value=relinquish_value(next->value);
+ entry=next;
+ next=next->next;
+ entry=(ElementInfo *) RelinquishMagickMemory(entry);
+ }
+ list_info->signature=(~MagickCoreSignature);
+ UnlockSemaphoreInfo(list_info->semaphore);
+ RelinquishSemaphoreInfo(&list_info->semaphore);
+ list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
+ return(list_info);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% G e t L a s t V a l u e I n L i n k e d L i s t %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% GetLastValueInLinkedList() gets the last value in the linked-list.
+%
+% The format of the GetLastValueInLinkedList method is:
+%
+% void *GetLastValueInLinkedList(LinkedListInfo *list_info)
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked_list info.
+%
+*/
+MagickExport void *GetLastValueInLinkedList(LinkedListInfo *list_info)
+{
+ void
+ *value;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ if (list_info->elements == 0)
+ return((void *) NULL);
+ LockSemaphoreInfo(list_info->semaphore);
+ value=list_info->tail->value;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(value);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% G e t N e x t V a l u e I n L i n k e d L i s t %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% GetNextValueInLinkedList() gets the next value in the linked-list.
+%
+% The format of the GetNextValueInLinkedList method is:
+%
+% void *GetNextValueInLinkedList(LinkedListInfo *list_info)
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked-list info.
+%
+*/
+MagickExport void *GetNextValueInLinkedList(LinkedListInfo *list_info)
+{
+ void
+ *value;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ LockSemaphoreInfo(list_info->semaphore);
+ if (list_info->next == (ElementInfo *) NULL)
+ {
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return((void *) NULL);
+ }
+ value=list_info->next->value;
+ list_info->next=list_info->next->next;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(value);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% 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 %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% GetNumberOfElementsInLinkedList() returns the number of entries in the
+% linked-list.
+%
+% The format of the GetNumberOfElementsInLinkedList method is:
+%
+% size_t GetNumberOfElementsInLinkedList(
+% const LinkedListInfo *list_info)
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked-list info.
+%
+*/
+MagickExport size_t GetNumberOfElementsInLinkedList(
+ const LinkedListInfo *list_info)
+{
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ return(list_info->elements);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% G e t V a l u e F r o m L i n k e d L i s t %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% GetValueFromLinkedList() gets a value from the linked-list at the specified
+% location.
+%
+% The format of the GetValueFromLinkedList method is:
+%
+% void *GetValueFromLinkedList(LinkedListInfo *list_info,
+% const size_t index)
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked_list info.
+%
+% o index: the list index.
+%
+*/
+MagickExport void *GetValueFromLinkedList(LinkedListInfo *list_info,
+ const size_t index)
+{
+ register ElementInfo
+ *next;
+
+ register ssize_t
+ i;
+
+ void
+ *value;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ if (index >= list_info->elements)
+ return((void *) NULL);
+ LockSemaphoreInfo(list_info->semaphore);
+ if (index == 0)
+ {
+ value=list_info->head->value;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(value);
+ }
+ if (index == (list_info->elements-1))
+ {
+ value=list_info->tail->value;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(value);
+ }
+ next=list_info->head;
+ for (i=0; i < (ssize_t) index; i++)
+ next=next->next;
+ value=next->value;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(value);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% I n s e r t V a l u e I n L i n k e d L i s t %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% InsertValueInLinkedList() inserts an element in the linked-list at the
+% specified location.
+%
+% The format of the InsertValueInLinkedList method is:
+%
+% MagickBooleanType InsertValueInLinkedList(ListInfo *list_info,
+% const size_t index,const void *value)
+%
+% A description of each parameter follows:
+%
+% o list_info: the hashmap info.
+%
+% o index: the index.
+%
+% o value: the value.
+%
+*/
+MagickExport MagickBooleanType InsertValueInLinkedList(
+ LinkedListInfo *list_info,const size_t index,const void *value)
+{
+ register ElementInfo
+ *next;
+
+ register ssize_t
+ i;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ if (value == (const void *) NULL)
+ return(MagickFalse);
+ if ((index > list_info->elements) ||
+ (list_info->elements == list_info->capacity))
+ return(MagickFalse);
+ next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
+ if (next == (ElementInfo *) NULL)
+ return(MagickFalse);
+ next->value=(void *) value;
+ next->next=(ElementInfo *) NULL;
+ LockSemaphoreInfo(list_info->semaphore);
+ if (list_info->elements == 0)
+ {
+ if (list_info->next == (ElementInfo *) NULL)
+ list_info->next=next;
+ list_info->head=next;
+ list_info->tail=next;
+ }
+ else
+ {
+ if (index == 0)
+ {
+ if (list_info->next == list_info->head)
+ list_info->next=next;
+ next->next=list_info->head;
+ list_info->head=next;
+ }
+ else
+ if (index == list_info->elements)
+ {
+ if (list_info->next == (ElementInfo *) NULL)
+ list_info->next=next;
+ list_info->tail->next=next;
+ list_info->tail=next;
+ }
+ else
+ {
+ ElementInfo
+ *element;
+
+ element=list_info->head;
+ next->next=element->next;
+ for (i=1; i < (ssize_t) index; i++)
+ {
+ element=element->next;
+ next->next=element->next;
+ }
+ next=next->next;
+ element->next=next;
+ if (list_info->next == next->next)
+ list_info->next=next;
+ }
+ }
+ list_info->elements++;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(MagickTrue);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% 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 %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% InsertValueInSortedLinkedList() inserts a value in the sorted linked-list.
+%
+% The format of the InsertValueInSortedLinkedList method is:
+%
+% MagickBooleanType InsertValueInSortedLinkedList(ListInfo *list_info,
+% int (*compare)(const void *,const void *),void **replace,
+% const void *value)
+%
+% A description of each parameter follows:
+%
+% o list_info: the hashmap info.
+%
+% o index: the index.
+%
+% o compare: the compare method.
+%
+% o replace: return previous element here.
+%
+% o value: the value.
+%
+*/
+MagickExport MagickBooleanType InsertValueInSortedLinkedList(
+ LinkedListInfo *list_info,int (*compare)(const void *,const void *),
+ void **replace,const void *value)
+{
+ ElementInfo
+ *element;
+
+ register ElementInfo
+ *next;
+
+ register ssize_t
+ i;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ if ((compare == (int (*)(const void *,const void *)) NULL) ||
+ (value == (const void *) NULL))
+ return(MagickFalse);
+ if (list_info->elements == list_info->capacity)
+ return(MagickFalse);
+ next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
+ if (next == (ElementInfo *) NULL)
+ return(MagickFalse);
+ next->value=(void *) value;
+ element=(ElementInfo *) NULL;
+ LockSemaphoreInfo(list_info->semaphore);
+ next->next=list_info->head;
+ while (next->next != (ElementInfo *) NULL)
+ {
+ i=(ssize_t) compare(value,next->next->value);
+ if ((i < 0) || ((replace != (void **) NULL) && (i == 0)))
+ {
+ if (i == 0)
+ {
+ *replace=next->next->value;
+ next->next=next->next->next;
+ if (element != (ElementInfo *) NULL)
+ element->next=(ElementInfo *) RelinquishMagickMemory(
+ element->next);
+ list_info->elements--;
+ }
+ if (element != (ElementInfo *) NULL)
+ element->next=next;
+ else
+ list_info->head=next;
+ break;
+ }
+ element=next->next;
+ next->next=next->next->next;
+ }
+ if (next->next == (ElementInfo *) NULL)
+ {
+ if (element != (ElementInfo *) NULL)
+ element->next=next;
+ else
+ list_info->head=next;
+ list_info->tail=next;
+ }
+ list_info->elements++;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(MagickTrue);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% I s L i n k e d L i s t E m p t y %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% IsLinkedListEmpty() returns MagickTrue if the linked-list is empty.
+%
+% The format of the IsLinkedListEmpty method is:
+%
+% MagickBooleanType IsLinkedListEmpty(LinkedListInfo *list_info)
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked-list info.
+%
+*/
+MagickExport MagickBooleanType IsLinkedListEmpty(
+ const LinkedListInfo *list_info)
+{
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ return(list_info->elements == 0 ? MagickTrue : MagickFalse);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% L i n k e d L i s t T o A r r a y %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% LinkedListToArray() converts the linked-list to an array.
+%
+% The format of the LinkedListToArray method is:
+%
+% MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
+% void **array)
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked-list info.
+%
+% o array: the array.
+%
+*/
+MagickExport MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
+ void **array)
+{
+ register ElementInfo
+ *next;
+
+ register ssize_t
+ i;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ if (array == (void **) NULL)
+ return(MagickFalse);
+ LockSemaphoreInfo(list_info->semaphore);
+ next=list_info->head;
+ for (i=0; next != (ElementInfo *) NULL; i++)
+ {
+ array[i]=next->value;
+ next=next->next;
+ }
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(MagickTrue);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% N e w L i n k e d L i s t I n f o %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% NewLinkedList() returns a pointer to a LinkedListInfo structure
+% initialized to default values.
+%
+% The format of the NewLinkedList method is:
+%
+% LinkedListInfo *NewLinkedList(const size_t capacity)
+%
+% A description of each parameter follows:
+%
+% o capacity: the maximum number of elements in the list.
+%
+*/
+MagickExport LinkedListInfo *NewLinkedList(const size_t capacity)
+{
+ LinkedListInfo
+ *list_info;
+
+ list_info=(LinkedListInfo *) AcquireCriticalMemory(sizeof(*list_info));
+ (void) memset(list_info,0,sizeof(*list_info));
+ list_info->capacity=capacity == 0 ? (size_t) (~0) : capacity;
+ list_info->elements=0;
+ list_info->head=(ElementInfo *) NULL;
+ list_info->tail=(ElementInfo *) NULL;
+ list_info->next=(ElementInfo *) NULL;
+ list_info->semaphore=AcquireSemaphoreInfo();
+ list_info->signature=MagickCoreSignature;
+ return(list_info);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% 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 %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% RemoveElementByValueFromLinkedList() removes an element from the linked-list
+% by value.
+%
+% The format of the RemoveElementByValueFromLinkedList method is:
+%
+% void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
+% const void *value)
+%
+% A description of each parameter follows:
+%
+% o list_info: the list info.
+%
+% o value: the value.
+%
+*/
+MagickExport void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
+ const void *value)
+{
+ ElementInfo
+ *next;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ if ((list_info->elements == 0) || (value == (const void *) NULL))
+ return((void *) NULL);
+ LockSemaphoreInfo(list_info->semaphore);
+ if (value == list_info->head->value)
+ {
+ if (list_info->next == list_info->head)
+ list_info->next=list_info->head->next;
+ next=list_info->head;
+ list_info->head=list_info->head->next;
+ next=(ElementInfo *) RelinquishMagickMemory(next);
+ }
+ else
+ {
+ ElementInfo
+ *element;
+
+ next=list_info->head;
+ while ((next->next != (ElementInfo *) NULL) &&
+ (next->next->value != value))
+ next=next->next;
+ if (next->next == (ElementInfo *) NULL)
+ {
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return((void *) NULL);
+ }
+ element=next->next;
+ next->next=element->next;
+ if (element == list_info->tail)
+ list_info->tail=next;
+ if (list_info->next == element)
+ list_info->next=element->next;
+ element=(ElementInfo *) RelinquishMagickMemory(element);
+ }
+ list_info->elements--;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return((void *) value);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% 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 %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% RemoveElementFromLinkedList() removes an element from the linked-list at the
+% specified location.
+%
+% The format of the RemoveElementFromLinkedList method is:
+%
+% void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
+% const size_t index)
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked-list info.
+%
+% o index: the index.
+%
+*/
+MagickExport void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
+ const size_t index)
+{
+ ElementInfo
+ *next;
+
+ register ssize_t
+ i;
+
+ void
+ *value;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ if (index >= list_info->elements)
+ return((void *) NULL);
+ LockSemaphoreInfo(list_info->semaphore);
+ if (index == 0)
+ {
+ if (list_info->next == list_info->head)
+ list_info->next=list_info->head->next;
+ value=list_info->head->value;
+ next=list_info->head;
+ list_info->head=list_info->head->next;
+ next=(ElementInfo *) RelinquishMagickMemory(next);
+ }
+ else
+ {
+ ElementInfo
+ *element;
+
+ next=list_info->head;
+ for (i=1; i < (ssize_t) index; i++)
+ next=next->next;
+ element=next->next;
+ next->next=element->next;
+ if (element == list_info->tail)
+ list_info->tail=next;
+ if (list_info->next == element)
+ list_info->next=element->next;
+ value=element->value;
+ element=(ElementInfo *) RelinquishMagickMemory(element);
+ }
+ list_info->elements--;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(value);
+}
+
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% 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 %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% RemoveLastElementFromLinkedList() removes the last element from the
+% linked-list.
+%
+% The format of the RemoveLastElementFromLinkedList method is:
+%
+% void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked-list info.
+%
+*/
+MagickExport void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
+{
+ void
+ *value;
+
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ if (list_info->elements == 0)
+ return((void *) NULL);
+ LockSemaphoreInfo(list_info->semaphore);
+ if (list_info->next == list_info->tail)
+ list_info->next=(ElementInfo *) NULL;
+ if (list_info->elements == 1UL)
+ {
+ value=list_info->head->value;
+ list_info->head=(ElementInfo *) NULL;
+ list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
+ }
+ else
+ {
+ ElementInfo
+ *next;
+
+ value=list_info->tail->value;
+ next=list_info->head;
+ while (next->next != list_info->tail)
+ next=next->next;
+ list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
+ list_info->tail=next;
+ next->next=(ElementInfo *) NULL;
+ }
+ list_info->elements--;
+ UnlockSemaphoreInfo(list_info->semaphore);
+ return(value);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% R e s e t L i n k e d L i s t I t e r a t o r %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% ResetLinkedListIterator() resets the lined-list iterator. Use it in
+% conjunction with GetNextValueInLinkedList() to iterate over all the values
+% in the linked-list.
+%
+% The format of the ResetLinkedListIterator method is:
+%
+% ResetLinkedListIterator(LinkedListInfo *list_info)
+%
+% A description of each parameter follows:
+%
+% o list_info: the linked-list info.
+%
+*/
+MagickExport void ResetLinkedListIterator(LinkedListInfo *list_info)
+{
+ assert(list_info != (LinkedListInfo *) NULL);
+ assert(list_info->signature == MagickCoreSignature);
+ LockSemaphoreInfo(list_info->semaphore);
+ list_info->next=list_info->head;
+ UnlockSemaphoreInfo(list_info->semaphore);
+}