root / ImageMagick / branches / ImageMagick-6.3.5 / magick / hashmap.c

Revision 7906, 68.4 kB (checked in by cristy, 15 months ago)
Line 
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%                  ImageMagick Hash-map and Linked-list Methods               %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                               December 2002                                 %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2007 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 "magick/studio.h"
46#include "magick/exception.h"
47#include "magick/exception-private.h"
48#include "magick/hashmap.h"
49#include "magick/memory_.h"
50#include "magick/semaphore.h"
51#include "magick/signature.h"
52#include "magick/string_.h"
53
54/*
55  Typedef declarations.
56*/
57typedef struct _ElementInfo
58{
59  void
60    *value;
61
62  struct _ElementInfo
63    *next;
64} ElementInfo;
65
66typedef struct _EntryInfo
67{
68  size_t
69    hash;
70
71  void
72    *key,
73    *value;
74} EntryInfo;
75
76struct _LinkedListInfo
77{
78  unsigned long
79    capacity,
80    elements;
81
82  ElementInfo
83    *head,
84    *tail,
85    *next;
86
87  MagickBooleanType
88    debug;
89
90  SemaphoreInfo
91    *semaphore;
92
93  unsigned long
94    signature;
95};
96
97struct _HashmapInfo
98{
99  size_t
100    (*hash)(const void *);
101
102  MagickBooleanType
103    (*compare)(const void *,const void *);
104
105  void
106    *(*relinquish_key)(void *),
107    *(*relinquish_value)(void *);
108
109  unsigned long
110    capacity,
111    entries,
112    next;
113
114  MagickBooleanType
115    head_of_list;
116
117  LinkedListInfo
118    **map;
119
120  MagickBooleanType
121    debug;
122
123  SemaphoreInfo
124    *semaphore;
125
126  unsigned long
127    signature;
128};
129
130/*
131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132%                                                                             %
133%                                                                             %
134%                                                                             %
135%   A p p e n d V a l u e T o L i n k e d L i s t                             %
136%                                                                             %
137%                                                                             %
138%                                                                             %
139%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140%
141%  AppendValueToLinkedList() appends a value to the end of the linked-list.
142%
143%  The format of the AppendValueToLinkedList method is:
144%
145%      MagickBooleanType AppendValueToLinkedList(LinkedListInfo *list_info,
146%        const void *value)
147%
148%  A description of each parameter follows:
149%
150%    o list_info: The linked-list info.
151%
152%    o value: The value.
153%
154*/
155MagickExport MagickBooleanType AppendValueToLinkedList(
156  LinkedListInfo *list_info,const void *value)
157{
158  register ElementInfo
159    *next;
160
161  assert(list_info != (LinkedListInfo *) NULL);
162  assert(list_info->signature == MagickSignature);
163  list_info->debug=IsEventLogging();
164  if (list_info->debug != MagickFalse)
165    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
166  if (list_info->elements == list_info->capacity)
167    return(MagickFalse);
168  next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
169  if (next == (ElementInfo *) NULL)
170    return(MagickFalse);
171  next->value=(void *) value;
172  next->next=(ElementInfo *) NULL;
173  AcquireSemaphoreInfo(&list_info->semaphore);
174  if (list_info->next == (ElementInfo *) NULL)
175    list_info->next=next;
176  if (list_info->elements == 0)
177    list_info->head=next;
178  else
179    list_info->tail->next=next;
180  list_info->tail=next;
181  list_info->elements++;
182  RelinquishSemaphoreInfo(list_info->semaphore);
183  return(MagickTrue);
184}
185
186/*
187%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
188%                                                                             %
189%                                                                             %
190%                                                                             %
191%   C l e a r L i n k e d L i s t                                             %
192%                                                                             %
193%                                                                             %
194%                                                                             %
195%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196%
197%  ClearLinkedList() clears all the elements from the linked-list.
198%
199%  The format of the ClearLinkedList method is:
200%
201%      void ClearLinkedList(LinkedListInfo *list_info,
202%        void *(*relinquish_value)(void *))
203%
204%  A description of each parameter follows:
205%
206%    o list_info: The linked-list info.
207%
208%    o relinquish_value: The value deallocation method; typically
209%      RelinquishMagickMemory().
210%
211*/
212MagickExport void ClearLinkedList(LinkedListInfo *list_info,
213  void *(*relinquish_value)(void *))
214{
215  ElementInfo
216    *element;
217
218  register ElementInfo
219    *next;
220
221  assert(list_info != (LinkedListInfo *) NULL);
222  assert(list_info->signature == MagickSignature);
223  if (list_info->debug != MagickFalse)
224    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
225  AcquireSemaphoreInfo(&list_info->semaphore);
226  next=list_info->head;
227  while (next != (ElementInfo *) NULL)
228  {
229    if (relinquish_value != (void *(*)(void *)) NULL)
230      next->value=relinquish_value(next->value);
231    element=next;
232    next=next->next;
233    element=(ElementInfo *) RelinquishMagickMemory(element);
234  }
235  list_info->head=(ElementInfo *) NULL;
236  list_info->tail=(ElementInfo *) NULL;
237  list_info->next=(ElementInfo *) NULL;
238  list_info->elements=0;
239  RelinquishSemaphoreInfo(list_info->semaphore);
240}
241
242/*
243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244%                                                                             %
245%                                                                             %
246%                                                                             %
247%   C o m p a r e H a s h m a p S t r i n g                                   %
248%                                                                             %
249%                                                                             %
250%                                                                             %
251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252%
253%  Specify the CompareHashmapString() method in NewHashmap() to find an entry
254%  in a hash-map based on the contents of a string.
255%
256%  The format of the CompareHashmapString method is:
257%
258%      MagickBooleanType CompareHashmapString(const void *target,
259%        const void *source)
260%
261%  A description of each parameter follows:
262%
263%    o target: The target string.
264%
265%    o source: The source string.
266%
267*/
268MagickExport MagickBooleanType CompareHashmapString(const void *target,
269  const void *source)
270{
271  const char
272    *p,
273    *q;
274
275  p=(const char *) target;
276  q=(const char *) source;
277  return(LocaleCompare(p,q) == 0 ? MagickTrue : MagickFalse);
278}
279
280/*
281%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282%                                                                             %
283%                                                                             %
284%                                                                             %
285%   C o m p a r e H a s h m a p S t r i n g I n f o                           %
286%                                                                             %
287%                                                                             %
288%                                                                             %
289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290%
291%  Specify the CompareHashmapStringInfo() method in NewHashmap() to find an
292%  entry in a hash-map based on the contents of a string.
293%
294%  The format of the CompareHashmapStringInfo method is:
295%
296%      MagickBooleanType CompareHashmapStringInfo(const void *target,
297%        const void *source)
298%
299%  A description of each parameter follows:
300%
301%    o target: The target string.
302%
303%    o source: The source string.
304%
305*/
306MagickExport MagickBooleanType CompareHashmapStringInfo(const void *target,
307  const void *source)
308{
309  const StringInfo
310    *p,
311    *q;
312
313  p=(const StringInfo *) target;
314  q=(const StringInfo *) source;
315  return(CompareStringInfo(p,q) == 0 ? MagickTrue : MagickFalse);
316}
317
318/*
319%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
320%                                                                             %
321%                                                                             %
322%                                                                             %
323%   D e s t r o y H a s h m a p                                               %
324%                                                                             %
325%                                                                             %
326%                                                                             %
327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328%
329%  DestroyHashmap() frees the hash-map and all associated resources.
330%
331%  The format of the DestroyHashmap method is:
332%
333%      HashmapInfo *DestroyHashmap(HashmapInfo *hashmap_info)
334%
335%  A description of each parameter follows:
336%
337%    o hashmap_info: The hashmap info.
338%
339*/
340MagickExport HashmapInfo *DestroyHashmap(HashmapInfo *hashmap_info)
341{
342  LinkedListInfo
343    *list_info;
344
345  register EntryInfo
346    *entry;
347
348  register long
349    i;
350
351  assert(hashmap_info != (HashmapInfo *) NULL);
352  assert(hashmap_info->signature == MagickSignature);
353  if (hashmap_info->debug != MagickFalse)
354    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
355  AcquireSemaphoreInfo(&hashmap_info->semaphore);
356  for (i=0; i < (long) hashmap_info->capacity; i++)
357  {
358    list_info=hashmap_info->map[i];
359    if (list_info != (LinkedListInfo *) NULL)
360      {
361        list_info->next=list_info->head;
362        entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
363        while (entry != (EntryInfo *) NULL)
364        {
365          if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
366            entry->key=hashmap_info->relinquish_key(entry->key);
367          if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
368            entry->value=hashmap_info->relinquish_value(entry->value);
369          entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
370        }
371      }
372    if (list_info != (LinkedListInfo *) NULL)
373      list_info=DestroyLinkedList(list_info,RelinquishMagickMemory);
374  }
375  hashmap_info->map=(LinkedListInfo **) RelinquishMagickMemory(
376    hashmap_info->map);
377  hashmap_info->signature=(~MagickSignature);
378  RelinquishSemaphoreInfo(hashmap_info->semaphore);
379  hashmap_info->semaphore=DestroySemaphoreInfo(hashmap_info->semaphore);
380  hashmap_info=(HashmapInfo *) RelinquishMagickMemory(hashmap_info);
381  return(hashmap_info);
382}
383
384/*
385%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386%                                                                             %
387%                                                                             %
388%                                                                             %
389%   D e s t r o y L i n k e d L i s t                                         %
390%                                                                             %
391%                                                                             %
392%                                                                             %
393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394%
395%  DestroyLinkedList() frees the linked-list and all associated resources.
396%
397%  The format of the DestroyLinkedList method is:
398%
399%      LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
400%        void *(*relinquish_value)(void *))
401%
402%  A description of each parameter follows:
403%
404%    o list_info: The linked-list info.
405%
406%    o relinquish_value: The value deallocation method;  typically
407%      RelinquishMagickMemory().
408%
409*/
410MagickExport LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
411  void *(*relinquish_value)(void *))
412{
413  ElementInfo
414    *entry;
415
416  register ElementInfo
417    *next;
418
419  assert(list_info != (LinkedListInfo *) NULL);
420  assert(list_info->signature == MagickSignature);
421  if (list_info->debug != MagickFalse)
422    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
423  AcquireSemaphoreInfo(&list_info->semaphore);
424  for (next=list_info->head; next != (ElementInfo *) NULL; )
425  {
426    if (relinquish_value != (void *(*)(void *)) NULL)
427      next->value=relinquish_value(next->value);
428    entry=next;
429    next=next->next;
430    entry=(ElementInfo *) RelinquishMagickMemory(entry);
431  }
432  list_info->signature=(~MagickSignature);
433  RelinquishSemaphoreInfo(list_info->semaphore);
434  list_info->semaphore=DestroySemaphoreInfo(list_info->semaphore);
435  list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
436  return(list_info);
437}
438
439/*
440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441%                                                                             %
442%                                                                             %
443%                                                                             %
444%   G e t L a s t V a l u e I n L i n k e d L i s t                           %
445%                                                                             %
446%                                                                             %
447%                                                                             %
448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
449%
450%  GetLastValueInLinkedList() gets the last value in the linked-list.
451%
452%  The format of the GetLastValueInLinkedList method is:
453%
454%      void *GetLastValueInLinkedList(LinkedListInfo *list_info)
455%
456%  A description of each parameter follows:
457%
458%    o list_info: The linked_list info.
459%
460*/
461MagickExport void *GetLastValueInLinkedList(LinkedListInfo *list_info)
462{
463  void
464    *value;
465
466  assert(list_info != (LinkedListInfo *) NULL);
467  assert(list_info->signature == MagickSignature);
468  if (list_info->debug != MagickFalse)
469    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
470  if (list_info->elements == 0)
471    return((void *) NULL);
472  AcquireSemaphoreInfo(&list_info->semaphore);
473  value=list_info->tail->value;
474  RelinquishSemaphoreInfo(list_info->semaphore);
475  return(value);
476}
477
478/*
479%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
480%                                                                             %
481%                                                                             %
482%                                                                             %
483%   G e t N e x t K e y I n H a s h m a p                                     %
484%                                                                             %
485%                                                                             %
486%                                                                             %
487%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
488%
489%  GetNextKeyInHashmap() gets the next key in the hash-map.
490%
491%  The format of the GetNextKeyInHashmap method is:
492%
493%      void *GetNextKeyInHashmap(HashmapInfo *hashmap_info)
494%
495%  A description of each parameter follows:
496%
497%    o hashmap_info: The hashmap info.
498%
499*/
500MagickExport void *GetNextKeyInHashmap(HashmapInfo *hashmap_info)
501{
502  LinkedListInfo
503    *list_info;
504
505  register EntryInfo
506    *entry;
507
508  void
509    *key;
510
511  assert(hashmap_info != (HashmapInfo *) NULL);
512  assert(hashmap_info->signature == MagickSignature);
513  if (hashmap_info->debug != MagickFalse)
514    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
515  AcquireSemaphoreInfo(&hashmap_info->semaphore);
516  while (hashmap_info->next < hashmap_info->capacity)
517  {
518    list_info=hashmap_info->map[hashmap_info->next];
519    if (list_info != (LinkedListInfo *) NULL)
520      {
521        if (hashmap_info->head_of_list == MagickFalse)
522          {
523            list_info->next=list_info->head;
524            hashmap_info->head_of_list=MagickTrue;
525          }
526        entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
527        if (entry != (EntryInfo *) NULL)
528          {
529            key=entry->key;
530            RelinquishSemaphoreInfo(hashmap_info->semaphore);
531            return(key);
532          }
533        hashmap_info->head_of_list=MagickFalse;
534      }
535    hashmap_info->next++;
536  }
537  RelinquishSemaphoreInfo(hashmap_info->semaphore);
538  return((void *) NULL);
539}
540
541/*
542%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
543%                                                                             %
544%                                                                             %
545%                                                                             %
546%   G e t N e x t V a l u e I n H a s h m a p                                 %
547%                                                                             %
548%                                                                             %
549%                                                                             %
550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551%
552%  GetNextValueInHashmap() gets the next value in the hash-map.
553%
554%  The format of the GetNextValueInHashmap method is:
555%
556%      void *GetNextValueInHashmap(HashmapInfo *hashmap_info)
557%
558%  A description of each parameter follows:
559%
560%    o hashmap_info: The hashmap info.
561%
562*/
563MagickExport void *GetNextValueInHashmap(HashmapInfo *hashmap_info)
564{
565  LinkedListInfo
566    *list_info;
567
568  register EntryInfo
569    *entry;
570
571  void
572    *value;
573
574  assert(hashmap_info != (HashmapInfo *) NULL);
575  assert(hashmap_info->signature == MagickSignature);
576  if (hashmap_info->debug != MagickFalse)
577    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
578  AcquireSemaphoreInfo(&hashmap_info->semaphore);
579  while (hashmap_info->next < hashmap_info->capacity)
580  {
581    list_info=hashmap_info->map[hashmap_info->next];
582    if (list_info != (LinkedListInfo *) NULL)
583      {
584        if (hashmap_info->head_of_list == MagickFalse)
585          {
586            list_info->next=list_info->head;
587            hashmap_info->head_of_list=MagickTrue;
588          }
589        entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
590        if (entry != (EntryInfo *) NULL)
591          {
592            value=entry->value;
593            RelinquishSemaphoreInfo(hashmap_info->semaphore);
594            return(value);
595          }
596        hashmap_info->head_of_list=MagickFalse;
597      }
598    hashmap_info->next++;
599  }
600  RelinquishSemaphoreInfo(hashmap_info->semaphore);
601  return((void *) NULL);
602}
603
604/*
605%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
606%                                                                             %
607%                                                                             %
608%                                                                             %
609%   G e t N e x t V a l u e I n L i n k e d L i s t                           %
610%                                                                             %
611%                                                                             %
612%                                                                             %
613%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
614%
615%  GetNextValueInLinkedList() gets the next value in the linked-list.
616%
617%  The format of the GetNextValueInLinkedList method is:
618%
619%      void *GetNextValueInLinkedList(LinkedListInfo *list_info)
620%
621%  A description of each parameter follows:
622%
623%    o list_info: The linked-list info.
624%
625*/
626MagickExport void *GetNextValueInLinkedList(LinkedListInfo *list_info)
627{
628  void
629    *value;
630
631  assert(list_info != (LinkedListInfo *) NULL);
632  assert(list_info->signature == MagickSignature);
633  if (list_info->debug != MagickFalse)
634    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
635  if (list_info->next == (ElementInfo *) NULL)
636    return((void *) NULL);
637  AcquireSemaphoreInfo(&list_info->semaphore);
638  value=list_info->next->value;
639  list_info->next=list_info->next->next;
640  RelinquishSemaphoreInfo(list_info->semaphore);
641  return(value);
642}
643
644/*
645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646%                                                                             %
647%                                                                             %
648%                                                                             %
649%   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                     %
650%                                                                             %
651%                                                                             %
652%                                                                             %
653%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654%
655%  GetNumberOfEntriesInHashmap() returns the number of entries in the hash-map.
656%
657%  The format of the GetNumberOfEntriesInHashmap method is:
658%
659%      unsigned long GetNumberOfEntriesInHashmap(const HashmapInfo *hashmap_info)
660%
661%  A description of each parameter follows:
662%
663%    o hashmap_info: The hashmap info.
664%
665*/
666MagickExport unsigned long GetNumberOfEntriesInHashmap(
667  const HashmapInfo *hashmap_info)
668{
669  assert(hashmap_info != (HashmapInfo *) NULL);
670  assert(hashmap_info->signature == MagickSignature);
671  if (hashmap_info->debug != MagickFalse)
672    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
673  return(hashmap_info->entries);
674}
675
676/*
677%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
678%                                                                             %
679%                                                                             %
680%                                                                             %
681%   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             %
682%                                                                             %
683%                                                                             %
684%                                                                             %
685%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
686%
687%  GetNumberOfElementsInLinkedList() returns the number of entries in the
688%  linked-list.
689%
690%  The format of the GetNumberOfElementsInLinkedList method is:
691%
692%      unsigned long GetNumberOfElementsInLinkedList(
693%        const LinkedListInfo *list_info)
694%
695%  A description of each parameter follows:
696%
697%    o list_info: The linked-list info.
698%
699*/
700MagickExport unsigned long GetNumberOfElementsInLinkedList(
701  const LinkedListInfo *list_info)
702{
703  assert(list_info != (LinkedListInfo *) NULL);
704  assert(list_info->signature == MagickSignature);
705  if (list_info->debug != MagickFalse)
706    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
707  return(list_info->elements);
708}
709
710/*
711%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
712%                                                                             %
713%                                                                             %
714%                                                                             %
715%   G e t V a l u e F r o m H a s h m a p                                     %
716%                                                                             %
717%                                                                             %
718%                                                                             %
719%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
720%
721%  GetValueFromHashmap() gets an entry from the hash-map by its key.
722%
723%  The format of the GetValueFromHashmap method is:
724%
725%      void *GetValueFromHashmap(HashmapInfo *hashmap_info,const void *key)
726%
727%  A description of each parameter follows:
728%
729%    o hashmap_info: The hashmap info.
730%
731%    o key: The key.
732%
733*/
734MagickExport void *GetValueFromHashmap(HashmapInfo *hashmap_info,
735  const void *key)
736{
737  LinkedListInfo
738    *list_info;
739
740  register EntryInfo
741    *entry;
742
743  size_t
744    hash;
745
746  void
747    *value;
748
749  assert(hashmap_info != (HashmapInfo *) NULL);
750  assert(hashmap_info->signature == MagickSignature);
751  if (hashmap_info->debug != MagickFalse)
752    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
753  if (key == (const void *) NULL)
754    return((void *) NULL);
755  AcquireSemaphoreInfo(&hashmap_info->semaphore);
756  hash=hashmap_info->hash(key);
757  list_info=hashmap_info->map[hash % hashmap_info->capacity];
758  if (list_info != (LinkedListInfo *) NULL)
759    {
760      list_info->next=list_info->head;
761      entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
762      while (entry != (EntryInfo *) NULL)
763      {
764        if (entry->hash == hash)
765          {
766            MagickBooleanType
767              compare;
768
769            compare=MagickTrue;
770            if (hashmap_info->compare !=
771                (MagickBooleanType (*)(const void *,const void *)) NULL)
772              compare=hashmap_info->compare(key,entry->key);
773            if (compare == MagickTrue)
774              {
775                value=entry->value;
776                RelinquishSemaphoreInfo(hashmap_info->semaphore);
777                return(value);
778              }
779          }
780        entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
781      }
782    }
783  RelinquishSemaphoreInfo(hashmap_info->semaphore);
784  return((void *) NULL);
785}
786
787/*
788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789%                                                                             %
790%                                                                             %
791%                                                                             %
792%   G e t V a l u e F r o m L i n k e d L i s t                               %
793%                                                                             %
794%                                                                             %
795%                                                                             %
796%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
797%
798%  GetValueFromLinkedList() gets a value from the linked-list at the specified
799%  location.
800%
801%  The format of the GetValueFromLinkedList method is:
802%
803%      void *GetValueFromLinkedList(LinkedListInfo *list_info,
804%        const unsigned long index)
805%
806%  A description of each parameter follows:
807%
808%    o list_info: The linked_list info.
809%
810%    o index: The list index.
811%
812*/
813MagickExport void *GetValueFromLinkedList(LinkedListInfo *list_info,
814  const unsigned long index)
815{
816  register ElementInfo
817    *next;
818
819  register long
820    i;
821
822  void
823    *value;
824
825  assert(list_info != (LinkedListInfo *) NULL);
826  assert(list_info->signature == MagickSignature);
827  if (list_info->debug != MagickFalse)
828    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
829  if (index >= list_info->elements)
830    return((void *) NULL);
831  AcquireSemaphoreInfo(&list_info->semaphore);
832  if (index == 0)
833    {
834      value=list_info->head->value;
835      RelinquishSemaphoreInfo(list_info->semaphore);
836      return(value);
837    }
838  if (index == (list_info->elements-1))
839    {
840      value=list_info->tail->value;
841      RelinquishSemaphoreInfo(list_info->semaphore);
842      return(value);
843    }
844  next=list_info->head;
845  for (i=0; i < (long) index; i++)
846    next=next->next;
847  value=next->value;
848  RelinquishSemaphoreInfo(list_info->semaphore);
849  return(value);
850}
851
852/*
853%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
854%                                                                             %
855%                                                                             %
856%                                                                             %
857%   H a s h P o i n t e r T y p e                                             %
858%                                                                             %
859%                                                                             %
860%                                                                             %
861%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
862%
863%  Specify the HashPointerType() method in NewHashmap() to find an entry
864%  in a hash-map based on the address of a pointer.
865%
866%  The format of the HashPointerType method is:
867%
868%      size_t HashPointerType(const void *pointer)
869%
870%  A description of each parameter follows:
871%
872%    o pointer: compute the hash entry location from this pointer address.
873%
874*/
875MagickExport size_t HashPointerType(const void *pointer)
876{
877  size_t
878    hash;
879
880  hash=(size_t) pointer;
881  hash+=(~(hash << 9));
882  hash^=(hash >> 14);
883  hash+=(hash << 4);
884  hash^=(hash >> 10);
885  return(hash);
886}
887
888/*
889%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
890%                                                                             %
891%                                                                             %
892%                                                                             %
893%   H a s h S t r i n g T y p e                                               %
894%                                                                             %
895%                                                                             %
896%                                                                             %
897%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
898%
899%  Specify the HashStringType() method in NewHashmap() to find an entry
900%  in a hash-map based on the contents of a string.
901%
902%  The format of the HashStringType method is:
903%
904%      size_t HashStringType(const void *string)
905%
906%  A description of each parameter follows:
907%
908%    o string: compute the hash entry location from this string.
909%
910*/
911MagickExport size_t HashStringType(const void *string)
912{
913  register long
914    i;
915
916  SignatureInfo
917    signature_info;
918
919  size_t
920    hash;
921
922  GetSignatureInfo(&signature_info);
923  UpdateSignature(&signature_info,(const unsigned char *) string,
924    strlen((const char *) string));
925  FinalizeSignature(&signature_info);
926  hash=0;
927  for (i=0; i < 8; i++)
928    hash^=signature_info.digest[i];
929  return(hash);
930}
931
932/*
933%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934%                                                                             %
935%                                                                             %
936%                                                                             %
937%   H a s h S t r i n g I n f o T y p e                                       %
938%                                                                             %
939%                                                                             %
940%                                                                             %
941%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942%
943%  Specify the HashStringInfoType() method in NewHashmap() to find an entry
944%  in a hash-map based on the contents of a string.
945%
946%  The format of the HashStringInfoType method is:
947%
948%      size_t HashStringInfoType(const void *string)
949%
950%  A description of each parameter follows:
951%
952%    o string: compute the hash entry location from this string.
953%
954*/
955MagickExport size_t HashStringInfoType(const void *string)
956{