45#include "magick/studio.h"
46#include "magick/exception.h"
47#include "magick/exception-private.h"
48#include "magick/hashmap.h"
49#include "magick/hashmap-private.h"
50#include "magick/locale_.h"
51#include "magick/memory_.h"
52#include "magick/semaphore.h"
53#include "magick/signature-private.h"
54#include "magick/string_.h"
90 (*hash)(
const void *);
93 (*compare)(
const void *,
const void *);
96 *(*relinquish_key)(
void *),
97 *(*relinquish_value)(
void *);
142MagickExport MagickBooleanType AppendValueToLinkedList(
149 assert(list_info->signature == MagickCoreSignature);
150 if (list_info->elements == list_info->capacity)
152 next=(
ElementInfo *) AcquireMagickMemory(
sizeof(*next));
155 next->value=(
void *) value;
157 LockSemaphoreInfo(list_info->semaphore);
159 list_info->next=next;
160 if (list_info->elements == 0)
161 list_info->head=next;
163 list_info->tail->next=next;
164 list_info->tail=next;
165 list_info->elements++;
166 UnlockSemaphoreInfo(list_info->semaphore);
197 void *(*relinquish_value)(
void *))
206 assert(list_info->signature == MagickCoreSignature);
207 LockSemaphoreInfo(list_info->semaphore);
208 next=list_info->head;
211 if (relinquish_value != (
void *(*)(
void *)) NULL)
212 next->value=relinquish_value(next->value);
215 element=(
ElementInfo *) RelinquishMagickMemory(element);
220 list_info->elements=0;
221 UnlockSemaphoreInfo(list_info->semaphore);
250MagickExport MagickBooleanType CompareHashmapString(
const void *target,
257 p=(
const char *) target;
258 q=(
const char *) source;
259 return(LocaleCompare(p,q) == 0 ? MagickTrue : MagickFalse);
288MagickExport MagickBooleanType CompareHashmapStringInfo(
const void *target,
297 return(CompareStringInfo(p,q) == 0 ? MagickTrue : MagickFalse);
334 assert(hashmap_info->signature == MagickCoreSignature);
335 LockSemaphoreInfo(hashmap_info->semaphore);
336 for (i=0; i < (ssize_t) hashmap_info->capacity; i++)
338 list_info=hashmap_info->map[i];
341 list_info->next=list_info->head;
342 entry=(
EntryInfo *) GetNextValueInLinkedList(list_info);
345 if (hashmap_info->relinquish_key != (
void *(*)(
void *)) NULL)
346 entry->key=hashmap_info->relinquish_key(entry->key);
347 if (hashmap_info->relinquish_value != (
void *(*)(
void *)) NULL)
348 entry->value=hashmap_info->relinquish_value(entry->value);
349 entry=(
EntryInfo *) GetNextValueInLinkedList(list_info);
353 list_info=DestroyLinkedList(list_info,RelinquishMagickMemory);
357 hashmap_info->signature=(~MagickCoreSignature);
358 UnlockSemaphoreInfo(hashmap_info->semaphore);
359 DestroySemaphoreInfo(&hashmap_info->semaphore);
360 hashmap_info=(
HashmapInfo *) RelinquishMagickMemory(hashmap_info);
361 return(hashmap_info);
391 void *(*relinquish_value)(
void *))
400 assert(list_info->signature == MagickCoreSignature);
401 LockSemaphoreInfo(list_info->semaphore);
402 for (next=list_info->head; next != (
ElementInfo *) NULL; )
404 if (relinquish_value != (
void *(*)(
void *)) NULL)
405 next->value=relinquish_value(next->value);
408 entry=(
ElementInfo *) RelinquishMagickMemory(entry);
410 list_info->signature=(~MagickCoreSignature);
411 UnlockSemaphoreInfo(list_info->semaphore);
412 DestroySemaphoreInfo(&list_info->semaphore);
439MagickPrivate
ElementInfo *GetHeadElementInLinkedList(
443 assert(list_info->signature == MagickCoreSignature);
444 return(list_info->head);
469MagickExport
void *GetLastValueInLinkedList(
LinkedListInfo *list_info)
475 assert(list_info->signature == MagickCoreSignature);
476 if (list_info->elements == 0)
477 return((
void *) NULL);
478 LockSemaphoreInfo(list_info->semaphore);
479 value=list_info->tail->value;
480 UnlockSemaphoreInfo(list_info->semaphore);
506MagickExport
void *GetNextKeyInHashmap(
HashmapInfo *hashmap_info)
518 assert(hashmap_info->signature == MagickCoreSignature);
519 LockSemaphoreInfo(hashmap_info->semaphore);
520 while (hashmap_info->next < hashmap_info->capacity)
522 list_info=hashmap_info->map[hashmap_info->next];
525 if (hashmap_info->head_of_list == MagickFalse)
527 list_info->next=list_info->head;
528 hashmap_info->head_of_list=MagickTrue;
530 entry=(
EntryInfo *) GetNextValueInLinkedList(list_info);
534 UnlockSemaphoreInfo(hashmap_info->semaphore);
537 hashmap_info->head_of_list=MagickFalse;
539 hashmap_info->next++;
541 UnlockSemaphoreInfo(hashmap_info->semaphore);
542 return((
void *) NULL);
567MagickExport
void *GetNextValueInHashmap(
HashmapInfo *hashmap_info)
579 assert(hashmap_info->signature == MagickCoreSignature);
580 LockSemaphoreInfo(hashmap_info->semaphore);
581 while (hashmap_info->next < hashmap_info->capacity)
583 list_info=hashmap_info->map[hashmap_info->next];
586 if (hashmap_info->head_of_list == MagickFalse)
588 list_info->next=list_info->head;
589 hashmap_info->head_of_list=MagickTrue;
591 entry=(
EntryInfo *) GetNextValueInLinkedList(list_info);
595 UnlockSemaphoreInfo(hashmap_info->semaphore);
598 hashmap_info->head_of_list=MagickFalse;
600 hashmap_info->next++;
602 UnlockSemaphoreInfo(hashmap_info->semaphore);
603 return((
void *) NULL);
628MagickExport
void *GetNextValueInLinkedList(
LinkedListInfo *list_info)
634 assert(list_info->signature == MagickCoreSignature);
635 LockSemaphoreInfo(list_info->semaphore);
638 UnlockSemaphoreInfo(list_info->semaphore);
639 return((
void *) NULL);
641 value=list_info->next->value;
642 list_info->next=list_info->next->next;
643 UnlockSemaphoreInfo(list_info->semaphore);
669MagickExport
size_t GetNumberOfEntriesInHashmap(
673 assert(hashmap_info->signature == MagickCoreSignature);
674 return(hashmap_info->entries);
701MagickExport
size_t GetNumberOfElementsInLinkedList(
705 assert(list_info->signature == MagickCoreSignature);
706 return(list_info->elements);
733MagickExport
void *GetValueFromHashmap(
HashmapInfo *hashmap_info,
749 assert(hashmap_info->signature == MagickCoreSignature);
750 if (key == (
const void *) NULL)
751 return((
void *) NULL);
752 LockSemaphoreInfo(hashmap_info->semaphore);
753 hash=hashmap_info->hash(key);
754 list_info=hashmap_info->map[hash % hashmap_info->capacity];
757 list_info->next=list_info->head;
758 entry=(
EntryInfo *) GetNextValueInLinkedList(list_info);
761 if (entry->hash == hash)
767 if (hashmap_info->compare !=
768 (MagickBooleanType (*)(
const void *,
const void *)) NULL)
769 compare=hashmap_info->compare(key,entry->key);
770 if (compare != MagickFalse)
773 UnlockSemaphoreInfo(hashmap_info->semaphore);
777 entry=(
EntryInfo *) GetNextValueInLinkedList(list_info);
780 UnlockSemaphoreInfo(hashmap_info->semaphore);
781 return((
void *) NULL);
810MagickExport
void *GetValueFromLinkedList(
LinkedListInfo *list_info,
823 assert(list_info->signature == MagickCoreSignature);
824 if (index >= list_info->elements)
825 return((
void *) NULL);
826 LockSemaphoreInfo(list_info->semaphore);
829 value=list_info->head->value;
830 UnlockSemaphoreInfo(list_info->semaphore);
833 if (index == (list_info->elements-1))
835 value=list_info->tail->value;
836 UnlockSemaphoreInfo(list_info->semaphore);
839 next=list_info->head;
840 for (i=0; i < (ssize_t) index; i++)
843 UnlockSemaphoreInfo(list_info->semaphore);
870MagickExport
size_t HashPointerType(
const void *pointer)
875 hash=(size_t) pointer;
876 hash+=(~(hash << 9));
906MagickExport
size_t HashStringType(
const void *
string)
923 signature_info=AcquireSignatureInfo();
924 signature=StringToStringInfo((
const char *)
string);
925 UpdateSignature(signature_info,signature);
926 FinalizeSignature(signature_info);
927 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
929 for (i=0; i < 8; i++)
931 signature=DestroyStringInfo(signature);
932 signature_info=DestroySignatureInfo(signature_info);
959MagickExport
size_t HashStringInfoType(
const void *string_info)
973 signature_info=AcquireSignatureInfo();
974 UpdateSignature(signature_info,(
const StringInfo *) string_info);
975 FinalizeSignature(signature_info);
976 digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
978 for (i=0; i < 8; i++)
980 signature_info=DestroySignatureInfo(signature_info);
1012MagickExport MagickBooleanType InsertValueInLinkedList(
1022 assert(list_info->signature == MagickCoreSignature);
1023 if (value == (
const void *) NULL)
1024 return(MagickFalse);
1025 if ((index > list_info->elements) ||
1026 (list_info->elements == list_info->capacity))
1027 return(MagickFalse);
1028 next=(
ElementInfo *) AcquireMagickMemory(
sizeof(*next));
1030 return(MagickFalse);
1031 next->value=(
void *) value;
1033 LockSemaphoreInfo(list_info->semaphore);
1034 if (list_info->elements == 0)
1037 list_info->next=next;
1038 list_info->head=next;
1039 list_info->tail=next;
1045 if (list_info->next == list_info->head)
1046 list_info->next=next;
1047 next->next=list_info->head;
1048 list_info->head=next;
1051 if (index == list_info->elements)
1054 list_info->next=next;
1055 list_info->tail->next=next;
1056 list_info->tail=next;
1063 element=list_info->head;
1064 next->next=element->next;
1065 for (i=1; i < (ssize_t) index; i++)
1067 element=element->next;
1068 next->next=element->next;
1072 if (list_info->next == next->next)
1073 list_info->next=next;
1076 list_info->elements++;
1077 UnlockSemaphoreInfo(list_info->semaphore);
1113MagickExport MagickBooleanType InsertValueInSortedLinkedList(
1114 LinkedListInfo *list_info,
int (*compare)(
const void *,
const void *),
1115 void **replace,
const void *value)
1127 assert(list_info->signature == MagickCoreSignature);
1128 if ((compare == (
int (*)(
const void *,
const void *)) NULL) ||
1129 (value == (
const void *) NULL))
1130 return(MagickFalse);
1131 if (list_info->elements == list_info->capacity)
1132 return(MagickFalse);
1133 next=(
ElementInfo *) AcquireMagickMemory(
sizeof(*next));
1135 return(MagickFalse);
1136 next->value=(
void *) value;
1138 LockSemaphoreInfo(list_info->semaphore);
1139 next->next=list_info->head;
1142 i=(ssize_t) compare(value,next->next->value);
1143 if ((i < 0) || ((replace != (
void **) NULL) && (i == 0)))
1147 *replace=next->next->value;
1148 next->next=next->next->next;
1150 element->next=(
ElementInfo *) RelinquishMagickMemory(
1152 list_info->elements--;
1157 list_info->head=next;
1161 next->next=next->next->next;
1168 list_info->head=next;
1169 list_info->tail=next;
1171 list_info->elements++;
1172 UnlockSemaphoreInfo(list_info->semaphore);
1198MagickExport MagickBooleanType IsHashmapEmpty(
const HashmapInfo *hashmap_info)
1201 assert(hashmap_info->signature == MagickCoreSignature);
1202 return(hashmap_info->entries == 0 ? MagickTrue : MagickFalse);
1227MagickExport MagickBooleanType IsLinkedListEmpty(
1231 assert(list_info->signature == MagickCoreSignature);
1232 return(list_info->elements == 0 ? MagickTrue : MagickFalse);
1260MagickExport MagickBooleanType LinkedListToArray(
LinkedListInfo *list_info,
1270 assert(list_info->signature == MagickCoreSignature);
1271 if (array == (
void **) NULL)
1272 return(MagickFalse);
1273 LockSemaphoreInfo(list_info->semaphore);
1274 next=list_info->head;
1277 array[i]=next->value;
1280 UnlockSemaphoreInfo(list_info->semaphore);
1330MagickExport
HashmapInfo *NewHashmap(
const size_t capacity,
1331 size_t (*hash)(
const void *),
1332 MagickBooleanType (*compare)(
const void *,
const void *),
1333 void *(*relinquish_key)(
void *),
void *(*relinquish_value)(
void *))
1338 hashmap_info=(
HashmapInfo *) AcquireMagickMemory(
sizeof(*hashmap_info));
1340 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1341 (void) memset(hashmap_info,0,
sizeof(*hashmap_info));
1342 hashmap_info->hash=HashPointerType;
1343 if (hash != (
size_t (*)(
const void *)) NULL)
1344 hashmap_info->hash=hash;
1345 hashmap_info->compare=(MagickBooleanType (*)(
const void *,
const void *)) NULL;
1346 if (compare != (MagickBooleanType (*)(
const void *,
const void *)) NULL)
1347 hashmap_info->compare=compare;
1348 hashmap_info->relinquish_key=relinquish_key;
1349 hashmap_info->relinquish_value=relinquish_value;
1350 hashmap_info->entries=0;
1351 hashmap_info->capacity=capacity;
1353 if (~capacity >= 1UL)
1354 hashmap_info->map=(
LinkedListInfo **) AcquireQuantumMemory((
size_t)
1355 capacity+1UL,
sizeof(*hashmap_info->map));
1357 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1358 (void) memset(hashmap_info->map,0,(
size_t) capacity*
1359 sizeof(*hashmap_info->map));
1360 hashmap_info->semaphore=AllocateSemaphoreInfo();
1361 hashmap_info->signature=MagickCoreSignature;
1362 return(hashmap_info);
1393 list_info=(
LinkedListInfo *) AcquireMagickMemory(
sizeof(*list_info));
1395 ThrowFatalException(ResourceLimitFatalError,
"MemoryAllocationFailed");
1396 (void) memset(list_info,0,
sizeof(*list_info));
1397 list_info->capacity=capacity == 0 ? (size_t) (~0) : capacity;
1398 list_info->elements=0;
1402 list_info->semaphore=AllocateSemaphoreInfo();
1403 list_info->signature=MagickCoreSignature;
1436static MagickBooleanType IncreaseHashmapCapacity(
HashmapInfo *hashmap_info)
1438#define MaxCapacities 20
1441 capacities[MaxCapacities] =
1443 17, 31, 61, 131, 257, 509, 1021, 2053, 4099, 8191, 16381, 32771,
1444 65537, 131071, 262147, 524287, 1048573, 2097143, 4194301, 8388617
1469 for (i=0; i < MaxCapacities; i++)
1470 if (hashmap_info->capacity < capacities[i])
1472 if (i >= (MaxCapacities-1))
1473 return(MagickFalse);
1474 capacity=capacities[i+1];
1475 map=(
LinkedListInfo **) AcquireQuantumMemory((
size_t) capacity+1UL,
1478 return(MagickFalse);
1479 (void) memset(map,0,(
size_t) capacity*
sizeof(*map));
1483 for (i=0; i < (ssize_t) hashmap_info->capacity; i++)
1488 list_info=hashmap_info->map[i];
1491 LockSemaphoreInfo(list_info->semaphore);
1492 for (next=list_info->head; next != (
ElementInfo *) NULL; )
1497 map_info=map[entry->hash % capacity];
1500 map_info=NewLinkedList(0);
1501 map[entry->hash % capacity]=map_info;
1503 map_info->next=element;
1504 element->next=map_info->head;
1505 map_info->head=element;
1506 map_info->elements++;
1508 list_info->signature=(~MagickCoreSignature);
1509 UnlockSemaphoreInfo(list_info->semaphore);
1510 DestroySemaphoreInfo(&list_info->semaphore);
1515 hashmap_info->map=map;
1516 hashmap_info->capacity=capacity;
1520MagickExport MagickBooleanType PutEntryInHashmap(
HashmapInfo *hashmap_info,
1521 const void *key,
const void *value)
1534 assert(hashmap_info->signature == MagickCoreSignature);
1535 if ((key == (
void *) NULL) || (value == (
void *) NULL))
1536 return(MagickFalse);
1537 next=(
EntryInfo *) AcquireMagickMemory(
sizeof(*next));
1539 return(MagickFalse);
1540 LockSemaphoreInfo(hashmap_info->semaphore);
1541 next->hash=hashmap_info->hash(key);
1542 next->key=(
void *) key;
1543 next->value=(
void *) value;
1544 list_info=hashmap_info->map[next->hash % hashmap_info->capacity];
1547 list_info=NewLinkedList(0);
1548 hashmap_info->map[next->hash % hashmap_info->capacity]=list_info;
1552 list_info->next=list_info->head;
1553 entry=(
EntryInfo *) GetNextValueInLinkedList(list_info);
1554 for (i=0; entry != (
EntryInfo *) NULL; i++)
1556 if (entry->hash == next->hash)
1562 if (hashmap_info->compare !=
1563 (MagickBooleanType (*)(
const void *,
const void *)) NULL)
1564 compare=hashmap_info->compare(key,entry->key);
1565 if (compare != MagickFalse)
1567 (void) RemoveElementFromLinkedList(list_info,i);
1568 if (hashmap_info->relinquish_key != (
void *(*)(
void *)) NULL)
1569 entry->key=hashmap_info->relinquish_key(entry->key);
1570 if (hashmap_info->relinquish_value != (
void *(*)(
void *)) NULL)
1571 entry->value=hashmap_info->relinquish_value(entry->value);
1572 entry=(
EntryInfo *) RelinquishMagickMemory(entry);
1576 entry=(
EntryInfo *) GetNextValueInLinkedList(list_info);
1579 if (InsertValueInLinkedList(list_info,0,next) == MagickFalse)
1581 next=(
EntryInfo *) RelinquishMagickMemory(next);
1582 UnlockSemaphoreInfo(hashmap_info->semaphore);
1583 return(MagickFalse);
1585 if (list_info->elements >= (hashmap_info->capacity-1))
1586 if (IncreaseHashmapCapacity(hashmap_info) == MagickFalse)
1588 UnlockSemaphoreInfo(hashmap_info->semaphore);
1589 return(MagickFalse);
1591 hashmap_info->entries++;
1592 UnlockSemaphoreInfo(hashmap_info->semaphore);
1622MagickExport
void *RemoveElementByValueFromLinkedList(
LinkedListInfo *list_info,
1629 assert(list_info->signature == MagickCoreSignature);
1630 if ((list_info->elements == 0) || (value == (
const void *) NULL))
1631 return((
void *) NULL);
1632 LockSemaphoreInfo(list_info->semaphore);
1633 if (value == list_info->head->value)
1635 if (list_info->next == list_info->head)
1636 list_info->next=list_info->head->next;
1637 next=list_info->head;
1638 list_info->head=list_info->head->next;
1639 next=(
ElementInfo *) RelinquishMagickMemory(next);
1646 next=list_info->head;
1648 (next->next->value != value))
1652 UnlockSemaphoreInfo(list_info->semaphore);
1653 return((
void *) NULL);
1656 next->next=element->next;
1657 if (element == list_info->tail)
1658 list_info->tail=next;
1659 if (list_info->next == element)
1660 list_info->next=element->next;
1661 element=(
ElementInfo *) RelinquishMagickMemory(element);
1663 list_info->elements--;
1664 UnlockSemaphoreInfo(list_info->semaphore);
1665 return((
void *) value);
1694MagickExport
void *RemoveElementFromLinkedList(
LinkedListInfo *list_info,
1707 assert(list_info->signature == MagickCoreSignature);
1708 if (index >= list_info->elements)
1709 return((
void *) NULL);
1710 LockSemaphoreInfo(list_info->semaphore);
1713 if (list_info->next == list_info->head)
1714 list_info->next=list_info->head->next;
1715 value=list_info->head->value;
1716 next=list_info->head;
1717 list_info->head=list_info->head->next;
1718 next=(
ElementInfo *) RelinquishMagickMemory(next);
1725 next=list_info->head;
1726 for (i=1; i < (ssize_t) index; i++)
1729 next->next=element->next;
1730 if (element == list_info->tail)
1731 list_info->tail=next;
1732 if (list_info->next == element)
1733 list_info->next=element->next;
1734 value=element->value;
1735 element=(
ElementInfo *) RelinquishMagickMemory(element);
1737 list_info->elements--;
1738 UnlockSemaphoreInfo(list_info->semaphore);
1766MagickExport
void *RemoveEntryFromHashmap(
HashmapInfo *hashmap_info,
1785 assert(hashmap_info->signature == MagickCoreSignature);
1786 if (key == (
const void *) NULL)
1787 return((
void *) NULL);
1788 LockSemaphoreInfo(hashmap_info->semaphore);
1789 hash=hashmap_info->hash(key);
1790 list_info=hashmap_info->map[hash % hashmap_info->capacity];
1793 list_info->next=list_info->head;
1794 entry=(
EntryInfo *) GetNextValueInLinkedList(list_info);
1795 for (i=0; entry != (
EntryInfo *) NULL; i++)
1797 if (entry->hash == hash)
1803 if (hashmap_info->compare !=
1804 (MagickBooleanType (*)(
const void *,
const void *)) NULL)
1805 compare=hashmap_info->compare(key,entry->key);
1806 if (compare != MagickFalse)
1808 entry=(
EntryInfo *) RemoveElementFromLinkedList(list_info,i);
1811 UnlockSemaphoreInfo(hashmap_info->semaphore);
1812 return((
void *) NULL);
1814 if (hashmap_info->relinquish_key != (
void *(*)(
void *)) NULL)
1815 entry->key=hashmap_info->relinquish_key(entry->key);
1817 entry=(
EntryInfo *) RelinquishMagickMemory(entry);
1818 hashmap_info->entries--;
1819 UnlockSemaphoreInfo(hashmap_info->semaphore);
1823 entry=(
EntryInfo *) GetNextValueInLinkedList(list_info);
1826 UnlockSemaphoreInfo(hashmap_info->semaphore);
1827 return((
void *) NULL);
1853MagickExport
void *RemoveLastElementFromLinkedList(
LinkedListInfo *list_info)
1859 assert(list_info->signature == MagickCoreSignature);
1860 if (list_info->elements == 0)
1861 return((
void *) NULL);
1862 LockSemaphoreInfo(list_info->semaphore);
1863 if (list_info->next == list_info->tail)
1865 if (list_info->elements == 1UL)
1867 value=list_info->head->value;
1869 list_info->tail=(
ElementInfo *) RelinquishMagickMemory(list_info->tail);
1876 value=list_info->tail->value;
1877 next=list_info->head;
1878 while (next->next != list_info->tail)
1880 list_info->tail=(
ElementInfo *) RelinquishMagickMemory(list_info->tail);
1881 list_info->tail=next;
1884 list_info->elements--;
1885 UnlockSemaphoreInfo(list_info->semaphore);
1912MagickExport
void ResetHashmapIterator(
HashmapInfo *hashmap_info)
1915 assert(hashmap_info->signature == MagickCoreSignature);
1916 LockSemaphoreInfo(hashmap_info->semaphore);
1917 hashmap_info->next=0;
1918 hashmap_info->head_of_list=MagickFalse;
1919 UnlockSemaphoreInfo(hashmap_info->semaphore);
1946MagickExport
void ResetLinkedListIterator(
LinkedListInfo *list_info)
1949 assert(list_info->signature == MagickCoreSignature);
1950 LockSemaphoreInfo(list_info->semaphore);
1951 list_info->next=list_info->head;
1952 UnlockSemaphoreInfo(list_info->semaphore);
1980MagickPrivate
void SetHeadElementInLinkedList(
LinkedListInfo *list_info,
1987 assert(list_info->signature == MagickCoreSignature);
1989 if (element == list_info->head)
1991 prev=list_info->head;
1994 if (prev->next == element)
1996 prev->next=element->next;
1997 element->next=list_info->head;
1998 if (list_info->head == list_info->next)
1999 list_info->next=element;
2000 list_info->head=element;