hashmap.c

Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                H   H   AAA   SSSSS  H   H  M   M   AAA   PPPP               %
00007 %                H   H  A   A  SS     H   H  MM MM  A   A  P   P              %
00008 %                HHHHH  AAAAA   SSS   HHHHH  M M M  AAAAA  PPPP               %
00009 %                H   H  A   A     SS  H   H  M   M  A   A  P                  %
00010 %                H   H  A   A  SSSSS  H   H  M   M  A   A  P                  %
00011 %                                                                             %
00012 %                                                                             %
00013 %                  MagickCore Hash-map and Linked-list Methods                %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                                John Cristy                                  %
00017 %                               December 2002                                 %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %  This module implements the standard handy hash and linked-list methods for
00037 %  storing and retrieving large numbers of data elements.  It is loosely based
00038 %  on the Java implementation of these algorithms.
00039 %
00040 */
00041 
00042 /*
00043   Include declarations.
00044 */
00045 #include "magick/studio.h"
00046 #include "magick/exception.h"
00047 #include "magick/exception-private.h"
00048 #include "magick/hashmap.h"
00049 #include "magick/memory_.h"
00050 #include "magick/semaphore.h"
00051 #include "magick/signature-private.h"
00052 #include "magick/string_.h"
00053 
00054 /*
00055   Typedef declarations.
00056 */
00057 typedef struct _ElementInfo
00058 {
00059   void
00060     *value;
00061 
00062   struct _ElementInfo
00063     *next;
00064 } ElementInfo;
00065 
00066 typedef struct _EntryInfo
00067 {
00068   size_t
00069     hash;
00070 
00071   void
00072     *key,
00073     *value;
00074 } EntryInfo;
00075 
00076 struct _LinkedListInfo
00077 {
00078   unsigned long
00079     capacity,
00080     elements;
00081 
00082   ElementInfo
00083     *head,
00084     *tail,
00085     *next;
00086 
00087   MagickBooleanType
00088     debug;
00089 
00090   SemaphoreInfo
00091     *semaphore;
00092 
00093   unsigned long
00094     signature;
00095 };
00096 
00097 struct _HashmapInfo
00098 {
00099   size_t
00100     (*hash)(const void *);
00101 
00102   MagickBooleanType
00103     (*compare)(const void *,const void *);
00104 
00105   void
00106     *(*relinquish_key)(void *),
00107     *(*relinquish_value)(void *);
00108 
00109   unsigned long
00110     capacity,
00111     entries,
00112     next;
00113 
00114   MagickBooleanType
00115     head_of_list;
00116 
00117   LinkedListInfo
00118     **map;
00119 
00120   MagickBooleanType
00121     debug;
00122 
00123   SemaphoreInfo
00124     *semaphore;
00125 
00126   unsigned long
00127     signature;
00128 };
00129 
00130 /*
00131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00132 %                                                                             %
00133 %                                                                             %
00134 %                                                                             %
00135 %   A p p e n d V a l u e T o L i n k e d L i s t                             %
00136 %                                                                             %
00137 %                                                                             %
00138 %                                                                             %
00139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00140 %
00141 %  AppendValueToLinkedList() appends a value to the end of the linked-list.
00142 %
00143 %  The format of the AppendValueToLinkedList method is:
00144 %
00145 %      MagickBooleanType AppendValueToLinkedList(LinkedListInfo *list_info,
00146 %        const void *value)
00147 %
00148 %  A description of each parameter follows:
00149 %
00150 %    o list_info: the linked-list info.
00151 %
00152 %    o value: the value.
00153 %
00154 */
00155 MagickExport MagickBooleanType AppendValueToLinkedList(
00156   LinkedListInfo *list_info,const void *value)
00157 {
00158   register ElementInfo
00159     *next;
00160 
00161   assert(list_info != (LinkedListInfo *) NULL);
00162   assert(list_info->signature == MagickSignature);
00163   list_info->debug=IsEventLogging();
00164   if (list_info->debug != MagickFalse)
00165     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00166   if (list_info->elements == list_info->capacity)
00167     return(MagickFalse);
00168   next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
00169   if (next == (ElementInfo *) NULL)
00170     return(MagickFalse);
00171   next->value=(void *) value;
00172   next->next=(ElementInfo *) NULL;
00173   (void) LockSemaphoreInfo(list_info->semaphore);
00174   if (list_info->next == (ElementInfo *) NULL)
00175     list_info->next=next;
00176   if (list_info->elements == 0)
00177     list_info->head=next;
00178   else
00179     list_info->tail->next=next;
00180   list_info->tail=next;
00181   list_info->elements++;
00182   (void) UnlockSemaphoreInfo(list_info->semaphore);
00183   return(MagickTrue);
00184 }
00185 
00186 /*
00187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00188 %                                                                             %
00189 %                                                                             %
00190 %                                                                             %
00191 %   C l e a r L i n k e d L i s t                                             %
00192 %                                                                             %
00193 %                                                                             %
00194 %                                                                             %
00195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00196 %
00197 %  ClearLinkedList() clears all the elements from the linked-list.
00198 %
00199 %  The format of the ClearLinkedList method is:
00200 %
00201 %      void ClearLinkedList(LinkedListInfo *list_info,
00202 %        void *(*relinquish_value)(void *))
00203 %
00204 %  A description of each parameter follows:
00205 %
00206 %    o list_info: the linked-list info.
00207 %
00208 %    o relinquish_value: the value deallocation method; typically
00209 %      RelinquishMagickMemory().
00210 %
00211 */
00212 MagickExport void ClearLinkedList(LinkedListInfo *list_info,
00213   void *(*relinquish_value)(void *))
00214 {
00215   ElementInfo
00216     *element;
00217 
00218   register ElementInfo
00219     *next;
00220 
00221   assert(list_info != (LinkedListInfo *) NULL);
00222   assert(list_info->signature == MagickSignature);
00223   if (list_info->debug != MagickFalse)
00224     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00225   (void) LockSemaphoreInfo(list_info->semaphore);
00226   next=list_info->head;
00227   while (next != (ElementInfo *) NULL)
00228   {
00229     if (relinquish_value != (void *(*)(void *)) NULL)
00230       next->value=relinquish_value(next->value);
00231     element=next;
00232     next=next->next;
00233     element=(ElementInfo *) RelinquishMagickMemory(element);
00234   }
00235   list_info->head=(ElementInfo *) NULL;
00236   list_info->tail=(ElementInfo *) NULL;
00237   list_info->next=(ElementInfo *) NULL;
00238   list_info->elements=0;
00239   (void) UnlockSemaphoreInfo(list_info->semaphore);
00240 }
00241 
00242 /*
00243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00244 %                                                                             %
00245 %                                                                             %
00246 %                                                                             %
00247 %   C o m p a r e H a s h m a p S t r i n g                                   %
00248 %                                                                             %
00249 %                                                                             %
00250 %                                                                             %
00251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00252 %
00253 %  Specify the CompareHashmapString() method in NewHashmap() to find an entry
00254 %  in a hash-map based on the contents of a string.
00255 %
00256 %  The format of the CompareHashmapString method is:
00257 %
00258 %      MagickBooleanType CompareHashmapString(const void *target,
00259 %        const void *source)
00260 %
00261 %  A description of each parameter follows:
00262 %
00263 %    o target: the target string.
00264 %
00265 %    o source: the source string.
00266 %
00267 */
00268 MagickExport MagickBooleanType CompareHashmapString(const void *target,
00269   const void *source)
00270 {
00271   const char
00272     *p,
00273     *q;
00274 
00275   p=(const char *) target;
00276   q=(const char *) source;
00277   return(LocaleCompare(p,q) == 0 ? MagickTrue : MagickFalse);
00278 }
00279 
00280 /*
00281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00282 %                                                                             %
00283 %                                                                             %
00284 %                                                                             %
00285 %   C o m p a r e H a s h m a p S t r i n g I n f o                           %
00286 %                                                                             %
00287 %                                                                             %
00288 %                                                                             %
00289 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00290 %
00291 %  Specify the CompareHashmapStringInfo() method in NewHashmap() to find an
00292 %  entry in a hash-map based on the contents of a string.
00293 %
00294 %  The format of the CompareHashmapStringInfo method is:
00295 %
00296 %      MagickBooleanType CompareHashmapStringInfo(const void *target,
00297 %        const void *source)
00298 %
00299 %  A description of each parameter follows:
00300 %
00301 %    o target: the target string.
00302 %
00303 %    o source: the source string.
00304 %
00305 */
00306 MagickExport MagickBooleanType CompareHashmapStringInfo(const void *target,
00307   const void *source)
00308 {
00309   const StringInfo
00310     *p,
00311     *q;
00312 
00313   p=(const StringInfo *) target;
00314   q=(const StringInfo *) source;
00315   return(CompareStringInfo(p,q) == 0 ? MagickTrue : MagickFalse);
00316 }
00317 
00318 /*
00319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00320 %                                                                             %
00321 %                                                                             %
00322 %                                                                             %
00323 %   D e s t r o y H a s h m a p                                               %
00324 %                                                                             %
00325 %                                                                             %
00326 %                                                                             %
00327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00328 %
00329 %  DestroyHashmap() frees the hash-map and all associated resources.
00330 %
00331 %  The format of the DestroyHashmap method is:
00332 %
00333 %      HashmapInfo *DestroyHashmap(HashmapInfo *hashmap_info)
00334 %
00335 %  A description of each parameter follows:
00336 %
00337 %    o hashmap_info: the hashmap info.
00338 %
00339 */
00340 MagickExport HashmapInfo *DestroyHashmap(HashmapInfo *hashmap_info)
00341 {
00342   LinkedListInfo
00343     *list_info;
00344 
00345   register EntryInfo
00346     *entry;
00347 
00348   register long
00349     i;
00350 
00351   assert(hashmap_info != (HashmapInfo *) NULL);
00352   assert(hashmap_info->signature == MagickSignature);
00353   if (hashmap_info->debug != MagickFalse)
00354     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00355   (void) LockSemaphoreInfo(hashmap_info->semaphore);
00356   for (i=0; i < (long) hashmap_info->capacity; i++)
00357   {
00358     list_info=hashmap_info->map[i];
00359     if (list_info != (LinkedListInfo *) NULL)
00360       {
00361         list_info->next=list_info->head;
00362         entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
00363         while (entry != (EntryInfo *) NULL)
00364         {
00365           if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
00366             entry->key=hashmap_info->relinquish_key(entry->key);
00367           if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
00368             entry->value=hashmap_info->relinquish_value(entry->value);
00369           entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
00370         }
00371       }
00372     if (list_info != (LinkedListInfo *) NULL)
00373       list_info=DestroyLinkedList(list_info,RelinquishMagickMemory);
00374   }
00375   hashmap_info->map=(LinkedListInfo **) RelinquishMagickMemory(
00376     hashmap_info->map);
00377   hashmap_info->signature=(~MagickSignature);
00378   (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
00379   DestroySemaphoreInfo(&hashmap_info->semaphore);
00380   hashmap_info=(HashmapInfo *) RelinquishMagickMemory(hashmap_info);
00381   return(hashmap_info);
00382 }
00383 
00384 /*
00385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00386 %                                                                             %
00387 %                                                                             %
00388 %                                                                             %
00389 %   D e s t r o y L i n k e d L i s t                                         %
00390 %                                                                             %
00391 %                                                                             %
00392 %                                                                             %
00393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00394 %
00395 %  DestroyLinkedList() frees the linked-list and all associated resources.
00396 %
00397 %  The format of the DestroyLinkedList method is:
00398 %
00399 %      LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
00400 %        void *(*relinquish_value)(void *))
00401 %
00402 %  A description of each parameter follows:
00403 %
00404 %    o list_info: the linked-list info.
00405 %
00406 %    o relinquish_value: the value deallocation method;  typically
00407 %      RelinquishMagickMemory().
00408 %
00409 */
00410 MagickExport LinkedListInfo *DestroyLinkedList(LinkedListInfo *list_info,
00411   void *(*relinquish_value)(void *))
00412 {
00413   ElementInfo
00414     *entry;
00415 
00416   register ElementInfo
00417     *next;
00418 
00419   assert(list_info != (LinkedListInfo *) NULL);
00420   assert(list_info->signature == MagickSignature);
00421   if (list_info->debug != MagickFalse)
00422     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00423   (void) LockSemaphoreInfo(list_info->semaphore);
00424   for (next=list_info->head; next != (ElementInfo *) NULL; )
00425   {
00426     if (relinquish_value != (void *(*)(void *)) NULL)
00427       next->value=relinquish_value(next->value);
00428     entry=next;
00429     next=next->next;
00430     entry=(ElementInfo *) RelinquishMagickMemory(entry);
00431   }
00432   list_info->signature=(~MagickSignature);
00433   (void) UnlockSemaphoreInfo(list_info->semaphore);
00434   DestroySemaphoreInfo(&list_info->semaphore);
00435   list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
00436   return(list_info);
00437 }
00438 
00439 /*
00440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00441 %                                                                             %
00442 %                                                                             %
00443 %                                                                             %
00444 %   G e t L a s t V a l u e I n L i n k e d L i s t                           %
00445 %                                                                             %
00446 %                                                                             %
00447 %                                                                             %
00448 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00449 %
00450 %  GetLastValueInLinkedList() gets the last value in the linked-list.
00451 %
00452 %  The format of the GetLastValueInLinkedList method is:
00453 %
00454 %      void *GetLastValueInLinkedList(LinkedListInfo *list_info)
00455 %
00456 %  A description of each parameter follows:
00457 %
00458 %    o list_info: the linked_list info.
00459 %
00460 */
00461 MagickExport void *GetLastValueInLinkedList(LinkedListInfo *list_info)
00462 {
00463   void
00464     *value;
00465 
00466   assert(list_info != (LinkedListInfo *) NULL);
00467   assert(list_info->signature == MagickSignature);
00468   if (list_info->debug != MagickFalse)
00469     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00470   if (list_info->elements == 0)
00471     return((void *) NULL);
00472   (void) LockSemaphoreInfo(list_info->semaphore);
00473   value=list_info->tail->value;
00474   (void) UnlockSemaphoreInfo(list_info->semaphore);
00475   return(value);
00476 }
00477 
00478 /*
00479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00480 %                                                                             %
00481 %                                                                             %
00482 %                                                                             %
00483 %   G e t N e x t K e y I n H a s h m a p                                     %
00484 %                                                                             %
00485 %                                                                             %
00486 %                                                                             %
00487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00488 %
00489 %  GetNextKeyInHashmap() gets the next key in the hash-map.
00490 %
00491 %  The format of the GetNextKeyInHashmap method is:
00492 %
00493 %      void *GetNextKeyInHashmap(HashmapInfo *hashmap_info)
00494 %
00495 %  A description of each parameter follows:
00496 %
00497 %    o hashmap_info: the hashmap info.
00498 %
00499 */
00500 MagickExport void *GetNextKeyInHashmap(HashmapInfo *hashmap_info)
00501 {
00502   LinkedListInfo
00503     *list_info;
00504 
00505   register EntryInfo
00506     *entry;
00507 
00508   void
00509     *key;
00510 
00511   assert(hashmap_info != (HashmapInfo *) NULL);
00512   assert(hashmap_info->signature == MagickSignature);
00513   if (hashmap_info->debug != MagickFalse)
00514     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00515   (void) LockSemaphoreInfo(hashmap_info->semaphore);
00516   while (hashmap_info->next < hashmap_info->capacity)
00517   {
00518     list_info=hashmap_info->map[hashmap_info->next];
00519     if (list_info != (LinkedListInfo *) NULL)
00520       {
00521         if (hashmap_info->head_of_list == MagickFalse)
00522           {
00523             list_info->next=list_info->head;
00524             hashmap_info->head_of_list=MagickTrue;
00525           }
00526         entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
00527         if (entry != (EntryInfo *) NULL)
00528           {
00529             key=entry->key;
00530             (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
00531             return(key);
00532           }
00533         hashmap_info->head_of_list=MagickFalse;
00534       }
00535     hashmap_info->next++;
00536   }
00537   (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
00538   return((void *) NULL);
00539 }
00540 
00541 /*
00542 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00543 %                                                                             %
00544 %                                                                             %
00545 %                                                                             %
00546 %   G e t N e x t V a l u e I n H a s h m a p                                 %
00547 %                                                                             %
00548 %                                                                             %
00549 %                                                                             %
00550 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00551 %
00552 %  GetNextValueInHashmap() gets the next value in the hash-map.
00553 %
00554 %  The format of the GetNextValueInHashmap method is:
00555 %
00556 %      void *GetNextValueInHashmap(HashmapInfo *hashmap_info)
00557 %
00558 %  A description of each parameter follows:
00559 %
00560 %    o hashmap_info: the hashmap info.
00561 %
00562 */
00563 MagickExport void *GetNextValueInHashmap(HashmapInfo *hashmap_info)
00564 {
00565   LinkedListInfo
00566     *list_info;
00567 
00568   register EntryInfo
00569     *entry;
00570 
00571   void
00572     *value;
00573 
00574   assert(hashmap_info != (HashmapInfo *) NULL);
00575   assert(hashmap_info->signature == MagickSignature);
00576   if (hashmap_info->debug != MagickFalse)
00577     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00578   (void) LockSemaphoreInfo(hashmap_info->semaphore);
00579   while (hashmap_info->next < hashmap_info->capacity)
00580   {
00581     list_info=hashmap_info->map[hashmap_info->next];
00582     if (list_info != (LinkedListInfo *) NULL)
00583       {
00584         if (hashmap_info->head_of_list == MagickFalse)
00585           {
00586             list_info->next=list_info->head;
00587             hashmap_info->head_of_list=MagickTrue;
00588           }
00589         entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
00590         if (entry != (EntryInfo *) NULL)
00591           {
00592             value=entry->value;
00593             (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
00594             return(value);
00595           }
00596         hashmap_info->head_of_list=MagickFalse;
00597       }
00598     hashmap_info->next++;
00599   }
00600   (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
00601   return((void *) NULL);
00602 }
00603 
00604 /*
00605 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00606 %                                                                             %
00607 %                                                                             %
00608 %                                                                             %
00609 %   G e t N e x t V a l u e I n L i n k e d L i s t                           %
00610 %                                                                             %
00611 %                                                                             %
00612 %                                                                             %
00613 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00614 %
00615 %  GetNextValueInLinkedList() gets the next value in the linked-list.
00616 %
00617 %  The format of the GetNextValueInLinkedList method is:
00618 %
00619 %      void *GetNextValueInLinkedList(LinkedListInfo *list_info)
00620 %
00621 %  A description of each parameter follows:
00622 %
00623 %    o list_info: the linked-list info.
00624 %
00625 */
00626 MagickExport void *GetNextValueInLinkedList(LinkedListInfo *list_info)
00627 {
00628   void
00629     *value;
00630 
00631   assert(list_info != (LinkedListInfo *) NULL);
00632   assert(list_info->signature == MagickSignature);
00633   if (list_info->debug != MagickFalse)
00634     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00635   (void) LockSemaphoreInfo(list_info->semaphore);
00636   if (list_info->next == (ElementInfo *) NULL)
00637     {
00638       (void) UnlockSemaphoreInfo(list_info->semaphore);
00639       return((void *) NULL);
00640     }
00641   value=list_info->next->value;
00642   list_info->next=list_info->next->next;
00643   (void) UnlockSemaphoreInfo(list_info->semaphore);
00644   return(value);
00645 }
00646 
00647 /*
00648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00649 %                                                                             %
00650 %                                                                             %
00651 %                                                                             %
00652 %   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                     %
00653 %                                                                             %
00654 %                                                                             %
00655 %                                                                             %
00656 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00657 %
00658 %  GetNumberOfEntriesInHashmap() returns the number of entries in the hash-map.
00659 %
00660 %  The format of the GetNumberOfEntriesInHashmap method is:
00661 %
00662 %      unsigned long GetNumberOfEntriesInHashmap(const HashmapInfo *hashmap_info)
00663 %
00664 %  A description of each parameter follows:
00665 %
00666 %    o hashmap_info: the hashmap info.
00667 %
00668 */
00669 MagickExport unsigned long GetNumberOfEntriesInHashmap(
00670   const HashmapInfo *hashmap_info)
00671 {
00672   assert(hashmap_info != (HashmapInfo *) NULL);
00673   assert(hashmap_info->signature == MagickSignature);
00674   if (hashmap_info->debug != MagickFalse)
00675     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00676   return(hashmap_info->entries);
00677 }
00678 
00679 /*
00680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00681 %                                                                             %
00682 %                                                                             %
00683 %                                                                             %
00684 %   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             %
00685 %                                                                             %
00686 %                                                                             %
00687 %                                                                             %
00688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00689 %
00690 %  GetNumberOfElementsInLinkedList() returns the number of entries in the
00691 %  linked-list.
00692 %
00693 %  The format of the GetNumberOfElementsInLinkedList method is:
00694 %
00695 %      unsigned long GetNumberOfElementsInLinkedList(
00696 %        const LinkedListInfo *list_info)
00697 %
00698 %  A description of each parameter follows:
00699 %
00700 %    o list_info: the linked-list info.
00701 %
00702 */
00703 MagickExport unsigned long GetNumberOfElementsInLinkedList(
00704   const LinkedListInfo *list_info)
00705 {
00706   assert(list_info != (LinkedListInfo *) NULL);
00707   assert(list_info->signature == MagickSignature);
00708   if (list_info->debug != MagickFalse)
00709     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00710   return(list_info->elements);
00711 }
00712 
00713 /*
00714 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00715 %                                                                             %
00716 %                                                                             %
00717 %                                                                             %
00718 %   G e t V a l u e F r o m H a s h m a p                                     %
00719 %                                                                             %
00720 %                                                                             %
00721 %                                                                             %
00722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00723 %
00724 %  GetValueFromHashmap() gets an entry from the hash-map by its key.
00725 %
00726 %  The format of the GetValueFromHashmap method is:
00727 %
00728 %      void *GetValueFromHashmap(HashmapInfo *hashmap_info,const void *key)
00729 %
00730 %  A description of each parameter follows:
00731 %
00732 %    o hashmap_info: the hashmap info.
00733 %
00734 %    o key: the key.
00735 %
00736 */
00737 MagickExport void *GetValueFromHashmap(HashmapInfo *hashmap_info,
00738   const void *key)
00739 {
00740   LinkedListInfo
00741     *list_info;
00742 
00743   register EntryInfo
00744     *entry;
00745 
00746   size_t
00747     hash;
00748 
00749   void
00750     *value;
00751 
00752   assert(hashmap_info != (HashmapInfo *) NULL);
00753   assert(hashmap_info->signature == MagickSignature);
00754   if (hashmap_info->debug != MagickFalse)
00755     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00756   if (key == (const void *) NULL)
00757     return((void *) NULL);
00758   (void) LockSemaphoreInfo(hashmap_info->semaphore);
00759   hash=hashmap_info->hash(key);
00760   list_info=hashmap_info->map[hash % hashmap_info->capacity];
00761   if (list_info != (LinkedListInfo *) NULL)
00762     {
00763       list_info->next=list_info->head;
00764       entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
00765       while (entry != (EntryInfo *) NULL)
00766       {
00767         if (entry->hash == hash)
00768           {
00769             MagickBooleanType
00770               compare;
00771 
00772             compare=MagickTrue;
00773             if (hashmap_info->compare !=
00774                 (MagickBooleanType (*)(const void *,const void *)) NULL)
00775               compare=hashmap_info->compare(key,entry->key);
00776             if (compare == MagickTrue)
00777               {
00778                 value=entry->value;
00779                 (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
00780                 return(value);
00781               }
00782           }
00783         entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
00784       }
00785     }
00786   (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
00787   return((void *) NULL);
00788 }
00789 
00790 /*
00791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00792 %                                                                             %
00793 %                                                                             %
00794 %                                                                             %
00795 %   G e t V a l u e F r o m L i n k e d L i s t                               %
00796 %                                                                             %
00797 %                                                                             %
00798 %                                                                             %
00799 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00800 %
00801 %  GetValueFromLinkedList() gets a value from the linked-list at the specified
00802 %  location.
00803 %
00804 %  The format of the GetValueFromLinkedList method is:
00805 %
00806 %      void *GetValueFromLinkedList(LinkedListInfo *list_info,
00807 %        const unsigned long index)
00808 %
00809 %  A description of each parameter follows:
00810 %
00811 %    o list_info: the linked_list info.
00812 %
00813 %    o index: the list index.
00814 %
00815 */
00816 MagickExport void *GetValueFromLinkedList(LinkedListInfo *list_info,
00817   const unsigned long index)
00818 {
00819   register ElementInfo
00820     *next;
00821 
00822   register long
00823     i;
00824 
00825   void
00826     *value;
00827 
00828   assert(list_info != (LinkedListInfo *) NULL);
00829   assert(list_info->signature == MagickSignature);
00830   if (list_info->debug != MagickFalse)
00831     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00832   if (index >= list_info->elements)
00833     return((void *) NULL);
00834   (void) LockSemaphoreInfo(list_info->semaphore);
00835   if (index == 0)
00836     {
00837       value=list_info->head->value;
00838       (void) UnlockSemaphoreInfo(list_info->semaphore);
00839       return(value);
00840     }
00841   if (index == (list_info->elements-1))
00842     {
00843       value=list_info->tail->value;
00844       (void) UnlockSemaphoreInfo(list_info->semaphore);
00845       return(value);
00846     }
00847   next=list_info->head;
00848   for (i=0; i < (long) index; i++)
00849     next=next->next;
00850   value=next->value;
00851   (void) UnlockSemaphoreInfo(list_info->semaphore);
00852   return(value);
00853 }
00854 
00855 /*
00856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00857 %                                                                             %
00858 %                                                                             %
00859 %                                                                             %
00860 %   H a s h P o i n t e r T y p e                                             %
00861 %                                                                             %
00862 %                                                                             %
00863 %                                                                             %
00864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00865 %
00866 %  Specify the HashPointerType() method in NewHashmap() to find an entry
00867 %  in a hash-map based on the address of a pointer.
00868 %
00869 %  The format of the HashPointerType method is:
00870 %
00871 %      size_t HashPointerType(const void *pointer)
00872 %
00873 %  A description of each parameter follows:
00874 %
00875 %    o pointer: compute the hash entry location from this pointer address.
00876 %
00877 */
00878 MagickExport size_t HashPointerType(const void *pointer)
00879 {
00880   size_t
00881     hash;
00882 
00883   hash=(size_t) pointer;
00884   hash+=(~(hash << 9));
00885   hash^=(hash >> 14);
00886   hash+=(hash << 4);
00887   hash^=(hash >> 10);
00888   return(hash);
00889 }
00890 
00891 /*
00892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00893 %                                                                             %
00894 %                                                                             %
00895 %                                                                             %
00896 %   H a s h S t r i n g T y p e                                               %
00897 %                                                                             %
00898 %                                                                             %
00899 %                                                                             %
00900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00901 %
00902 %  Specify the HashStringType() method in NewHashmap() to find an entry
00903 %  in a hash-map based on the contents of a string.
00904 %
00905 %  The format of the HashStringType method is:
00906 %
00907 %      size_t HashStringType(const void *string)
00908 %
00909 %  A description of each parameter follows:
00910 %
00911 %    o string: compute the hash entry location from this string.
00912 %
00913 */
00914 MagickExport size_t HashStringType(const void *string)
00915 {
00916   const unsigned char
00917     *digest;
00918 
00919   register long
00920     i;
00921 
00922   SignatureInfo
00923     *signature_info;
00924 
00925   size_t
00926     hash;
00927 
00928   StringInfo
00929     *signature;
00930 
00931   signature_info=AcquireSignatureInfo();
00932   signature=StringToStringInfo((const char *) string);
00933   UpdateSignature(signature_info,signature);
00934   FinalizeSignature(signature_info);
00935   digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
00936   hash=0;
00937   for (i=0; i < 8; i++)
00938     hash^=digest[i];
00939   signature=DestroyStringInfo(signature);
00940   signature_info=DestroySignatureInfo(signature_info);
00941   return(hash);
00942 }
00943 
00944 /*
00945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00946 %                                                                             %
00947 %                                                                             %
00948 %                                                                             %
00949 %   H a s h S t r i n g I n f o T y p e                                       %
00950 %                                                                             %
00951 %                                                                             %
00952 %                                                                             %
00953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00954 %
00955 %  Specify the HashStringInfoType() method in NewHashmap() to find an entry
00956 %  in a hash-map based on the contents of a string.
00957 %
00958 %  The format of the HashStringInfoType method is:
00959 %
00960 %      size_t HashStringInfoType(const void *string_info)
00961 %
00962 %  A description of each parameter follows:
00963 %
00964 %    o string_info: compute the hash entry location from this string.
00965 %
00966 */
00967 MagickExport size_t HashStringInfoType(const void *string_info)
00968 {
00969   const unsigned char
00970     *digest;
00971 
00972   register long
00973     i;
00974 
00975   SignatureInfo
00976     *signature_info;
00977 
00978   size_t
00979     hash;
00980 
00981   signature_info=AcquireSignatureInfo();
00982   UpdateSignature(signature_info,(const StringInfo *) string_info);
00983   FinalizeSignature(signature_info);
00984   digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
00985   hash=0;
00986   for (i=0; i < 8; i++)
00987     hash^=digest[i];
00988   signature_info=DestroySignatureInfo(signature_info);
00989   return(hash);
00990 }
00991 
00992 /*
00993 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00994 %                                                                             %
00995 %                                                                             %
00996 %                                                                             %
00997 %   I n s e r t V a l u e I n L i n k e d L i s t                             %
00998 %                                                                             %
00999 %                                                                             %
01000 %                                                                             %
01001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01002 %
01003 %  InsertValueInLinkedList() inserts an element in the linked-list at the
01004 %  specified location.
01005 %
01006 %  The format of the InsertValueInLinkedList method is:
01007 %
01008 %      MagickBooleanType InsertValueInLinkedList(ListInfo *list_info,
01009 %        const unsigned long index,const void *value)
01010 %
01011 %  A description of each parameter follows:
01012 %
01013 %    o list_info: the hashmap info.
01014 %
01015 %    o index: the index.
01016 %
01017 %    o value: the value.
01018 %
01019 */
01020 MagickExport MagickBooleanType InsertValueInLinkedList(
01021   LinkedListInfo *list_info,const unsigned long index,const void *value)
01022 {
01023   register ElementInfo
01024     *next;
01025 
01026   register long
01027     i;
01028 
01029   assert(list_info != (LinkedListInfo *) NULL);
01030   assert(list_info->signature == MagickSignature);
01031   if (list_info->debug != MagickFalse)
01032     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01033   if (value == (const void *) NULL)
01034     return(MagickFalse);
01035   if ((index > list_info->elements) ||
01036       (list_info->elements == list_info->capacity))
01037     return(MagickFalse);
01038   next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
01039   if (next == (ElementInfo *) NULL)
01040     return(MagickFalse);
01041   next->value=(void *) value;
01042   next->next=(ElementInfo *) NULL;
01043   (void) LockSemaphoreInfo(list_info->semaphore);
01044   if (list_info->elements == 0)
01045     {
01046       if (list_info->next == (ElementInfo *) NULL)
01047         list_info->next=next;
01048       list_info->head=next;
01049       list_info->tail=next;
01050     }
01051   else
01052     {
01053       if (index == 0)
01054         {
01055           if (list_info->next == list_info->head)
01056             list_info->next=next;
01057           next->next=list_info->head;
01058           list_info->head=next;
01059         }
01060       else
01061         if (index == list_info->elements)
01062           {
01063             if (list_info->next == (ElementInfo *) NULL)
01064               list_info->next=next;
01065             list_info->tail->next=next;
01066             list_info->tail=next;
01067           }
01068         else
01069           {
01070             ElementInfo
01071               *element;
01072 
01073             element=list_info->head;
01074             next->next=element->next;
01075             for (i=1; i < (long) index; i++)
01076             {
01077               element=element->next;
01078               next->next=element->next;
01079             }
01080             next=next->next;
01081             element->next=next;
01082             if (list_info->next == next->next)
01083               list_info->next=next;
01084           }
01085     }
01086   list_info->elements++;
01087   (void) UnlockSemaphoreInfo(list_info->semaphore);
01088   return(MagickTrue);
01089 }
01090 
01091 /*
01092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01093 %                                                                             %
01094 %                                                                             %
01095 %                                                                             %
01096 %   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                 %
01097 %                                                                             %
01098 %                                                                             %
01099 %                                                                             %
01100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01101 %
01102 %  InsertValueInSortedLinkedList() inserts a value in the sorted linked-list.
01103 %
01104 %  The format of the InsertValueInSortedLinkedList method is:
01105 %
01106 %      MagickBooleanType InsertValueInSortedLinkedList(ListInfo *list_info,
01107 %        int (*compare)(const void *,const void *),void **replace,
01108 %        const void *value)
01109 %
01110 %  A description of each parameter follows:
01111 %
01112 %    o list_info: the hashmap info.
01113 %
01114 %    o index: the index.
01115 %
01116 %    o compare: the compare method.
01117 %
01118 %    o replace: return previous element here.
01119 %
01120 %    o value: the value.
01121 %
01122 */
01123 MagickExport MagickBooleanType InsertValueInSortedLinkedList(
01124   LinkedListInfo *list_info,int (*compare)(const void *,const void *),
01125   void **replace,const void *value)
01126 {
01127   ElementInfo
01128     *element;
01129 
01130   register ElementInfo
01131     *next;
01132 
01133   register long
01134     i;
01135 
01136   assert(list_info != (LinkedListInfo *) NULL);
01137   assert(list_info->signature == MagickSignature);
01138   if (list_info->debug != MagickFalse)
01139     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01140   if ((compare == (int (*)(const void *,const void *)) NULL) ||
01141       (value == (const void *) NULL))
01142     return(MagickFalse);
01143   if (list_info->elements == list_info->capacity)
01144     return(MagickFalse);
01145   next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
01146   if (next == (ElementInfo *) NULL)
01147     return(MagickFalse);
01148   next->value=(void *) value;
01149   element=(ElementInfo *) NULL;
01150   (void) LockSemaphoreInfo(list_info->semaphore);
01151   next->next=list_info->head;
01152   while (next->next != (ElementInfo *) NULL)
01153   {
01154     i=compare(value,next->next->value);
01155     if ((i < 0) || ((replace != (void **) NULL) && (i == 0)))
01156       {
01157         if (i == 0)
01158           {
01159             *replace=next->next->value;
01160             next->next=next->next->next;
01161             if (element != (ElementInfo *) NULL)
01162               element->next=(ElementInfo *) RelinquishMagickMemory(
01163                 element->next);
01164             list_info->elements--;
01165           }
01166         if (element != (ElementInfo *) NULL)
01167           element->next=next;
01168         else
01169           list_info->head=next;
01170         break;
01171       }
01172     element=next->next;
01173     next->next=next->next->next;
01174   }
01175   if (next->next == (ElementInfo *) NULL)
01176     {
01177       if (element != (ElementInfo *) NULL)
01178         element->next=next;
01179       else
01180         list_info->head=next;
01181       list_info->tail=next;
01182     }
01183   list_info->elements++;
01184   (void) UnlockSemaphoreInfo(list_info->semaphore);
01185   return(MagickTrue);
01186 }
01187 
01188 /*
01189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01190 %                                                                             %
01191 %                                                                             %
01192 %                                                                             %
01193 %   I s H a s h m a p E m p t y                                               %
01194 %                                                                             %
01195 %                                                                             %
01196 %                                                                             %
01197 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01198 %
01199 %  IsHashmapEmpty() returns MagickTrue if the hash-map is empty.
01200 %
01201 %  The format of the IsHashmapEmpty method is:
01202 %
01203 %      MagickBooleanType IsHashmapEmpty(const HashmapInfo *hashmap_info)
01204 %
01205 %  A description of each parameter follows:
01206 %
01207 %    o hashmap_info: the hashmap info.
01208 %
01209 */
01210 MagickExport MagickBooleanType IsHashmapEmpty(const HashmapInfo *hashmap_info)
01211 {
01212   assert(hashmap_info != (HashmapInfo *) NULL);
01213   assert(hashmap_info->signature == MagickSignature);
01214   if (hashmap_info->debug != MagickFalse)
01215     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01216   return(hashmap_info->entries == 0 ? MagickTrue : MagickFalse);
01217 }
01218 
01219 /*
01220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01221 %                                                                             %
01222 %                                                                             %
01223 %                                                                             %
01224 %   I s L i n k e d L i s t E m p t y                                         %
01225 %                                                                             %
01226 %                                                                             %
01227 %                                                                             %
01228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01229 %
01230 %  IsLinkedListEmpty() returns MagickTrue if the linked-list is empty.
01231 %
01232 %  The format of the IsLinkedListEmpty method is:
01233 %
01234 %      MagickBooleanType IsLinkedListEmpty(LinkedListInfo *list_info)
01235 %
01236 %  A description of each parameter follows:
01237 %
01238 %    o list_info: the linked-list info.
01239 %
01240 */
01241 MagickExport MagickBooleanType IsLinkedListEmpty(
01242   const LinkedListInfo *list_info)
01243 {
01244   assert(list_info != (LinkedListInfo *) NULL);
01245   assert(list_info->signature == MagickSignature);
01246   if (list_info->debug != MagickFalse)
01247     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01248   return(list_info->elements == 0 ? MagickTrue : MagickFalse);
01249 }
01250 
01251 /*
01252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01253 %                                                                             %
01254 %                                                                             %
01255 %                                                                             %
01256 %   L i n k e d L i s t T o A r r a y                                         %
01257 %                                                                             %
01258 %                                                                             %
01259 %                                                                             %
01260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01261 %
01262 %  LinkedListToArray() converts the linked-list to an array.
01263 %
01264 %  The format of the LinkedListToArray method is:
01265 %
01266 %      MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
01267 %        void **array)
01268 %
01269 %  A description of each parameter follows:
01270 %
01271 %    o list_info: the linked-list info.
01272 %
01273 %    o array: the array.
01274 %
01275 */
01276 MagickExport MagickBooleanType LinkedListToArray(LinkedListInfo *list_info,
01277   void **array)
01278 {
01279   register ElementInfo
01280     *next;
01281 
01282   register long
01283     i;
01284 
01285   assert(list_info != (LinkedListInfo *) NULL);
01286   assert(list_info->signature == MagickSignature);
01287   if (list_info->debug != MagickFalse)
01288     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01289   if (array == (void **) NULL)
01290     return(MagickFalse);
01291   (void) LockSemaphoreInfo(list_info->semaphore);
01292   next=list_info->head;
01293   for (i=0; next != (ElementInfo *) NULL; i++)
01294   {
01295     array[i]=next->value;
01296     next=next->next;
01297   }
01298   (void) UnlockSemaphoreInfo(list_info->semaphore);
01299   return(MagickTrue);
01300 }
01301 
01302 /*
01303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01304 %                                                                             %
01305 %                                                                             %
01306 %                                                                             %
01307 %   N e w H a s h m a p                                                       %
01308 %                                                                             %
01309 %                                                                             %
01310 %                                                                             %
01311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01312 %
01313 %  NewHashmap() returns a pointer to a HashmapInfo structure initialized
01314 %  to default values.  The capacity is an initial estimate.  The hashmap will
01315 %  increase capacity dynamically as the demand requires.
01316 %
01317 %  The format of the NewHashmap method is:
01318 %
01319 %      HashmapInfo *NewHashmap(const unsigned long capacity,
01320 %        size_t (*hash)(const void *),
01321 %        MagickBooleanType (*compare)(const void *,const void *),
01322 %        void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
01323 %
01324 %  A description of each parameter follows:
01325 %
01326 %    o capacity: the initial number entries in the hash-map: typically
01327 %      SmallHashmapSize, MediumHashmapSize, or LargeHashmapSize.  The
01328 %      hashmap will dynamically increase its capacity on demand.
01329 %
01330 %    o hash: the hash method, typically HashPointerType(), HashStringType(),
01331 %      or HashStringInfoType().
01332 %
01333 %    o compare: the compare method, typically NULL, CompareHashmapString(),
01334 %      or CompareHashmapStringInfo().
01335 %
01336 %    o relinquish_key: the key deallocation method, typically
01337 %      RelinquishMagickMemory(), called whenever a key is removed from the
01338 %      hash-map.
01339 %
01340 %    o relinquish_value: the value deallocation method;  typically
01341 %      RelinquishMagickMemory(), called whenever a value object is removed from
01342 %      the hash-map.
01343 %
01344 */
01345 MagickExport HashmapInfo *NewHashmap(const unsigned long capacity,
01346   size_t (*hash)(const void *),
01347   MagickBooleanType (*compare)(const void *,const void *),
01348   void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
01349 {
01350   HashmapInfo
01351     *hashmap_info;
01352 
01353   hashmap_info=(HashmapInfo *) AcquireMagickMemory(sizeof(*hashmap_info));
01354   if (hashmap_info == (HashmapInfo *) NULL)
01355     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01356   (void) ResetMagickMemory(hashmap_info,0,sizeof(*hashmap_info));
01357   hashmap_info->hash=HashPointerType;
01358   if (hash != (size_t (*)(const void *)) NULL)
01359     hashmap_info->hash=hash;
01360   hashmap_info->compare=(MagickBooleanType (*)(const void *,const void *)) NULL;
01361   if (compare != (MagickBooleanType (*)(const void *,const void *)) NULL)
01362     hashmap_info->compare=compare;
01363   hashmap_info->relinquish_key=relinquish_key;
01364   hashmap_info->relinquish_value=relinquish_value;
01365   hashmap_info->entries=0;
01366   hashmap_info->capacity=capacity;
01367   hashmap_info->map=(LinkedListInfo **) NULL;
01368   if (~capacity >= 1UL)
01369     hashmap_info->map=(LinkedListInfo **) AcquireQuantumMemory((size_t)
01370       capacity+1UL,sizeof(*hashmap_info->map));
01371   if (hashmap_info->map == (LinkedListInfo **) NULL)
01372     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01373   (void) ResetMagickMemory(hashmap_info->map,0,(size_t) capacity*
01374     sizeof(*hashmap_info->map));
01375   hashmap_info->debug=IsEventLogging();
01376   hashmap_info->semaphore=AllocateSemaphoreInfo();
01377   hashmap_info->signature=MagickSignature;
01378   return(hashmap_info);
01379 }
01380 
01381 /*
01382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01383 %                                                                             %
01384 %                                                                             %
01385 %                                                                             %
01386 %   N e w L i n k e d L i s t I n f o                                         %
01387 %                                                                             %
01388 %                                                                             %
01389 %                                                                             %
01390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01391 %
01392 %  NewLinkedList() returns a pointer to a LinkedListInfo structure
01393 %  initialized to default values.
01394 %
01395 %  The format of the NewLinkedList method is:
01396 %
01397 %      LinkedListInfo *NewLinkedList(const unsigned long capacity)
01398 %
01399 %  A description of each parameter follows:
01400 %
01401 %    o capacity: the maximum number of elements in the list.
01402 %
01403 */
01404 MagickExport LinkedListInfo *NewLinkedList(const unsigned long capacity)
01405 {
01406   LinkedListInfo
01407     *list_info;
01408 
01409   list_info=(LinkedListInfo *) AcquireMagickMemory(sizeof(*list_info));
01410   if (list_info == (LinkedListInfo *) NULL)
01411     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
01412   (void) ResetMagickMemory(list_info,0,sizeof(*list_info));
01413   list_info->capacity=capacity == 0 ? (unsigned long) (~0) : capacity;
01414   list_info->elements=0;
01415   list_info->head=(ElementInfo *) NULL;
01416   list_info->tail=(ElementInfo *) NULL;
01417   list_info->next=(ElementInfo *) NULL;
01418   list_info->debug=MagickFalse;
01419   list_info->semaphore=AllocateSemaphoreInfo();
01420   list_info->signature=MagickSignature;
01421   return(list_info);
01422 }
01423 
01424 /*
01425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01426 %                                                                             %
01427 %                                                                             %
01428 %                                                                             %
01429 %   P u t E n t r y I n H a s h m a p                                         %
01430 %                                                                             %
01431 %                                                                             %
01432 %                                                                             %
01433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01434 %
01435 %  PutEntryInHashmap() puts an entry in the hash-map.  If the key already
01436 %  exists in the map it is first removed.
01437 %
01438 %  The format of the PutEntryInHashmap method is:
01439 %
01440 %      MagickBooleanType PutEntryInHashmap(HashmapInfo *hashmap_info,
01441 %        const void *key,const void *value)
01442 %
01443 %  A description of each parameter follows:
01444 %
01445 %    o hashmap_info: the hashmap info.
01446 %
01447 %    o key: the key.
01448 %
01449 %    o value: the value.
01450 %
01451 */
01452 
01453 static MagickBooleanType IncreaseHashmapCapacity(HashmapInfo *hashmap_info)
01454 {
01455 #define MaxCapacities  20
01456 
01457   const unsigned long
01458     capacities[MaxCapacities] =
01459     {
01460       17, 31, 61, 131, 257, 509, 1021, 2053, 4099, 8191, 16381, 32771,
01461       65537, 131071, 262147, 524287, 1048573, 2097143, 4194301, 8388617
01462     };
01463 
01464   ElementInfo
01465     *element;
01466 
01467   EntryInfo
01468     *entry;
01469 
01470   LinkedListInfo
01471     *list_info,
01472     *map_info,
01473     **map;
01474 
01475   register ElementInfo
01476     *next;
01477 
01478   register long
01479     i;
01480 
01481   unsigned long
01482     capacity;
01483 
01484   /*
01485     Increase to the next prime capacity.
01486   */
01487   for (i=0; i < MaxCapacities; i++)
01488     if (hashmap_info->capacity < capacities[i])
01489       break;
01490   if (i >= (MaxCapacities-1))
01491     return(MagickFalse);
01492   capacity=capacities[i+1];
01493   map=(LinkedListInfo **) AcquireQuantumMemory((size_t) capacity+1UL,
01494     sizeof(*map));
01495   if (map == (LinkedListInfo **) NULL)
01496     return(MagickFalse);
01497   (void) ResetMagickMemory(map,0,(size_t) capacity*sizeof(*map));
01498   /*
01499     Copy entries to new hashmap with increased capacity.
01500   */
01501   for (i=0; i < (long) hashmap_info->capacity; i++)
01502   {
01503     list_info=hashmap_info->map[i];
01504     if (list_info == (LinkedListInfo *) NULL)
01505       continue;
01506     (void) LockSemaphoreInfo(list_info->semaphore);
01507     for (next=list_info->head; next != (ElementInfo *) NULL; )
01508     {
01509       element=next;
01510       next=next->next;
01511       entry=(EntryInfo *) element->value;
01512       map_info=map[entry->hash % capacity];
01513       if (map_info == (LinkedListInfo *) NULL)
01514         {
01515           map_info=NewLinkedList(0);
01516           map[entry->hash % capacity]=map_info;
01517         }
01518       map_info->next=element;
01519       element->next=map_info->head;
01520       map_info->head=element;
01521       map_info->elements++;
01522     }
01523     list_info->signature=(~MagickSignature);
01524     (void) UnlockSemaphoreInfo(list_info->semaphore);
01525     DestroySemaphoreInfo(&list_info->semaphore);
01526     list_info=(LinkedListInfo *) RelinquishMagickMemory(list_info);
01527   }
01528   hashmap_info->map=(LinkedListInfo **) RelinquishMagickMemory(
01529     hashmap_info->map);
01530   hashmap_info->map=map;
01531   hashmap_info->capacity=capacity;
01532   return(MagickTrue);
01533 }
01534 
01535 MagickExport MagickBooleanType PutEntryInHashmap(HashmapInfo *hashmap_info,
01536   const void *key,const void *value)
01537 {
01538   EntryInfo
01539     *entry,
01540     *next;
01541 
01542   LinkedListInfo
01543     *list_info;
01544 
01545   register unsigned long
01546     i;
01547 
01548   assert(hashmap_info != (HashmapInfo *) NULL);
01549   assert(hashmap_info->signature == MagickSignature);
01550   if (hashmap_info->debug != MagickFalse)
01551     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01552   if ((key == (void *) NULL) || (value == (void *) NULL))
01553     return(MagickFalse);
01554   next=(EntryInfo *) AcquireMagickMemory(sizeof(*next));
01555   if (next == (EntryInfo *) NULL)
01556     return(MagickFalse);
01557   (void) LockSemaphoreInfo(hashmap_info->semaphore);
01558   next->hash=hashmap_info->hash(key);
01559   next->key=(void *) key;
01560   next->value=(void *) value;
01561   list_info=hashmap_info->map[next->hash % hashmap_info->capacity];
01562   if (list_info == (LinkedListInfo *) NULL)
01563     {
01564       list_info=NewLinkedList(0);
01565       hashmap_info->map[next->hash % hashmap_info->capacity]=list_info;
01566     }
01567   else
01568     {
01569       list_info->next=list_info->head;
01570       entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
01571       for (i=0; entry != (EntryInfo *) NULL; i++)
01572       {
01573         if (entry->hash == next->hash)
01574           {
01575             MagickBooleanType
01576               compare;
01577 
01578             compare=MagickTrue;
01579             if (hashmap_info->compare !=
01580                 (MagickBooleanType (*)(const void *,const void *)) NULL)
01581               compare=hashmap_info->compare(key,entry->key);
01582             if (compare == MagickTrue)
01583               {
01584                 (void) RemoveElementFromLinkedList(list_info,i);
01585                 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
01586                   entry->key=hashmap_info->relinquish_key(entry->key);
01587                 if (hashmap_info->relinquish_value != (void *(*)(void *)) NULL)
01588                   entry->value=hashmap_info->relinquish_value(entry->value);
01589                 entry=(EntryInfo *) RelinquishMagickMemory(entry);
01590                 break;
01591               }
01592           }
01593         entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
01594       }
01595     }
01596   if (InsertValueInLinkedList(list_info,0,next) == MagickFalse)
01597     {
01598       next=(EntryInfo *) RelinquishMagickMemory(next);
01599       (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
01600       return(MagickFalse);
01601     }
01602   if (list_info->elements >= (hashmap_info->capacity-1))
01603     if (IncreaseHashmapCapacity(hashmap_info) == MagickFalse)
01604       {
01605         (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
01606         return(MagickFalse);
01607       }
01608   hashmap_info->entries++;
01609   (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
01610   return(MagickTrue);
01611 }
01612 
01613 /*
01614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01615 %                                                                             %
01616 %                                                                             %
01617 %                                                                             %
01618 %   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       %
01619 %                                                                             %
01620 %                                                                             %
01621 %                                                                             %
01622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01623 %
01624 %  RemoveElementByValueFromLinkedList() removes an element from the linked-list
01625 %  by value.
01626 %
01627 %  The format of the RemoveElementByValueFromLinkedList method is:
01628 %
01629 %      void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
01630 %        const void *value)
01631 %
01632 %  A description of each parameter follows:
01633 %
01634 %    o list_info: the list info.
01635 %
01636 %    o value: the value.
01637 %
01638 */
01639 MagickExport void *RemoveElementByValueFromLinkedList(LinkedListInfo *list_info,
01640   const void *value)
01641 {
01642   ElementInfo
01643     *next;
01644 
01645   assert(list_info != (LinkedListInfo *) NULL);
01646   assert(list_info->signature == MagickSignature);
01647   if (list_info->debug != MagickFalse)
01648     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01649   if ((list_info->elements == 0) || (value == (const void *) NULL))
01650     return((void *) NULL);
01651   (void) LockSemaphoreInfo(list_info->semaphore);
01652   if (value == list_info->head->value)
01653     {
01654       if (list_info->next == list_info->head)
01655         list_info->next=list_info->head->next;
01656       next=list_info->head;
01657       list_info->head=list_info->head->next;
01658       next=(ElementInfo *) RelinquishMagickMemory(next);
01659     }
01660   else
01661     {
01662       ElementInfo
01663         *element;
01664 
01665       next=list_info->head;
01666       while ((next->next != (ElementInfo *) NULL) &&
01667              (next->next->value != value))
01668         next=next->next;
01669       if (next->next == (ElementInfo *) NULL)
01670         {
01671           (void) UnlockSemaphoreInfo(list_info->semaphore);
01672           return((void *) NULL);
01673         }
01674       element=next->next;
01675       next->next=element->next;
01676       if (element == list_info->tail)
01677         list_info->tail=next;
01678       if (list_info->next == element)
01679         list_info->next=element->next;
01680       element=(ElementInfo *) RelinquishMagickMemory(element);
01681     }
01682   list_info->elements--;
01683   (void) UnlockSemaphoreInfo(list_info->semaphore);
01684   return((void *) value);
01685 }
01686 
01687 /*
01688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01689 %                                                                             %
01690 %                                                                             %
01691 %                                                                             %
01692 %   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                     %
01693 %                                                                             %
01694 %                                                                             %
01695 %                                                                             %
01696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01697 %
01698 %  RemoveElementFromLinkedList() removes an element from the linked-list at the
01699 %  specified location.
01700 %
01701 %  The format of the RemoveElementFromLinkedList method is:
01702 %
01703 %      void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
01704 %        const unsigned long index)
01705 %
01706 %  A description of each parameter follows:
01707 %
01708 %    o list_info: the linked-list info.
01709 %
01710 %    o index: the index.
01711 %
01712 */
01713 MagickExport void *RemoveElementFromLinkedList(LinkedListInfo *list_info,
01714   const unsigned long index)
01715 {
01716   ElementInfo
01717     *next;
01718 
01719   register long
01720     i;
01721 
01722   void
01723     *value;
01724 
01725   assert(list_info != (LinkedListInfo *) NULL);
01726   assert(list_info->signature == MagickSignature);
01727   if (list_info->debug != MagickFalse)
01728     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01729   if (index >= list_info->elements)
01730     return((void *) NULL);
01731   (void) LockSemaphoreInfo(list_info->semaphore);
01732   if (index == 0)
01733     {
01734       if (list_info->next == list_info->head)
01735         list_info->next=list_info->head->next;
01736       value=list_info->head->value;
01737       next=list_info->head;
01738       list_info->head=list_info->head->next;
01739       next=(ElementInfo *) RelinquishMagickMemory(next);
01740     }
01741   else
01742     {
01743       ElementInfo
01744         *element;
01745 
01746       next=list_info->head;
01747       for (i=1; i < (long) index; i++)
01748         next=next->next;
01749       element=next->next;
01750       next->next=element->next;
01751       if (element == list_info->tail)
01752         list_info->tail=next;
01753       if (list_info->next == element)
01754         list_info->next=element->next;
01755       value=element->value;
01756       element=(ElementInfo *) RelinquishMagickMemory(element);
01757     }
01758   list_info->elements--;
01759   (void) UnlockSemaphoreInfo(list_info->semaphore);
01760   return(value);
01761 }
01762 
01763 /*
01764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01765 %                                                                             %
01766 %                                                                             %
01767 %                                                                             %
01768 %   R e m o v e E n t r y F r o m H a s h m a p                               %
01769 %                                                                             %
01770 %                                                                             %
01771 %                                                                             %
01772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01773 %
01774 %  RemoveEntryFromHashmap() removes an entry from the hash-map by its key.
01775 %
01776 %  The format of the RemoveEntryFromHashmap method is:
01777 %
01778 %      void *RemoveEntryFromHashmap(HashmapInfo *hashmap_info,void *key)
01779 %
01780 %  A description of each parameter follows:
01781 %
01782 %    o hashmap_info: the hashmap info.
01783 %
01784 %    o key: the key.
01785 %
01786 */
01787 MagickExport void *RemoveEntryFromHashmap(HashmapInfo *hashmap_info,
01788   const void *key)
01789 {
01790   EntryInfo
01791     *entry;
01792 
01793   LinkedListInfo
01794     *list_info;
01795 
01796   register unsigned long
01797     i;
01798 
01799   size_t
01800     hash;
01801 
01802   void
01803     *value;
01804 
01805   assert(hashmap_info != (HashmapInfo *) NULL);
01806   assert(hashmap_info->signature == MagickSignature);
01807   if (hashmap_info->debug != MagickFalse)
01808     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01809   if (key == (const void *) NULL)
01810     return((void *) NULL);
01811   (void) LockSemaphoreInfo(hashmap_info->semaphore);
01812   hash=hashmap_info->hash(key);
01813   list_info=hashmap_info->map[hash % hashmap_info->capacity];
01814   if (list_info != (LinkedListInfo *) NULL)
01815     {
01816       list_info->next=list_info->head;
01817       entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
01818       for (i=0; entry != (EntryInfo *) NULL; i++)
01819       {
01820         if (entry->hash == hash)
01821           {
01822             MagickBooleanType
01823               compare;
01824 
01825             compare=MagickTrue;
01826             if (hashmap_info->compare !=
01827                 (MagickBooleanType (*)(const void *,const void *)) NULL)
01828               compare=hashmap_info->compare(key,entry->key);
01829             if (compare == MagickTrue)
01830               {
01831                 entry=(EntryInfo *) RemoveElementFromLinkedList(list_info,i);
01832                 if (entry == (EntryInfo *) NULL)
01833                   {
01834                     (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
01835                     return((void *) NULL);
01836                   }
01837                 if (hashmap_info->relinquish_key != (void *(*)(void *)) NULL)
01838                   entry->key=hashmap_info->relinquish_key(entry->key);
01839                 value=entry->value;
01840                 entry=(EntryInfo *) RelinquishMagickMemory(entry);
01841                 hashmap_info->entries--;
01842                 (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
01843                 return(value);
01844               }
01845           }
01846         entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
01847       }
01848     }
01849   (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
01850   return((void *) NULL);
01851 }
01852 
01853 /*
01854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01855 %                                                                             %
01856 %                                                                             %
01857 %                                                                             %
01858 %   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             %
01859 %                                                                             %
01860 %                                                                             %
01861 %                                                                             %
01862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01863 %
01864 %  RemoveLastElementFromLinkedList() removes the last element from the
01865 %  linked-list.
01866 %
01867 %  The format of the RemoveLastElementFromLinkedList method is:
01868 %
01869 %      void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
01870 %
01871 %  A description of each parameter follows:
01872 %
01873 %    o list_info: the linked-list info.
01874 %
01875 */
01876 MagickExport void *RemoveLastElementFromLinkedList(LinkedListInfo *list_info)
01877 {
01878   void
01879     *value;
01880 
01881   assert(list_info != (LinkedListInfo *) NULL);
01882   assert(list_info->signature == MagickSignature);
01883   if (list_info->debug != MagickFalse)
01884     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01885   if (list_info->elements == 0)
01886     return((void *) NULL);
01887   (void) LockSemaphoreInfo(list_info->semaphore);
01888   if (list_info->next == list_info->tail)
01889     list_info->next=(ElementInfo *) NULL;
01890   if (list_info->elements == 1UL)
01891     {
01892       value=list_info->head->value;
01893       list_info->head=(ElementInfo *) NULL;
01894       list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
01895     }
01896   else
01897     {
01898       ElementInfo
01899         *next;
01900 
01901       value=list_info->tail->value;
01902       next=list_info->head;
01903       while (next->next != list_info->tail)
01904         next=next->next;
01905       list_info->tail=(ElementInfo *) RelinquishMagickMemory(list_info->tail);
01906       list_info->tail=next;
01907       next->next=(ElementInfo *) NULL;
01908     }
01909   list_info->elements--;
01910   (void) UnlockSemaphoreInfo(list_info->semaphore);
01911   return(value);
01912 }
01913 
01914 /*
01915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01916 %                                                                             %
01917 %                                                                             %
01918 %                                                                             %
01919 %   R e s e t H a s h m a p I t e r a t o r                                   %
01920 %                                                                             %
01921 %                                                                             %
01922 %                                                                             %
01923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01924 %
01925 %  ResetHashmapIterator() resets the hash-map iterator.  Use it in conjunction
01926 %  with GetNextKeyInHashmap() to iterate over all the keys in the hash-map.
01927 %
01928 %  The format of the ResetHashmapIterator method is:
01929 %
01930 %      ResetHashmapIterator(HashmapInfo *hashmap_info)
01931 %
01932 %  A description of each parameter follows:
01933 %
01934 %    o hashmap_info: the hashmap info.
01935 %
01936 */
01937 MagickExport void ResetHashmapIterator(HashmapInfo *hashmap_info)
01938 {
01939   assert(hashmap_info != (HashmapInfo *) NULL);
01940   assert(hashmap_info->signature == MagickSignature);
01941   if (hashmap_info->debug != MagickFalse)
01942     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01943   (void) LockSemaphoreInfo(hashmap_info->semaphore);
01944   hashmap_info->next=0;
01945   hashmap_info->head_of_list=MagickFalse;
01946   (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
01947 }
01948 
01949 /*
01950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01951 %                                                                             %
01952 %                                                                             %
01953 %                                                                             %
01954 %   R e s e t L i n k e d L i s t I t e r a t o r                             %
01955 %                                                                             %
01956 %                                                                             %
01957 %                                                                             %
01958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01959 %
01960 %  ResetLinkedListIterator() resets the lined-list iterator.  Use it in
01961 %  conjunction with GetNextValueInLinkedList() to iterate over all the values
01962 %  in the linked-list.
01963 %
01964 %  The format of the ResetLinkedListIterator method is:
01965 %
01966 %      ResetLinkedListIterator(LinkedListInfo *list_info)
01967 %
01968 %  A description of each parameter follows:
01969 %
01970 %    o list_info: the linked-list info.
01971 %
01972 */
01973 MagickExport void ResetLinkedListIterator(LinkedListInfo *list_info)
01974 {
01975   assert(list_info != (LinkedListInfo *) NULL);
01976   assert(list_info->signature == MagickSignature);
01977   if (list_info->debug != MagickFalse)
01978     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01979   (void) LockSemaphoreInfo(list_info->semaphore);
01980   list_info->next=list_info->head;
01981   (void) UnlockSemaphoreInfo(list_info->semaphore);
01982 }

Generated on Thu Jul 2 12:03:19 2009 for MagickCore by  doxygen 1.5.8