|
MagickCore
6.7.5
|
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-2012 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 "MagickCore/studio.h" 00046 #include "MagickCore/exception.h" 00047 #include "MagickCore/exception-private.h" 00048 #include "MagickCore/hashmap.h" 00049 #include "MagickCore/memory_.h" 00050 #include "MagickCore/semaphore.h" 00051 #include "MagickCore/signature-private.h" 00052 #include "MagickCore/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 size_t 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 size_t 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 size_t 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 size_t 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 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 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 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 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 % CompareHashmapString() finds an entry in a hash-map based on the contents 00254 % 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 % CompareHashmapStringInfo() finds an entry in a hash-map based on the 00292 % 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 ssize_t 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 LockSemaphoreInfo(hashmap_info->semaphore); 00356 for (i=0; i < (ssize_t) 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 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 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 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 LockSemaphoreInfo(list_info->semaphore); 00473 value=list_info->tail->value; 00474 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 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 UnlockSemaphoreInfo(hashmap_info->semaphore); 00531 return(key); 00532 } 00533 hashmap_info->head_of_list=MagickFalse; 00534 } 00535 hashmap_info->next++; 00536 } 00537 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 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 UnlockSemaphoreInfo(hashmap_info->semaphore); 00594 return(value); 00595 } 00596 hashmap_info->head_of_list=MagickFalse; 00597 } 00598 hashmap_info->next++; 00599 } 00600 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 LockSemaphoreInfo(list_info->semaphore); 00636 if (list_info->next == (ElementInfo *) NULL) 00637 { 00638 UnlockSemaphoreInfo(list_info->semaphore); 00639 return((void *) NULL); 00640 } 00641 value=list_info->next->value; 00642 list_info->next=list_info->next->next; 00643 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 % size_t 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 size_t 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 % size_t 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 size_t 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 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 UnlockSemaphoreInfo(hashmap_info->semaphore); 00780 return(value); 00781 } 00782 } 00783 entry=(EntryInfo *) GetNextValueInLinkedList(list_info); 00784 } 00785 } 00786 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 size_t 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 size_t index) 00818 { 00819 register ElementInfo 00820 *next; 00821 00822 register ssize_t 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 LockSemaphoreInfo(list_info->semaphore); 00835 if (index == 0) 00836 { 00837 value=list_info->head->value; 00838 UnlockSemaphoreInfo(list_info->semaphore); 00839 return(value); 00840 } 00841 if (index == (list_info->elements-1)) 00842 { 00843 value=list_info->tail->value; 00844 UnlockSemaphoreInfo(list_info->semaphore); 00845 return(value); 00846 } 00847 next=list_info->head; 00848 for (i=0; i < (ssize_t) index; i++) 00849 next=next->next; 00850 value=next->value; 00851 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 % HashPointerType() finds an entry in a hash-map based on the address of a 00867 % 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 % HashStringType() finds an entry in a hash-map based on the contents of a 00903 % 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 ssize_t 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 ssize_t 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 size_t 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 size_t index,const void *value) 01022 { 01023 register ElementInfo 01024 *next; 01025 01026 register ssize_t 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 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 < (ssize_t) 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 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 ssize_t 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 LockSemaphoreInfo(list_info->semaphore); 01151 next->next=list_info->head; 01152 while (next->next != (ElementInfo *) NULL) 01153 { 01154 i=(ssize_t) 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 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 ssize_t 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 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 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 size_t 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 size_t 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 size_t 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 size_t 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 ? (size_t) (~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 size_t 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 ssize_t 01479 i; 01480 01481 size_t 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 < (ssize_t) hashmap_info->capacity; i++) 01502 { 01503 list_info=hashmap_info->map[i]; 01504 if (list_info == (LinkedListInfo *) NULL) 01505 continue; 01506 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 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 size_t 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 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 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 UnlockSemaphoreInfo(hashmap_info->semaphore); 01606 return(MagickFalse); 01607 } 01608 hashmap_info->entries++; 01609 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 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 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 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 size_t 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 size_t index) 01715 { 01716 ElementInfo 01717 *next; 01718 01719 register ssize_t 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 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 < (ssize_t) 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 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 size_t 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 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 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 UnlockSemaphoreInfo(hashmap_info->semaphore); 01843 return(value); 01844 } 01845 } 01846 entry=(EntryInfo *) GetNextValueInLinkedList(list_info); 01847 } 01848 } 01849 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 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 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 LockSemaphoreInfo(hashmap_info->semaphore); 01944 hashmap_info->next=0; 01945 hashmap_info->head_of_list=MagickFalse; 01946 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 LockSemaphoreInfo(list_info->semaphore); 01980 list_info->next=list_info->head; 01981 UnlockSemaphoreInfo(list_info->semaphore); 01982 }