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-2008 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   if (list_info->next == (ElementInfo *) NULL)
00636     return((void *) NULL);
00637   (void) LockSemaphoreInfo(list_info->semaphore);
00638   value=list_info->next->value;
00639   list_info->next=list_info->next->next;
00640   (void) UnlockSemaphoreInfo(list_info->semaphore);
00641   return(value);
00642 }
00643 
00644 /*
00645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00646 %                                                                             %
00647 %                                                                             %
00648 %                                                                             %
00649 %   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                     %
00650 %                                                                             %
00651 %                                                                             %
00652 %                                                                             %
00653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00654 %
00655 %  GetNumberOfEntriesInHashmap() returns the number of entries in the hash-map.
00656 %
00657 %  The format of the GetNumberOfEntriesInHashmap method is:
00658 %
00659 %      unsigned long GetNumberOfEntriesInHashmap(const HashmapInfo *hashmap_info)
00660 %
00661 %  A description of each parameter follows:
00662 %
00663 %    o hashmap_info: the hashmap info.
00664 %
00665 */
00666 MagickExport unsigned long GetNumberOfEntriesInHashmap(
00667   const HashmapInfo *hashmap_info)
00668 {
00669   assert(hashmap_info != (HashmapInfo *) NULL);
00670   assert(hashmap_info->signature == MagickSignature);
00671   if (hashmap_info->debug != MagickFalse)
00672     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00673   return(hashmap_info->entries);
00674 }
00675 
00676 /*
00677 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00678 %                                                                             %
00679 %                                                                             %
00680 %                                                                             %
00681 %   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             %
00682 %                                                                             %
00683 %                                                                             %
00684 %                                                                             %
00685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00686 %
00687 %  GetNumberOfElementsInLinkedList() returns the number of entries in the
00688 %  linked-list.
00689 %
00690 %  The format of the GetNumberOfElementsInLinkedList method is:
00691 %
00692 %      unsigned long GetNumberOfElementsInLinkedList(
00693 %        const LinkedListInfo *list_info)
00694 %
00695 %  A description of each parameter follows:
00696 %
00697 %    o list_info: the linked-list info.
00698 %
00699 */
00700 MagickExport unsigned long GetNumberOfElementsInLinkedList(
00701   const LinkedListInfo *list_info)
00702 {
00703   assert(list_info != (LinkedListInfo *) NULL);
00704   assert(list_info->signature == MagickSignature);
00705   if (list_info->debug != MagickFalse)
00706     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00707   return(list_info->elements);
00708 }
00709 
00710 /*
00711 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00712 %                                                                             %
00713 %                                                                             %
00714 %                                                                             %
00715 %   G e t V a l u e F r o m H a s h m a p                                     %
00716 %                                                                             %
00717 %                                                                             %
00718 %                                                                             %
00719 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00720 %
00721 %  GetValueFromHashmap() gets an entry from the hash-map by its key.
00722 %
00723 %  The format of the GetValueFromHashmap method is:
00724 %
00725 %      void *GetValueFromHashmap(HashmapInfo *hashmap_info,const void *key)
00726 %
00727 %  A description of each parameter follows:
00728 %
00729 %    o hashmap_info: the hashmap info.
00730 %
00731 %    o key: the key.
00732 %
00733 */
00734 MagickExport void *GetValueFromHashmap(HashmapInfo *hashmap_info,
00735   const void *key)
00736 {
00737   LinkedListInfo
00738     *list_info;
00739 
00740   register EntryInfo
00741     *entry;
00742 
00743   size_t
00744     hash;
00745 
00746   void
00747     *value;
00748 
00749   assert(hashmap_info != (HashmapInfo *) NULL);
00750   assert(hashmap_info->signature == MagickSignature);
00751   if (hashmap_info->debug != MagickFalse)
00752     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00753   if (key == (const void *) NULL)
00754     return((void *) NULL);
00755   (void) LockSemaphoreInfo(hashmap_info->semaphore);
00756   hash=hashmap_info->hash(key);
00757   list_info=hashmap_info->map[hash % hashmap_info->capacity];
00758   if (list_info != (LinkedListInfo *) NULL)
00759     {
00760       list_info->next=list_info->head;
00761       entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
00762       while (entry != (EntryInfo *) NULL)
00763       {
00764         if (entry->hash == hash)
00765           {
00766             MagickBooleanType
00767               compare;
00768 
00769             compare=MagickTrue;
00770             if (hashmap_info->compare !=
00771                 (MagickBooleanType (*)(const void *,const void *)) NULL)
00772               compare=hashmap_info->compare(key,entry->key);
00773             if (compare == MagickTrue)
00774               {
00775                 value=entry->value;
00776                 (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
00777                 return(value);
00778               }
00779           }
00780         entry=(EntryInfo *) GetNextValueInLinkedList(list_info);
00781       }
00782     }
00783   (void) UnlockSemaphoreInfo(hashmap_info->semaphore);
00784   return((void *) NULL);
00785 }
00786 
00787 /*
00788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00789 %                                                                             %
00790 %                                                                             %
00791 %                                                                             %
00792 %   G e t V a l u e F r o m L i n k e d L i s t                               %
00793 %                                                                             %
00794 %                                                                             %
00795 %                                                                             %
00796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00797 %
00798 %  GetValueFromLinkedList() gets a value from the linked-list at the specified
00799 %  location.
00800 %
00801 %  The format of the GetValueFromLinkedList method is:
00802 %
00803 %      void *GetValueFromLinkedList(LinkedListInfo *list_info,
00804 %        const unsigned long index)
00805 %
00806 %  A description of each parameter follows:
00807 %
00808 %    o list_info: the linked_list info.
00809 %
00810 %    o index: the list index.
00811 %
00812 */
00813 MagickExport void *GetValueFromLinkedList(LinkedListInfo *list_info,
00814   const unsigned long index)
00815 {
00816   register ElementInfo
00817     *next;
00818 
00819   register long
00820     i;
00821 
00822   void
00823     *value;
00824 
00825   assert(list_info != (LinkedListInfo *) NULL);
00826   assert(list_info->signature == MagickSignature);
00827   if (list_info->debug != MagickFalse)
00828     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
00829   if (index >= list_info->elements)
00830     return((void *) NULL);
00831   (void) LockSemaphoreInfo(list_info->semaphore);
00832   if (index == 0)
00833     {
00834       value=list_info->head->value;
00835       (void) UnlockSemaphoreInfo(list_info->semaphore);
00836       return(value);
00837     }
00838   if (index == (list_info->elements-1))
00839     {
00840       value=list_info->tail->value;
00841       (void) UnlockSemaphoreInfo(list_info->semaphore);
00842       return(value);
00843     }
00844   next=list_info->head;
00845   for (i=0; i < (long) index; i++)
00846     next=next->next;
00847   value=next->value;
00848   (void) UnlockSemaphoreInfo(list_info->semaphore);
00849   return(value);
00850 }
00851 
00852 /*
00853 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00854 %                                                                             %
00855 %                                                                             %
00856 %                                                                             %
00857 %   H a s h P o i n t e r T y p e                                             %
00858 %                                                                             %
00859 %                                                                             %
00860 %                                                                             %
00861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00862 %
00863 %  Specify the HashPointerType() method in NewHashmap() to find an entry
00864 %  in a hash-map based on the address of a pointer.
00865 %
00866 %  The format of the HashPointerType method is:
00867 %
00868 %      size_t HashPointerType(const void *pointer)
00869 %
00870 %  A description of each parameter follows:
00871 %
00872 %    o pointer: compute the hash entry location from this pointer address.
00873 %
00874 */
00875 MagickExport size_t HashPointerType(const void *pointer)
00876 {
00877   size_t
00878     hash;
00879 
00880   hash=(size_t) pointer;
00881   hash+=(~(hash << 9));
00882   hash^=(hash >> 14);
00883   hash+=(hash << 4);
00884   hash^=(hash >> 10);
00885   return(hash);
00886 }
00887 
00888 /*
00889 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00890 %                                                                             %
00891 %                                                                             %
00892 %                                                                             %
00893 %   H a s h S t r i n g T y p e                                               %
00894 %                                                                             %
00895 %                                                                             %
00896 %                                                                             %
00897 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00898 %
00899 %  Specify the HashStringType() method in NewHashmap() to find an entry
00900 %  in a hash-map based on the contents of a string.
00901 %
00902 %  The format of the HashStringType method is:
00903 %
00904 %      size_t HashStringType(const void *string)
00905 %
00906 %  A description of each parameter follows:
00907 %
00908 %    o string: compute the hash entry location from this string.
00909 %
00910 */
00911 MagickExport size_t HashStringType(const void *string)
00912 {
00913   const unsigned char
00914     *digest;
00915 
00916   register long
00917     i;
00918 
00919   SignatureInfo
00920     *signature_info;
00921 
00922   size_t
00923     hash;
00924 
00925   StringInfo
00926     *signature;
00927 
00928   signature_info=AcquireSignatureInfo();
00929   signature=StringToStringInfo((const char *) string);
00930   UpdateSignature(signature_info,signature);
00931   FinalizeSignature(signature_info);
00932   digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
00933   hash=0;
00934   for (i=0; i < 8; i++)
00935     hash^=digest[i];
00936   signature=DestroyStringInfo(signature);
00937   signature_info=DestroySignatureInfo(signature_info);
00938   return(hash);
00939 }
00940 
00941 /*
00942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00943 %                                                                             %
00944 %                                                                             %
00945 %                                                                             %
00946 %   H a s h S t r i n g I n f o T y p e                                       %
00947 %                                                                             %
00948 %                                                                             %
00949 %                                                                             %
00950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00951 %
00952 %  Specify the HashStringInfoType() method in NewHashmap() to find an entry
00953 %  in a hash-map based on the contents of a string.
00954 %
00955 %  The format of the HashStringInfoType method is:
00956 %
00957 %      size_t HashStringInfoType(const void *string_info)
00958 %
00959 %  A description of each parameter follows:
00960 %
00961 %    o string_info: compute the hash entry location from this string.
00962 %
00963 */
00964 MagickExport size_t HashStringInfoType(const void *string_info)
00965 {
00966   const unsigned char
00967     *digest;
00968 
00969   register long
00970     i;
00971 
00972   SignatureInfo
00973     *signature_info;
00974 
00975   size_t
00976     hash;
00977 
00978   signature_info=AcquireSignatureInfo();
00979   UpdateSignature(signature_info,(const StringInfo *) string_info);
00980   FinalizeSignature(signature_info);
00981   digest=GetStringInfoDatum(GetSignatureDigest(signature_info));
00982   hash=0;
00983   for (i=0; i < 8; i++)
00984     hash^=digest[i];
00985   signature_info=DestroySignatureInfo(signature_info);
00986   return(hash);
00987 }
00988 
00989 /*
00990 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00991 %                                                                             %
00992 %                                                                             %
00993 %                                                                             %
00994 %   I n s e r t V a l u e I n L i n k e d L i s t                             %
00995 %                                                                             %
00996 %                                                                             %
00997 %                                                                             %
00998 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00999 %
01000 %  InsertValueInLinkedList() inserts an element in the linked-list at the
01001 %  specified location.
01002 %
01003 %  The format of the InsertValueInLinkedList method is:
01004 %
01005 %      MagickBooleanType InsertValueInLinkedList(ListInfo *list_info,
01006 %        const unsigned long index,const void *value)
01007 %
01008 %  A description of each parameter follows:
01009 %
01010 %    o list_info: the hashmap info.
01011 %
01012 %    o index: the index.
01013 %
01014 %    o value: the value.
01015 %
01016 */
01017 MagickExport MagickBooleanType InsertValueInLinkedList(
01018   LinkedListInfo *list_info,const unsigned long index,const void *value)
01019 {
01020   register ElementInfo
01021     *next;
01022 
01023   register long
01024     i;
01025 
01026   assert(list_info != (LinkedListInfo *) NULL);
01027   assert(list_info->signature == MagickSignature);
01028   if (list_info->debug != MagickFalse)
01029     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
01030   if (value == (const void *) NULL)
01031     return(MagickFalse);
01032   if ((index > list_info->elements) ||
01033       (list_info->elements == list_info->capacity))
01034     return(MagickFalse);
01035   next=(ElementInfo *) AcquireMagickMemory(sizeof(*next));
01036   if (next == (ElementInfo *) NULL)
01037     return(MagickFalse);
01038   next->value=(void *) value;
01039   next->next=(ElementInfo *) NULL;
01040   (void) LockSemaphoreInfo(list_info->semaphore);
01041   if (list_info->elements == 0)
01042     {
01043       if (list_info->next == (ElementInfo *) NULL)
01044         list_info->next=next;
01045       list_info->head=next;
01046       list_info->tail=next;
01047     }
01048   else
01049     {
01050       if (index == 0)
01051         {
01052           if (list_info->next == list_info->head)
01053             list_info->next=next;
01054           next->next=list_info->head;
01055           list_info->head=next;
01056         }
01057       else
01058         if (index == list_info->elements)
01059           {
01060             if (list_info->next == (ElementInfo *) NULL)
01061               list_info->next=next;
01062             list_info-><