MagickCore  7.0.0
hashmap.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % H H AAA SSSSS H H M M AAA PPPP %
7 % H H A A SS H H MM MM A A P P %
8 % HHHHH AAAAA SSS HHHHH M M M AAAAA PPPP %
9 % H H A A SS H H M M A A P %
10 % H H A A SSSSS H H M M A A P %
11 % %
12 % %
13 % MagickCore Hash-map and Linked-list Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % December 2002 %
18 % %
19 % %
20 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % http://www.imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 % This module implements the standard handy hash and linked-list methods for
37 % storing and retrieving large numbers of data elements. It is loosely based
38 % on the Java implementation of these algorithms.
39 %
40 */
41 
42 /*
43  Include declarations.
44 */
45 #include "MagickCore/studio.h"
46 #include "MagickCore/exception.h"
48 #include "MagickCore/locale_.h"
49 #include "MagickCore/hashmap.h"
50 #include "MagickCore/memory_.h"
51 #include "MagickCore/semaphore.h"
53 #include "MagickCore/string_.h"
54 
55 /*
56  Typedef declarations.
57 */
58 typedef struct _ElementInfo
59 {
60  void
62 
63  struct _ElementInfo
64  *next;
65 } ElementInfo;
66 
67 typedef struct _EntryInfo
68 {
69  size_t
71 
72  void
73  *key,
74  *value;
75 } EntryInfo;
76 
78 {
79  size_t
81  elements;
82 
84  *head,
85  *tail,
86  *next;
87 
90 
91  size_t
93 };
94 
96 {
97  size_t
98  (*hash)(const void *);
99 
101  (*compare)(const void *,const void *);
102 
103  void
104  *(*relinquish_key)(void *),
105  *(*relinquish_value)(void *);
106 
107  size_t
109  entries,
110  next;
111 
114 
116  **map;
117 
120 
121  size_t
123 };
124 
125 /*
126 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127 % %
128 % %
129 % %
130 % A p p e n d V a l u e T o L i n k e d L i s t %
131 % %
132 % %
133 % %
134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
135 %
136 % AppendValueToLinkedList() appends a value to the end of the linked-list.
137 %
138 % The format of the AppendValueToLinkedList method is:
139 %
140 % MagickBooleanType AppendValueToLinkedList(LinkedListInfo *list_info,
141 % const void *value)
142 %
143 % A description of each parameter follows:
144 %
145 % o list_info: the linked-list info.
146 %
147 % o value: the value.
148 %
149 */
151  LinkedListInfo *list_info,const void *value)
152 {
153  register ElementInfo
154  *next;
155 
156  assert(list_info != (LinkedListInfo *) NULL);
157  assert(list_info->signature == MagickCoreSignature);
158  if (list_info->elements == list_info->capacity)
159  return(MagickFalse);
160  next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
161  if (next == (ElementInfo *) NULL)
162  return(MagickFalse);
163  next->value=(void *) value;
164  next->next=(ElementInfo *) NULL;
165  LockSemaphoreInfo(list_info->semaphore);
166  if (list_info->next == (ElementInfo *) NULL)
167  list_info->next=next;
168  if (list_info->elements == 0)
169  list_info->head=next;
170  else
171  list_info->tail->next=next;
172  list_info->tail=next;
173  list_info->elements++;
174  UnlockSemaphoreInfo(list_info->semaphore);
175  return(MagickTrue);
176 }
177 
178 /*
179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180 % %
181 % %
182 % %
183 % C l e a r L i n k e d L i s t %
184 % %
185 % %
186 % %
187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188 %
189 % ClearLinkedList() clears all the elements from the linked-list.
190 %
191 % The format of the ClearLinkedList method is:
192 %
193 % void ClearLinkedList(LinkedListInfo *list_info,
194 % void *(*relinquish_value)(void *))
195 %
196 % A description of each parameter follows:
197 %
198 % o list_info: the linked-list info.
199 %
200 % o relinquish_value: the value deallocation method; typically
201 % RelinquishMagickMemory().
202 %
203 */
205  void *(*relinquish_value)(void *))
206 {
208  *element;
209 
210  register ElementInfo
211  *next;
212 
213  assert(list_info != (LinkedListInfo *) NULL);
214  assert(list_info->signature == MagickCoreSignature);
215  LockSemaphoreInfo(list_info->semaphore);
216  next=list_info->head;
217  while (next != (ElementInfo *) NULL)
218  {
219  if (relinquish_value != (void *(*)(void *)) NULL)
220  next->value=relinquish_value(next->value);
221  element=next;
222  next=next->next;
223  element=(ElementInfo *) RelinquishMagickMemory(element);
224  }
225  list_info->head=(ElementInfo *) NULL;
226  list_info->tail=(ElementInfo *) NULL;
227  list_info->next=(ElementInfo *) NULL;
228  list_info->elements=0;
229  UnlockSemaphoreInfo(list_info->semaphore);
230 }
231 
232 /*
233 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234 % %
235 % %
236 % %
237 % C o m p a r e H a s h m a p S t r i n g %
238 % %
239 % %
240 % %
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 %
243 % CompareHashmapString() finds an entry in a hash-map based on the contents
244 % of a string.
245 %
246 % The format of the CompareHashmapString method is:
247 %
248 % MagickBooleanType CompareHashmapString(const void *target,
249 % const void *source)
250 %
251 % A description of each parameter follows:
252 %
253 % o target: the target string.
254 %
255 % o source: the source string.
256 %
257 */
259  const void *source)
260 {
261  const char
262  *p,
263  *q;
264 
265  p=(const char *) target;
266  q=(const char *) source;
267  return(LocaleCompare(p,q) == 0 ? MagickTrue : MagickFalse);
268 }
269 
270 /*
271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272 % %
273 % %
274 % %
275 % C o m p a r e H a s h m a p S t r i n g I n f o %
276 % %
277 % %
278 % %
279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280 %
281 % CompareHashmapStringInfo() finds an entry in a hash-map based on the
282 % contents of a string.
283 %
284 % The format of the CompareHashmapStringInfo method is:
285 %
286 % MagickBooleanType CompareHashmapStringInfo(const void *target,
287 % const void *source)
288 %
289 % A description of each parameter follows:
290 %
291 % o target: the target string.
292 %
293 % o source: the source string.
294 %
295 */
297  const void *source)
298 {
299  const StringInfo
300  *p,
301  *q;
302 
303  p=(const StringInfo *) target;
304  q=(const StringInfo *) source;
305  return(CompareStringInfo(p,q) == 0 ? MagickTrue : MagickFalse);
306 }
307 
308 /*
309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310 % %
311 % %
312 % %
313 % D e s t r o y H a s h m a p %
314 % %
315 % %
316 % %
317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318 %
319 % DestroyHashmap() frees the hash-map and all associated resources.
320 %
321 % The format of the DestroyHashmap method is:
322 %
323 % HashmapInfo *DestroyHashmap(HashmapInfo *hashmap_info)
324 %
325 % A description of each parameter follows:
326 %
327 % o hashmap_info: the hashmap info.
328 %
329 */
331 {
333  *list_info;
334 
335  register EntryInfo
336  *entry;
337 
338  register ssize_t
339  i;
340 
341  assert(hashmap_info != (HashmapInfo *) NULL);
342  assert(hashmap_info->signature == MagickCoreSignature);
343  LockSemaphoreInfo(hashmap_info->semaphore);
344  for (i=0; i < (ssize_t) hashmap_info->capacity; i++)
345  {
346  list_info=hashmap_info->map[i];
347  if (list_info != (LinkedListInfo *) NULL)
348  {
349  list_info->next=list_info->head;
350  entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
351  while (entry != (EntryInfo *) NULL)
352  {
353  if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
354  entry->key=hashmap_info->relinquish_key(entry->key);
355  if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
356  entry->value=hashmap_info->relinquish_value(entry->value);
357  entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
358  }
359  }
360  if (list_info != (LinkedListInfo *) NULL)
361  list_info=DestroyLinkedList(list_info,RelinquishMagickMemory);
362  }
363  hashmap_info->map=(LinkedListInfo **) RelinquishMagickMemory(
364  hashmap_info->map);
365  hashmap_info->signature=(~MagickCoreSignature);
366  UnlockSemaphoreInfo(hashmap_info->semaphore);
367  RelinquishSemaphoreInfo(&hashmap_info->semaphore);
368  hashmap_info=(HashmapInfo *) RelinquishMagickMemory(hashmap_info);
369  return(hashmap_info);
370 }
371 
372 /*
373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
374 % %
375 % %
376 % %
377 % D e s t r o y L i n k e d L i s t %
378 % %
379 % %
380 % %
381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
382 %
383 % DestroyLinkedList() frees the linked-list and all associated resources.
384 %
385 % The format of the DestroyLinkedList method is:
386 %
387 % LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
388 % void *(*relinquish_value)(void *))
389 %
390 % A description of each parameter follows:
391 %
392 % o list_info: the linked-list info.
393 %
394 % o relinquish_value: the value deallocation method; typically
395 % RelinquishMagickMemory().
396 %
397 */
399  void *(*relinquish_value)(void *))
400 {
402  *entry;
403 
404  register ElementInfo
405  *next;
406 
407  assert(list_info != (LinkedListInfo *) NULL);
408  assert(list_info->signature == MagickCoreSignature);
409  LockSemaphoreInfo(list_info->semaphore);
410  for (next=list_info->head; next != (ElementInfo *) NULL; )
411  {
412  if (relinquish_value != (void *(*)(void *)) NULL)
413  next->value=relinquish_value(next->value);
414  entry=next;
415  next=next->next;
416  entry=(ElementInfo *) RelinquishMagickMemory(entry);
417  }
418  list_info->signature=(~MagickCoreSignature);
419  UnlockSemaphoreInfo(list_info->semaphore);
420  RelinquishSemaphoreInfo(&list_info->semaphore);
421  list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
422  return(list_info);
423 }
424 
425 /*
426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427 % %
428 % %
429 % %
430 % G e t L a s t V a l u e I n L i n k e d L i s t %
431 % %
432 % %
433 % %
434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435 %
436 % GetLastValueInLinkedList() gets the last value in the linked-list.
437 %
438 % The format of the GetLastValueInLinkedList method is:
439 %
440 % void *GetLastValueInLinkedList(LinkedListInfo *list_info)
441 %
442 % A description of each parameter follows:
443 %
444 % o list_info: the linked_list info.
445 %
446 */
448 {
449  void
450  *value;
451 
452  assert(list_info != (LinkedListInfo *) NULL);
453  assert(list_info->signature == MagickCoreSignature);
454  if (list_info->elements == 0)
455  return((void *) NULL);
456  LockSemaphoreInfo(list_info->semaphore);
457  value=list_info->tail->value;
458  UnlockSemaphoreInfo(list_info->semaphore);
459  return(value);
460 }
461 
462 /*
463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464 % %
465 % %
466 % %
467 % G e t N e x t K e y I n H a s h m a p %
468 % %
469 % %
470 % %
471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
472 %
473 % GetNextKeyInHashmap() gets the next key in the hash-map.
474 %
475 % The format of the GetNextKeyInHashmap method is:
476 %
477 % void *GetNextKeyInHashmap(HashmapInfo *hashmap_info)
478 %
479 % A description of each parameter follows:
480 %
481 % o hashmap_info: the hashmap info.
482 %
483 */
485 {
487  *list_info;
488 
489  register EntryInfo
490  *entry;
491 
492  void
493  *key;
494 
495  assert(hashmap_info != (HashmapInfo *) NULL);
496  assert(hashmap_info->signature == MagickCoreSignature);
497  LockSemaphoreInfo(hashmap_info->semaphore);
498  while (hashmap_info->next < hashmap_info->capacity)
499  {
500  list_info=hashmap_info->map[hashmap_info->next];
501  if (list_info != (LinkedListInfo *) NULL)
502  {
503  if (hashmap_info->head_of_list == MagickFalse)
504  {
505  list_info->next=list_info->head;
506  hashmap_info->head_of_list=MagickTrue;
507  }
508  entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
509  if (entry != (EntryInfo *) NULL)
510  {
511  key=entry->key;
512  UnlockSemaphoreInfo(hashmap_info->semaphore);
513  return(key);
514  }
515  hashmap_info->head_of_list=MagickFalse;
516  }
517  hashmap_info->next++;
518  }
519  UnlockSemaphoreInfo(hashmap_info->semaphore);
520  return((void *) NULL);
521 }
522 
523 /*
524 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
525 % %
526 % %
527 % %
528 % G e t N e x t V a l u e I n H a s h m a p %
529 % %
530 % %
531 % %
532 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 %
534 % GetNextValueInHashmap() gets the next value in the hash-map.
535 %
536 % The format of the GetNextValueInHashmap method is:
537 %
538 % void *GetNextValueInHashmap(HashmapInfo *hashmap_info)
539 %
540 % A description of each parameter follows:
541 %
542 % o hashmap_info: the hashmap info.
543 %
544 */
546 {
548  *list_info;
549 
550  register EntryInfo
551  *entry;
552 
553  void
554  *value;
555 
556  assert(hashmap_info != (HashmapInfo *) NULL);
557  assert(hashmap_info->signature == MagickCoreSignature);
558  LockSemaphoreInfo(hashmap_info->semaphore);
559  while (hashmap_info->next < hashmap_info->capacity)
560  {
561  list_info=hashmap_info->map[hashmap_info->next];
562  if (list_info != (LinkedListInfo *) NULL)
563  {
564  if (hashmap_info->head_of_list == MagickFalse)
565  {
566  list_info->next=list_info->head;
567  hashmap_info->head_of_list=MagickTrue;
568  }
569  entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
570  if (entry != (EntryInfo *) NULL)
571  {
572  value=entry->value;
573  UnlockSemaphoreInfo(hashmap_info->semaphore);
574  return(value);
575  }
576  hashmap_info->head_of_list=MagickFalse;
577  }
578  hashmap_info->next++;
579  }
580  UnlockSemaphoreInfo(hashmap_info->semaphore);
581  return((void *) NULL);
582 }
583 
584 /*
585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
586 % %
587 % %
588 % %
589 % G e t N e x t V a l u e I n L i n k e d L i s t %
590 % %
591 % %
592 % %
593 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594 %
595 % GetNextValueInLinkedList() gets the next value in the linked-list.
596 %
597 % The format of the GetNextValueInLinkedList method is:
598 %
599 % void *GetNextValueInLinkedList(LinkedListInfo *list_info)
600 %
601 % A description of each parameter follows:
602 %
603 % o list_info: the linked-list info.
604 %
605 */
607 {
608  void
609  *value;
610 
611  assert(list_info != (LinkedListInfo *) NULL);
612  assert(list_info->signature == MagickCoreSignature);
613  LockSemaphoreInfo(list_info->semaphore);
614  if (list_info->next == (ElementInfo *) NULL)
615  {
616  UnlockSemaphoreInfo(list_info->semaphore);
617  return((void *) NULL);
618  }
619  value=list_info->next->value;
620  list_info->next=list_info->next->next;
621  UnlockSemaphoreInfo(list_info->semaphore);
622  return(value);
623 }
624 
625 /*
626 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627 % %
628 % %
629 % %
630 % G e t N u m b e r O f E n t r i e s I n H a s h m a p %
631 % %
632 % %
633 % %
634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
635 %
636 % GetNumberOfEntriesInHashmap() returns the number of entries in the hash-map.
637 %
638 % The format of the GetNumberOfEntriesInHashmap method is:
639 %
640 % size_t GetNumberOfEntriesInHashmap(const HashmapInfo *hashmap_info)
641 %
642 % A description of each parameter follows:
643 %
644 % o hashmap_info: the hashmap info.
645 %
646 */
648  const HashmapInfo *hashmap_info)
649 {
650  assert(hashmap_info != (HashmapInfo *) NULL);
651  assert(hashmap_info->signature == MagickCoreSignature);
652  return(hashmap_info->entries);
653 }
654 
655 /*
656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
657 % %
658 % %
659 % %
660 % 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 %
661 % %
662 % %
663 % %
664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665 %
666 % GetNumberOfElementsInLinkedList() returns the number of entries in the
667 % linked-list.
668 %
669 % The format of the GetNumberOfElementsInLinkedList method is:
670 %
671 % size_t GetNumberOfElementsInLinkedList(
672 % const LinkedListInfo *list_info)
673 %
674 % A description of each parameter follows:
675 %
676 % o list_info: the linked-list info.
677 %
678 */
680  const LinkedListInfo *list_info)
681 {
682  assert(list_info != (LinkedListInfo *) NULL);
683  assert(list_info->signature == MagickCoreSignature);
684  return(list_info->elements);
685 }
686 
687 /*
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 % %
690 % %
691 % %
692 % G e t V a l u e F r o m H a s h m a p %
693 % %
694 % %
695 % %
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697 %
698 % GetValueFromHashmap() gets an entry from the hash-map by its key.
699 %
700 % The format of the GetValueFromHashmap method is:
701 %
702 % void *GetValueFromHashmap(HashmapInfo *hashmap_info,const void *key)
703 %
704 % A description of each parameter follows:
705 %
706 % o hashmap_info: the hashmap info.
707 %
708 % o key: the key.
709 %
710 */
712  const void *key)
713 {
715  *list_info;
716 
717  register EntryInfo
718  *entry;
719 
720  size_t
721  hash;
722 
723  void
724  *value;
725 
726  assert(hashmap_info != (HashmapInfo *) NULL);
727  assert(hashmap_info->signature == MagickCoreSignature);
728  if (key == (const void *) NULL)
729  return((void *) NULL);
730  LockSemaphoreInfo(hashmap_info->semaphore);
731  hash=hashmap_info->hash(key);
732  list_info=hashmap_info->map[hash % hashmap_info->capacity];
733  if (list_info != (LinkedListInfo *) NULL)
734  {
735  list_info->next=list_info->head;
736  entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
737  while (entry != (EntryInfo *) NULL)
738  {
739  if (entry->hash == hash)
740  {
742  compare;
743 
744  compare=MagickTrue;
745  if (hashmap_info->compare !=
746  (MagickBooleanType (*)(const void *,const void *)) NULL)
747  compare=hashmap_info->compare(key,entry->key);
748  if (compare != MagickFalse)
749  {
750  value=entry->value;
751  UnlockSemaphoreInfo(hashmap_info->semaphore);
752  return(value);
753  }
754  }
755  entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
756  }
757  }
758  UnlockSemaphoreInfo(hashmap_info->semaphore);
759  return((void *) NULL);
760 }
761 
762 /*
763 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
764 % %
765 % %
766 % %
767 % G e t V a l u e F r o m L i n k e d L i s t %
768 % %
769 % %
770 % %
771 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
772 %
773 % GetValueFromLinkedList() gets a value from the linked-list at the specified
774 % location.
775 %
776 % The format of the GetValueFromLinkedList method is:
777 %
778 % void *GetValueFromLinkedList(LinkedListInfo *list_info,
779 % const size_t index)
780 %
781 % A description of each parameter follows:
782 %
783 % o list_info: the linked_list info.
784 %
785 % o index: the list index.
786 %
787 */
789  const size_t index)
790 {
791  register ElementInfo
792  *next;
793 
794  register ssize_t
795  i;
796 
797  void
798  *value;
799 
800  assert(list_info != (LinkedListInfo *) NULL);
801  assert(list_info->signature == MagickCoreSignature);
802  if (index >= list_info->elements)
803  return((void *) NULL);
804  LockSemaphoreInfo(list_info->semaphore);
805  if (index == 0)
806  {
807  value=list_info->head->value;
808  UnlockSemaphoreInfo(list_info->semaphore);
809  return(value);
810  }
811  if (index == (list_info->elements-1))
812  {
813  value=list_info->tail->value;
814  UnlockSemaphoreInfo(list_info->semaphore);
815  return(value);
816  }
817  next=list_info->head;
818  for (i=0; i < (ssize_t) index; i++)
819  next=next->next;
820  value=next->value;
821  UnlockSemaphoreInfo(list_info->semaphore);
822  return(value);
823 }
824 
825 /*
826 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827 % %
828 % %
829 % %
830 % H a s h P o i n t e r T y p e %
831 % %
832 % %
833 % %
834 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
835 %
836 % HashPointerType() finds an entry in a hash-map based on the address of a
837 % pointer.
838 %
839 % The format of the HashPointerType method is:
840 %
841 % size_t HashPointerType(const void *pointer)
842 %
843 % A description of each parameter follows:
844 %
845 % o pointer: compute the hash entry location from this pointer address.
846 %
847 */
848 MagickExport size_t HashPointerType(const void *pointer)
849 {
850  size_t
851  hash;
852 
853  hash=(size_t) pointer;
854  hash+=(~(hash << 9));
855  hash^=(hash >> 14);
856  hash+=(hash << 4);
857  hash^=(hash >> 10);
858  return(hash);
859 }
860 
861 /*
862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
863 % %
864 % %
865 % %
866 % H a s h S t r i n g T y p e %
867 % %
868 % %
869 % %
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
871 %
872 % HashStringType() finds an entry in a hash-map based on the contents of a
873 % string.
874 %
875 % The format of the HashStringType method is:
876 %
877 % size_t HashStringType(const void *string)
878 %
879 % A description of each parameter follows:
880 %
881 % o string: compute the hash entry location from this string.
882 %
883 */
884 MagickExport size_t HashStringType(const void *string)
885 {
886  const unsigned char
887  *digest;
888 
889  register ssize_t
890  i;
891 
893  *signature_info;
894 
895  size_t
896  hash;
897 
898  StringInfo
899  *signature;
900 
901  signature_info=AcquireSignatureInfo();
902  signature=StringToStringInfo((const char *) string);
903  UpdateSignature(signature_info,signature);
904  FinalizeSignature(signature_info);
905  digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
906  hash=0;
907  for (i=0; i < 8; i++)
908  hash^=digest[i];
909  signature=DestroyStringInfo(signature);
910  signature_info=DestroySignatureInfo(signature_info);
911  return(hash);
912 }
913 
914 /*
915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916 % %
917 % %
918 % %
919 % H a s h S t r i n g I n f o T y p e %
920 % %
921 % %
922 % %
923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
924 %
925 % Specify the HashStringInfoType() method in NewHashmap() to find an entry
926 % in a hash-map based on the contents of a string.
927 %
928 % The format of the HashStringInfoType method is:
929 %
930 % size_t HashStringInfoType(const void *string_info)
931 %
932 % A description of each parameter follows:
933 %
934 % o string_info: compute the hash entry location from this string.
935 %
936 */
937 MagickExport size_t HashStringInfoType(const void *string_info)
938 {
939  const unsigned char
940  *digest;
941 
942  register ssize_t
943  i;
944 
946  *signature_info;
947 
948  size_t
949  hash;
950 
951  signature_info=AcquireSignatureInfo();
952  UpdateSignature(signature_info,(const StringInfo *) string_info);
953  FinalizeSignature(signature_info);
954  digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
955  hash=0;
956  for (i=0; i < 8; i++)
957  hash^=digest[i];
958  signature_info=DestroySignatureInfo(signature_info);
959  return(hash);
960 }
961 
962 /*
963 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
964 % %
965 % %
966 % %
967 % I n s e r t V a l u e I n L i n k e d L i s t %
968 % %
969 % %
970 % %
971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
972 %
973 % InsertValueInLinkedList() inserts an element in the linked-list at the
974 % specified location.
975 %
976 % The format of the InsertValueInLinkedList method is:
977 %
978 % MagickBooleanType InsertValueInLinkedList(ListInfo *list_info,
979 % const size_t index,const void *value)
980 %
981 % A description of each parameter follows:
982 %
983 % o list_info: the hashmap info.
984 %
985 % o index: the index.
986 %
987 % o value: the value.
988 %
989 */
991  LinkedListInfo *list_info,const size_t index,const void *value)
992 {
993  register ElementInfo
994  *next;
995 
996  register ssize_t
997  i;
998 
999  assert(list_info != (LinkedListInfo *) NULL);
1000  assert(list_info->signature == MagickCoreSignature);
1001  if (value == (const void *) NULL)
1002  return(MagickFalse);
1003  if ((index > list_info->elements) ||
1004  (list_info->elements == list_info->capacity))
1005  return(MagickFalse);
1006  next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
1007  if (next == (ElementInfo *) NULL)
1008  return(MagickFalse);
1009  next->value=(void *) value;
1010  next->next=(ElementInfo *) NULL;
1011  LockSemaphoreInfo(list_info->semaphore);
1012  if (list_info->elements == 0)
1013  {
1014  if (list_info->next == (ElementInfo *) NULL)
1015  list_info->next=next;
1016  list_info->head=next;
1017  list_info->tail=next;
1018  }
1019  else
1020  {
1021  if (index == 0)
1022  {
1023  if (list_info->next == list_info->head)
1024  list_info->next=next;
1025  next->next=list_info->head;
1026  list_info->head=next;
1027  }
1028  else
1029  if (index == list_info->elements)
1030  {
1031  if (list_info->next == (ElementInfo *) NULL)
1032  list_info->next=next;
1033  list_info->tail->next=next;
1034  list_info->tail=next;
1035  }
1036  else
1037  {
1038  ElementInfo
1039  *element;
1040 
1041  element=list_info->head;
1042  next->next=element->next;
1043  for (i=1; i < (ssize_t) index; i++)
1044  {
1045  element=element->next;
1046  next->next=element->next;
1047  }
1048  next=next->next;
1049  element->next=next;
1050  if (list_info->next == next->next)
1051  list_info->next=next;
1052  }
1053  }
1054  list_info->elements++;
1055  UnlockSemaphoreInfo(list_info->semaphore);
1056  return(MagickTrue);
1057 }
1058 
1059 /*
1060 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1061 % %
1062 % %
1063 % %
1064 % 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 %
1065 % %
1066 % %
1067 % %
1068 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1069 %
1070 % InsertValueInSortedLinkedList() inserts a value in the sorted linked-list.
1071 %
1072 % The format of the InsertValueInSortedLinkedList method is:
1073 %
1074 % MagickBooleanType InsertValueInSortedLinkedList(ListInfo *list_info,
1075 % int (*compare)(const void *,const void *),void **replace,
1076 % const void *value)
1077 %
1078 % A description of each parameter follows:
1079 %
1080 % o list_info: the hashmap info.
1081 %
1082 % o index: the index.
1083 %
1084 % o compare: the compare method.
1085 %
1086 % o replace: return previous element here.
1087 %
1088 % o value: the value.
1089 %
1090 */
1092  LinkedListInfo *list_info,int (*compare)(const void *,const void *),
1093  void **replace,const void *value)
1094 {
1095  ElementInfo
1096  *element;
1097 
1098  register ElementInfo
1099  *next;
1100 
1101  register ssize_t
1102  i;
1103 
1104  assert(list_info != (LinkedListInfo *) NULL);
1105  assert(list_info->signature == MagickCoreSignature);
1106  if ((compare == (int (*)(const void *,const void *)) NULL) ||
1107  (value == (const void *) NULL))
1108  return(MagickFalse);
1109  if (list_info->elements == list_info->capacity)
1110  return(MagickFalse);
1111  next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
1112  if (next == (ElementInfo *) NULL)
1113  return(MagickFalse);
1114  next->value=(void *) value;
1115  element=(ElementInfo *) NULL;
1116  LockSemaphoreInfo(list_info->semaphore);
1117  next->next=list_info->head;
1118  while (next->next != (ElementInfo *) NULL)
1119  {
1120  i=(ssize_t) compare(value,next->next->value);
1121  if ((i < 0) || ((replace != (void **) NULL) && (i == 0)))
1122  {
1123  if (i == 0)
1124  {
1125  *replace=next->next->value;
1126  next->next=next->next->next;
1127  if (element != (ElementInfo *) NULL)
1129  element->next);
1130  list_info->elements--;
1131  }
1132  if (element != (ElementInfo *) NULL)
1133  element->next=next;
1134  else
1135  list_info->head=next;
1136  break;
1137  }
1138  element=next->next;
1139  next->next=next->next->next;
1140  }
1141  if (next->next == (ElementInfo *) NULL)
1142  {
1143  if (element != (ElementInfo *) NULL)
1144  element->next=next;
1145  else
1146  list_info->head=next;
1147  list_info->tail=next;
1148  }
1149  list_info->elements++;
1150  UnlockSemaphoreInfo(list_info->semaphore);
1151  return(MagickTrue);
1152 }
1153 
1154 /*
1155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1156 % %
1157 % %
1158 % %
1159 % I s H a s h m a p E m p t y %
1160 % %
1161 % %
1162 % %
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164 %
1165 % IsHashmapEmpty() returns MagickTrue if the hash-map is empty.
1166 %
1167 % The format of the IsHashmapEmpty method is:
1168 %
1169 % MagickBooleanType IsHashmapEmpty(const HashmapInfo *hashmap_info)
1170 %
1171 % A description of each parameter follows:
1172 %
1173 % o hashmap_info: the hashmap info.
1174 %
1175 */
1177 {
1178  assert(hashmap_info != (HashmapInfo *) NULL);
1179  assert(hashmap_info->signature == MagickCoreSignature);
1180  return(hashmap_info->entries == 0 ? MagickTrue : MagickFalse);
1181 }
1182 
1183 /*
1184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1185 % %
1186 % %
1187 % %
1188 % I s L i n k e d L i s t E m p t y %
1189 % %
1190 % %
1191 % %
1192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1193 %
1194 % IsLinkedListEmpty() returns MagickTrue if the linked-list is empty.
1195 %
1196 % The format of the IsLinkedListEmpty method is:
1197 %
1198 % MagickBooleanType IsLinkedListEmpty(LinkedListInfo *list_info)
1199 %
1200 % A description of each parameter follows:
1201 %
1202 % o list_info: the linked-list info.
1203 %
1204 */
1206  const LinkedListInfo *list_info)
1207 {
1208  assert(list_info != (LinkedListInfo *) NULL);
1209  assert(list_info->signature == MagickCoreSignature);
1210  return(list_info->elements == 0 ? MagickTrue : MagickFalse);
1211 }
1212 
1213 /*
1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1215 % %
1216 % %
1217 % %
1218 % L i n k e d L i s t T o A r r a y %
1219 % %
1220 % %
1221 % %
1222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1223 %
1224 % LinkedListToArray() converts the linked-list to an array.
1225 %
1226 % The format of the LinkedListToArray method is:
1227 %
1228 % MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
1229 % void **array)
1230 %
1231 % A description of each parameter follows:
1232 %
1233 % o list_info: the linked-list info.
1234 %
1235 % o array: the array.
1236 %
1237 */
1239  void **array)
1240 {
1241  register ElementInfo
1242  *next;
1243 
1244  register ssize_t
1245  i;
1246 
1247  assert(list_info != (LinkedListInfo *) NULL);
1248  assert(list_info->signature == MagickCoreSignature);
1249  if (array == (void **) NULL)
1250  return(MagickFalse);
1251  LockSemaphoreInfo(list_info->semaphore);
1252  next=list_info->head;
1253  for (i=0; next != (ElementInfo *) NULL; i++)
1254  {
1255  array[i]=next->value;
1256  next=next->next;
1257  }
1258  UnlockSemaphoreInfo(list_info->semaphore);
1259  return(MagickTrue);
1260 }
1261 
1262 /*
1263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1264 % %
1265 % %
1266 % %
1267 % N e w H a s h m a p %
1268 % %
1269 % %
1270 % %
1271 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1272 %
1273 % NewHashmap() returns a pointer to a HashmapInfo structure initialized
1274 % to default values. The capacity is an initial estimate. The hashmap will
1275 % increase capacity dynamically as the demand requires.
1276 %
1277 % The format of the NewHashmap method is:
1278 %
1279 % HashmapInfo *NewHashmap(const size_t capacity,
1280 % size_t (*hash)(const void *),
1281 % MagickBooleanType (*compare)(const void *,const void *),
1282 % void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1283 %
1284 % A description of each parameter follows:
1285 %
1286 % o capacity: the initial number entries in the hash-map: typically
1287 % SmallHashmapSize, MediumHashmapSize, or LargeHashmapSize. The
1288 % hashmap will dynamically increase its capacity on demand.
1289 %
1290 % o hash: the hash method, typically HashPointerType(), HashStringType(),
1291 % or HashStringInfoType().
1292 %
1293 % o compare: the compare method, typically NULL, CompareHashmapString(),
1294 % or CompareHashmapStringInfo().
1295 %
1296 % o relinquish_key: the key deallocation method, typically
1297 % RelinquishMagickMemory(), called whenever a key is removed from the
1298 % hash-map.
1299 %
1300 % o relinquish_value: the value deallocation method; typically
1301 % RelinquishMagickMemory(), called whenever a value object is removed from
1302 % the hash-map.
1303 %
1304 */
1305 MagickExport HashmapInfo *NewHashmap(const size_t capacity,
1306  size_t (*hash)(const void *),
1307  MagickBooleanType (*compare)(const void *,const void *),
1308  void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1309 {
1310  HashmapInfo
1311  *hashmap_info;
1312 
1313  hashmap_info=(HashmapInfo *) AcquireMagickMemory(sizeof(*hashmap_info));
1314  if (hashmap_info == (HashmapInfo *) NULL)
1315  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1316  (void) ResetMagickMemory(hashmap_info,0,sizeof(*hashmap_info));
1317  hashmap_info->hash=HashPointerType;
1318  if (hash != (size_t (*)(const void *)) NULL)
1319  hashmap_info->hash=hash;
1320  hashmap_info->compare=(MagickBooleanType (*)(const void *,const void *)) NULL;
1321  if (compare != (MagickBooleanType (*)(const void *,const void *)) NULL)
1322  hashmap_info->compare=compare;
1323  hashmap_info->relinquish_key=relinquish_key;
1324  hashmap_info->relinquish_value=relinquish_value;
1325  hashmap_info->entries=0;
1326  hashmap_info->capacity=capacity;
1327  hashmap_info->map=(LinkedListInfo **) NULL;
1328  if (~capacity >= 1UL)
1329  hashmap_info->map=(LinkedListInfo **) AcquireQuantumMemory((size_t)
1330  capacity+1UL,sizeof(*hashmap_info->map));
1331  if (hashmap_info->map == (LinkedListInfo **) NULL)
1332  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1333  (void) ResetMagickMemory(hashmap_info->map,0,(size_t) capacity*
1334  sizeof(*hashmap_info->map));
1335  hashmap_info->semaphore=AcquireSemaphoreInfo();
1336  hashmap_info->signature=MagickCoreSignature;
1337  return(hashmap_info);
1338 }
1339 
1340 /*
1341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1342 % %
1343 % %
1344 % %
1345 % N e w L i n k e d L i s t I n f o %
1346 % %
1347 % %
1348 % %
1349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1350 %
1351 % NewLinkedList() returns a pointer to a LinkedListInfo structure
1352 % initialized to default values.
1353 %
1354 % The format of the NewLinkedList method is:
1355 %
1356 % LinkedListInfo *NewLinkedList(const size_t capacity)
1357 %
1358 % A description of each parameter follows:
1359 %
1360 % o capacity: the maximum number of elements in the list.
1361 %
1362 */
1364 {
1366  *list_info;
1367 
1368  list_info=(LinkedListInfo *) AcquireMagickMemory(sizeof(*list_info));
1369  if (list_info == (LinkedListInfo *) NULL)
1370  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1371  (void) ResetMagickMemory(list_info,0,sizeof(*list_info));
1372  list_info->capacity=capacity == 0 ? (size_t) (~0) : capacity;
1373  list_info->elements=0;
1374  list_info->head=(ElementInfo *) NULL;
1375  list_info->tail=(ElementInfo *) NULL;
1376  list_info->next=(ElementInfo *) NULL;
1377  list_info->semaphore=AcquireSemaphoreInfo();
1378  list_info->signature=MagickCoreSignature;
1379  return(list_info);
1380 }
1381 
1382 /*
1383 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1384 % %
1385 % %
1386 % %
1387 % P u t E n t r y I n H a s h m a p %
1388 % %
1389 % %
1390 % %
1391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1392 %
1393 % PutEntryInHashmap() puts an entry in the hash-map. If the key already
1394 % exists in the map it is first removed.
1395 %
1396 % The format of the PutEntryInHashmap method is:
1397 %
1398 % MagickBooleanType PutEntryInHashmap(HashmapInfo *hashmap_info,
1399 % const void *key,const void *value)
1400 %
1401 % A description of each parameter follows:
1402 %
1403 % o hashmap_info: the hashmap info.
1404 %
1405 % o key: the key.
1406 %
1407 % o value: the value.
1408 %
1409 */
1410 
1412 {
1413 #define MaxCapacities 20
1414 
1415  const size_t
1416  capacities[MaxCapacities] =
1417  {
1418  17, 31, 61, 131, 257, 509, 1021, 2053, 4099, 8191, 16381, 32771,
1419  65537, 131071, 262147, 524287, 1048573, 2097143, 4194301, 8388617
1420  };
1421 
1422  ElementInfo
1423  *element;
1424 
1425  EntryInfo
1426  *entry;
1427 
1429  *map_info,
1430  **map;
1431 
1432  register ElementInfo
1433  *next;
1434 
1435  register ssize_t
1436  i;
1437 
1438  size_t
1439  capacity;
1440 
1441  /*
1442  Increase to the next prime capacity.
1443  */
1444  for (i=0; i < MaxCapacities; i++)
1445  if (hashmap_info->capacity < capacities[i])
1446  break;
1447  if (i >= (MaxCapacities-1))
1448  return(MagickFalse);
1449  capacity=capacities[i+1];
1450  map=(LinkedListInfo **) AcquireQuantumMemory((size_t) capacity+1UL,
1451  sizeof(*map));
1452  if (map == (LinkedListInfo **) NULL)
1453  return(MagickFalse);
1454  (void) ResetMagickMemory(map,0,(size_t) capacity*sizeof(*map));
1455  /*
1456  Copy entries to new hashmap with increased capacity.
1457  */
1458  for (i=0; i < (ssize_t) hashmap_info->capacity; i++)
1459  {
1461  *list_info;
1462 
1463  list_info=hashmap_info->map[i];
1464  if (list_info == (LinkedListInfo *) NULL)
1465  continue;
1466  LockSemaphoreInfo(list_info->semaphore);
1467  for (next=list_info->head; next != (ElementInfo *) NULL; )
1468  {
1469  element=next;
1470  next=next->next;
1471  entry=(EntryInfo *) element->value;
1472  map_info=map[entry->hash % capacity];
1473  if (map_info == (LinkedListInfo *) NULL)
1474  {
1475  map_info=NewLinkedList(0);
1476  map[entry->hash % capacity]=map_info;
1477  }
1478  map_info->next=element;
1479  element->next=map_info->head;
1480  map_info->head=element;
1481  map_info->elements++;
1482  }
1483  list_info->signature=(~MagickCoreSignature);
1484  UnlockSemaphoreInfo(list_info->semaphore);
1485  RelinquishSemaphoreInfo(&list_info->semaphore);
1486  list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
1487  }
1488  hashmap_info->map=(LinkedListInfo **) RelinquishMagickMemory(
1489  hashmap_info->map);
1490  hashmap_info->map=map;
1491  hashmap_info->capacity=capacity;
1492  return(MagickTrue);
1493 }
1494 
1496  const void *key,const void *value)
1497 {
1498  EntryInfo
1499  *entry,
1500  *next;
1501 
1503  *list_info;
1504 
1505  register size_t
1506  i;
1507 
1508  assert(hashmap_info != (HashmapInfo *) NULL);
1509  assert(hashmap_info->signature == MagickCoreSignature);
1510  if ((key == (void *) NULL) || (value == (void *) NULL))
1511  return(MagickFalse);
1512  next=(EntryInfo *) AcquireMagickMemory(sizeof(*next));
1513  if (next == (EntryInfo *) NULL)
1514  return(MagickFalse);
1515  LockSemaphoreInfo(hashmap_info->semaphore);
1516  next->hash=hashmap_info->hash(key);
1517  next->key=(void *) key;
1518  next->value=(void *) value;
1519  list_info=hashmap_info->map[next->hash % hashmap_info->capacity];
1520  if (list_info == (LinkedListInfo *) NULL)
1521  {
1522  list_info=NewLinkedList(0);
1523  hashmap_info->map[next->hash % hashmap_info->capacity]=list_info;
1524  }
1525  else
1526  {
1527  list_info->next=list_info->head;
1528  entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1529  for (i=0; entry != (EntryInfo *) NULL; i++)
1530  {
1531  if (entry->hash == next->hash)
1532  {
1534  compare;
1535 
1536  compare=MagickTrue;
1537  if (hashmap_info->compare !=
1538  (MagickBooleanType (*)(const void *,const void *)) NULL)
1539  compare=hashmap_info->compare(key,entry->key);
1540  if( compare != MagickFalse )
1541  {
1542  (void) RemoveElementFromLinkedList(list_info,i);
1543  if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
1544  entry->key=hashmap_info->relinquish_key(entry->key);
1545  if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
1546  entry->value=hashmap_info->relinquish_value(entry->value);
1547  entry=(EntryInfo *) RelinquishMagickMemory(entry);
1548  break;
1549  }
1550  }
1551  entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1552  }
1553  }
1554  if (InsertValueInLinkedList(list_info,0,next) == MagickFalse)
1555  {
1556  next=(EntryInfo *) RelinquishMagickMemory(next);
1557  UnlockSemaphoreInfo(hashmap_info->semaphore);
1558  return(MagickFalse);
1559  }
1560  if (list_info->elements >= (hashmap_info->capacity-1))
1561  if (IncreaseHashmapCapacity(hashmap_info) == MagickFalse)
1562  {
1563  UnlockSemaphoreInfo(hashmap_info->semaphore);
1564  return(MagickFalse);
1565  }
1566  hashmap_info->entries++;
1567  UnlockSemaphoreInfo(hashmap_info->semaphore);
1568  return(MagickTrue);
1569 }
1570 
1571 /*
1572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1573 % %
1574 % %
1575 % %
1576 % 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 %
1577 % %
1578 % %
1579 % %
1580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1581 %
1582 % RemoveElementByValueFromLinkedList() removes an element from the linked-list
1583 % by value.
1584 %
1585 % The format of the RemoveElementByValueFromLinkedList method is:
1586 %
1587 % void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
1588 % const void *value)
1589 %
1590 % A description of each parameter follows:
1591 %
1592 % o list_info: the list info.
1593 %
1594 % o value: the value.
1595 %
1596 */
1598  const void *value)
1599 {
1600  ElementInfo
1601  *next;
1602 
1603  assert(list_info != (LinkedListInfo *) NULL);
1604  assert(list_info->signature == MagickCoreSignature);
1605  if ((list_info->elements == 0) || (value == (const void *) NULL))
1606  return((void *) NULL);
1607  LockSemaphoreInfo(list_info->semaphore);
1608  if (value == list_info->head->value)
1609  {
1610  if (list_info->next == list_info->head)
1611  list_info->next=list_info->head->next;
1612  next=list_info->head;
1613  list_info->head=list_info->head->next;
1614  next=(ElementInfo *) RelinquishMagickMemory(next);
1615  }
1616  else
1617  {
1618  ElementInfo
1619  *element;
1620 
1621  next=list_info->head;
1622  while ((next->next != (ElementInfo *) NULL) &&
1623  (next->next->value != value))
1624  next=next->next;
1625  if (next->next == (ElementInfo *) NULL)
1626  {
1627  UnlockSemaphoreInfo(list_info->semaphore);
1628  return((void *) NULL);
1629  }
1630  element=next->next;
1631  next->next=element->next;
1632  if (element == list_info->tail)
1633  list_info->tail=next;
1634  if (list_info->next == element)
1635  list_info->next=element->next;
1636  element=(ElementInfo *) RelinquishMagickMemory(element);
1637  }
1638  list_info->elements--;
1639  UnlockSemaphoreInfo(list_info->semaphore);
1640  return((void *) value);
1641 }
1642 
1643 /*
1644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1645 % %
1646 % %
1647 % %
1648 % 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 %
1649 % %
1650 % %
1651 % %
1652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1653 %
1654 % RemoveElementFromLinkedList() removes an element from the linked-list at the
1655 % specified location.
1656 %
1657 % The format of the RemoveElementFromLinkedList method is:
1658 %
1659 % void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
1660 % const size_t index)
1661 %
1662 % A description of each parameter follows:
1663 %
1664 % o list_info: the linked-list info.
1665 %
1666 % o index: the index.
1667 %
1668 */
1670  const size_t index)
1671 {
1672  ElementInfo
1673  *next;
1674 
1675  register ssize_t
1676  i;
1677 
1678  void
1679  *value;
1680 
1681  assert(list_info != (LinkedListInfo *) NULL);
1682  assert(list_info->signature == MagickCoreSignature);
1683  if (index >= list_info->elements)
1684  return((void *) NULL);
1685  LockSemaphoreInfo(list_info->semaphore);
1686  if (index == 0)
1687  {
1688  if (list_info->next == list_info->head)
1689  list_info->next=list_info->head->next;
1690  value=list_info->head->value;
1691  next=list_info->head;
1692  list_info->head=list_info->head->next;
1693  next=(ElementInfo *) RelinquishMagickMemory(next);
1694  }
1695  else
1696  {
1697  ElementInfo
1698  *element;
1699 
1700  next=list_info->head;
1701  for (i=1; i < (ssize_t) index; i++)
1702  next=next->next;
1703  element=next->next;
1704  next->next=element->next;
1705  if (element == list_info->tail)
1706  list_info->tail=next;
1707  if (list_info->next == element)
1708  list_info->next=element->next;
1709  value=element->value;
1710  element=(ElementInfo *) RelinquishMagickMemory(element);
1711  }
1712  list_info->elements--;
1713  UnlockSemaphoreInfo(list_info->semaphore);
1714  return(value);
1715 }
1716 
1717 /*
1718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1719 % %
1720 % %
1721 % %
1722 % R e m o v e E n t r y F r o m H a s h m a p %
1723 % %
1724 % %
1725 % %
1726 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1727 %
1728 % RemoveEntryFromHashmap() removes an entry from the hash-map by its key.
1729 %
1730 % The format of the RemoveEntryFromHashmap method is:
1731 %
1732 % void *RemoveEntryFromHashmap(HashmapInfo *hashmap_info,void *key)
1733 %
1734 % A description of each parameter follows:
1735 %
1736 % o hashmap_info: the hashmap info.
1737 %
1738 % o key: the key.
1739 %
1740 */
1742  const void *key)
1743 {
1744  EntryInfo
1745  *entry;
1746 
1748  *list_info;
1749 
1750  register size_t
1751  i;
1752 
1753  size_t
1754  hash;
1755 
1756  void
1757  *value;
1758 
1759  assert(hashmap_info != (HashmapInfo *) NULL);
1760  assert(hashmap_info->signature == MagickCoreSignature);
1761  if (key == (const void *) NULL)
1762  return((void *) NULL);
1763  LockSemaphoreInfo(hashmap_info->semaphore);
1764  hash=hashmap_info->hash(key);
1765  list_info=hashmap_info->map[hash % hashmap_info->capacity];
1766  if (list_info != (LinkedListInfo *) NULL)
1767  {
1768  list_info->next=list_info->head;
1769  entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1770  for (i=0; entry != (EntryInfo *) NULL; i++)
1771  {
1772  if (entry->hash == hash)
1773  {
1775  compare;
1776 
1777  compare=MagickTrue;
1778  if (hashmap_info->compare !=
1779  (MagickBooleanType (*)(const void *,const void *)) NULL)
1780  compare=hashmap_info->compare(key,entry->key);
1781  if (compare != MagickFalse)
1782  {
1783  entry=(EntryInfo *) RemoveElementFromLinkedList(list_info,i);
1784  if (entry == (EntryInfo *) NULL)
1785  {
1786  UnlockSemaphoreInfo(hashmap_info->semaphore);
1787  return((void *) NULL);
1788  }
1789  if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
1790  entry->key=hashmap_info->relinquish_key(entry->key);
1791  value=entry->value;
1792  entry=(EntryInfo *) RelinquishMagickMemory(entry);
1793  hashmap_info->entries--;
1794  UnlockSemaphoreInfo(hashmap_info->semaphore);
1795  return(value);
1796  }
1797  }
1798  entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
1799  }
1800  }
1801  UnlockSemaphoreInfo(hashmap_info->semaphore);
1802  return((void *) NULL);
1803 }
1804 
1805 /*
1806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1807 % %
1808 % %
1809 % %
1810 % 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 %
1811 % %
1812 % %
1813 % %
1814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1815 %
1816 % RemoveLastElementFromLinkedList() removes the last element from the
1817 % linked-list.
1818 %
1819 % The format of the RemoveLastElementFromLinkedList method is:
1820 %
1821 % void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
1822 %
1823 % A description of each parameter follows:
1824 %
1825 % o list_info: the linked-list info.
1826 %
1827 */
1829 {
1830  void
1831  *value;
1832 
1833  assert(list_info != (LinkedListInfo *) NULL);
1834  assert(list_info->signature == MagickCoreSignature);
1835  if (list_info->elements == 0)
1836  return((void *) NULL);
1837  LockSemaphoreInfo(list_info->semaphore);
1838  if (list_info->next == list_info->tail)
1839  list_info->next=(ElementInfo *) NULL;
1840  if (list_info->elements == 1UL)
1841  {
1842  value=list_info->head->value;
1843  list_info->head=(ElementInfo *) NULL;
1844  list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
1845  }
1846  else
1847  {
1848  ElementInfo
1849  *next;
1850 
1851  value=list_info->tail->value;
1852  next=list_info->head;
1853  while (next->next != list_info->tail)
1854  next=next->next;
1855  list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
1856  list_info->tail=next;
1857  next->next=(ElementInfo *) NULL;
1858  }
1859  list_info->elements--;
1860  UnlockSemaphoreInfo(list_info->semaphore);
1861  return(value);
1862 }
1863 
1864 /*
1865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1866 % %
1867 % %
1868 % %
1869 % R e s e t H a s h m a p I t e r a t o r %
1870 % %
1871 % %
1872 % %
1873 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1874 %
1875 % ResetHashmapIterator() resets the hash-map iterator. Use it in conjunction
1876 % with GetNextKeyInHashmap() to iterate over all the keys in the hash-map.
1877 %
1878 % The format of the ResetHashmapIterator method is:
1879 %
1880 % ResetHashmapIterator(HashmapInfo *hashmap_info)
1881 %
1882 % A description of each parameter follows:
1883 %
1884 % o hashmap_info: the hashmap info.
1885 %
1886 */
1888 {
1889  assert(hashmap_info != (HashmapInfo *) NULL);
1890  assert(hashmap_info->signature == MagickCoreSignature);
1891  LockSemaphoreInfo(hashmap_info->semaphore);
1892  hashmap_info->next=0;
1893  hashmap_info->head_of_list=MagickFalse;
1894  UnlockSemaphoreInfo(hashmap_info->semaphore);
1895 }
1896 
1897 /*
1898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1899 % %
1900 % %
1901 % %
1902 % R e s e t L i n k e d L i s t I t e r a t o r %
1903 % %
1904 % %
1905 % %
1906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1907 %
1908 % ResetLinkedListIterator() resets the lined-list iterator. Use it in
1909 % conjunction with GetNextValueInLinkedList() to iterate over all the values
1910 % in the linked-list.
1911 %
1912 % The format of the ResetLinkedListIterator method is:
1913 %
1914 % ResetLinkedListIterator(LinkedListInfo *list_info)
1915 %
1916 % A description of each parameter follows:
1917 %
1918 % o list_info: the linked-list info.
1919 %
1920 */
1922 {
1923  assert(list_info != (LinkedListInfo *) NULL);
1924  assert(list_info->signature == MagickCoreSignature);
1925  LockSemaphoreInfo(list_info->semaphore);
1926  list_info->next=list_info->head;
1927  UnlockSemaphoreInfo(list_info->semaphore);
1928 }
MagickExport MagickBooleanType IsLinkedListEmpty(const LinkedListInfo *list_info)
Definition: hashmap.c:1205
MagickExport int CompareStringInfo(const StringInfo *target, const StringInfo *source)
Definition: string.c:363
SemaphoreInfo * semaphore
Definition: hashmap.c:119
MagickExport StringInfo * StringToStringInfo(const char *string)
Definition: string.c:2379
struct _EntryInfo EntryInfo
MagickExport MagickBooleanType LinkedListToArray(LinkedListInfo *list_info, void **array)
Definition: hashmap.c:1238
MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:449
MagickExport MagickBooleanType InsertValueInLinkedList(LinkedListInfo *list_info, const size_t index, const void *value)
Definition: hashmap.c:990
#define ThrowFatalException(severity, tag)
void *(* relinquish_key)(void *)
Definition: hashmap.c:104
MagickPrivate SignatureInfo * AcquireSignatureInfo(void)
MagickExport HashmapInfo * DestroyHashmap(HashmapInfo *hashmap_info)
Definition: hashmap.c:330
MagickExport SemaphoreInfo * AcquireSemaphoreInfo(void)
Definition: semaphore.c:191
void * value
Definition: hashmap.c:73
MagickExport void * GetValueFromHashmap(HashmapInfo *hashmap_info, const void *key)
Definition: hashmap.c:711
MagickExport void * GetNextValueInHashmap(HashmapInfo *hashmap_info)
Definition: hashmap.c:545
MagickBooleanType(* compare)(const void *, const void *)
Definition: hashmap.c:101
size_t(* hash)(const void *)
Definition: hashmap.c:98
size_t hash
Definition: hashmap.c:70
MagickExport void ResetLinkedListIterator(LinkedListInfo *list_info)
Definition: hashmap.c:1921
ElementInfo * tail
Definition: hashmap.c:84
MagickExport void * RemoveEntryFromHashmap(HashmapInfo *hashmap_info, const void *key)
Definition: hashmap.c:1741
MagickExport void ResetHashmapIterator(HashmapInfo *hashmap_info)
Definition: hashmap.c:1887
MagickExport size_t HashPointerType(const void *pointer)
Definition: hashmap.c:848
MagickExport MagickBooleanType InsertValueInSortedLinkedList(LinkedListInfo *list_info, int(*compare)(const void *, const void *), void **replace, const void *value)
Definition: hashmap.c:1091
size_t next
Definition: hashmap.c:108
MagickExport size_t HashStringType(const void *string)
Definition: hashmap.c:884
MagickExport size_t GetNumberOfEntriesInHashmap(const HashmapInfo *hashmap_info)
Definition: hashmap.c:647
#define MagickCoreSignature
MagickPrivate void FinalizeSignature(SignatureInfo *)
MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:292
MagickExport LinkedListInfo * DestroyLinkedList(LinkedListInfo *list_info, void *(*relinquish_value)(void *))
Definition: hashmap.c:398
MagickPrivate SignatureInfo * DestroySignatureInfo(SignatureInfo *)
Definition: signature.c:168
MagickExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition: string.c:1274
MagickExport void ClearLinkedList(LinkedListInfo *list_info, void *(*relinquish_value)(void *))
Definition: hashmap.c:204
void * value
Definition: hashmap.c:61
SemaphoreInfo * semaphore
Definition: hashmap.c:89
MagickBooleanType
Definition: magick-type.h:145
MagickExport void * RemoveElementFromLinkedList(LinkedListInfo *list_info, const size_t index)
Definition: hashmap.c:1669
MagickExport MagickBooleanType PutEntryInHashmap(HashmapInfo *hashmap_info, const void *key, const void *value)
Definition: hashmap.c:1495
MagickExport void * ResetMagickMemory(void *memory, int byte, const size_t size)
Definition: memory.c:1100
MagickExport StringInfo * DestroyStringInfo(StringInfo *string_info)
Definition: string.c:840
MagickExport MagickBooleanType IsHashmapEmpty(const HashmapInfo *hashmap_info)
Definition: hashmap.c:1176
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:540
struct _ElementInfo * next
Definition: hashmap.c:63
MagickExport void * GetNextKeyInHashmap(HashmapInfo *hashmap_info)
Definition: hashmap.c:484
MagickExport MagickBooleanType AppendValueToLinkedList(LinkedListInfo *list_info, const void *value)
Definition: hashmap.c:150
MagickExport void * GetLastValueInLinkedList(LinkedListInfo *list_info)
Definition: hashmap.c:447
MagickExport size_t HashStringInfoType(const void *string_info)
Definition: hashmap.c:937
MagickExport void * GetNextValueInLinkedList(LinkedListInfo *list_info)
Definition: hashmap.c:606
size_t signature
Definition: hashmap.c:92
MagickPrivate void UpdateSignature(SignatureInfo *, const StringInfo *)
Definition: signature.c:774
static MagickBooleanType IncreaseHashmapCapacity(HashmapInfo *hashmap_info)
Definition: hashmap.c:1411
size_t capacity
Definition: hashmap.c:108
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1408
ElementInfo * next
Definition: hashmap.c:84
void *(*)*(* relinquish_value)(void *)
Definition: hashmap.c:105
void * key
Definition: hashmap.c:73
MagickExport size_t GetNumberOfElementsInLinkedList(const LinkedListInfo *list_info)
Definition: hashmap.c:679
MagickExport MagickBooleanType CompareHashmapStringInfo(const void *target, const void *source)
Definition: hashmap.c:296
LinkedListInfo ** map
Definition: hashmap.c:116
MagickExport void * RemoveElementByValueFromLinkedList(LinkedListInfo *list_info, const void *value)
Definition: hashmap.c:1597
MagickExport void * AcquireMagickMemory(const size_t size)
Definition: memory.c:469
#define MaxCapacities
size_t signature
Definition: hashmap.c:122
MagickBooleanType head_of_list
Definition: hashmap.c:113
MagickExport void * RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
Definition: hashmap.c:1828
size_t elements
Definition: hashmap.c:80
ElementInfo * head
Definition: hashmap.c:84
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:969
size_t capacity
Definition: hashmap.c:80
size_t entries
Definition: hashmap.c:108
MagickPrivate const StringInfo * GetSignatureDigest(const SignatureInfo *)
Definition: signature.c:322
MagickExport HashmapInfo * NewHashmap(const size_t capacity, size_t(*hash)(const void *), MagickBooleanType(*compare)(const void *, const void *), void *(*relinquish_key)(void *), void *(*relinquish_value)(void *))
Definition: hashmap.c:1305
#define MagickExport
MagickExport LinkedListInfo * NewLinkedList(const size_t capacity)
Definition: hashmap.c:1363
MagickExport MagickBooleanType CompareHashmapString(const void *target, const void *source)
Definition: hashmap.c:258
MagickExport void * GetValueFromLinkedList(LinkedListInfo *list_info, const size_t index)
Definition: hashmap.c:788
MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition: semaphore.c:350
struct _ElementInfo ElementInfo