blob: 33079d46e63af1cead06cd618827d6c177a46a72 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% SSSSS PPPP L AAA Y Y %
7% SS P P L A A Y Y %
8% SSS PPPP L AAAAA Y %
9% SS P L A A Y %
10% SSSSS P LLLLL A A Y %
11% %
12% TTTTT RRRR EEEEE EEEEE %
13% T R R E E %
14% T RRRR EEE EEE %
15% T R R E E %
16% T R R EEEEE EEEEE %
17% %
18% %
19% MagickCore Self-adjusting Binary Search Tree Methods %
20% %
21% Software Design %
22% John Cristy %
23% December 2002 %
24% %
25% %
cristy1454be72011-12-19 01:52:48 +000026% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000027% dedicated to making software imaging solutions freely available. %
28% %
29% You may not use this file except in compliance with the License. You may %
30% obtain a copy of the License at %
31% %
32% http://www.imagemagick.org/script/license.php %
33% %
34% Unless required by applicable law or agreed to in writing, software %
35% distributed under the License is distributed on an "AS IS" BASIS, %
36% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
37% See the License for the specific language governing permissions and %
38% limitations under the License. %
39% %
40%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41%
42% This module implements the standard handy splay-tree methods for storing and
43% retrieving large numbers of data elements. It is loosely based on the Java
44% implementation of these algorithms.
45%
46*/
47
48/*
49 Include declarations.
50*/
cristy4c08aed2011-07-01 19:47:50 +000051#include "MagickCore/studio.h"
52#include "MagickCore/exception.h"
53#include "MagickCore/exception-private.h"
54#include "MagickCore/log.h"
55#include "MagickCore/memory_.h"
56#include "MagickCore/splay-tree.h"
57#include "MagickCore/semaphore.h"
58#include "MagickCore/string_.h"
cristy3ed852e2009-09-05 21:47:34 +000059
60/*
61 Define declarations.
62*/
63#define MaxSplayTreeDepth 1024
64
65/*
66 Typedef declarations.
67*/
68typedef struct _NodeInfo
69{
70 void
71 *key;
72
73 void
74 *value;
75
76 struct _NodeInfo
77 *left,
78 *right;
79} NodeInfo;
80
81struct _SplayTreeInfo
82{
83 NodeInfo
84 *root;
85
86 int
87 (*compare)(const void *,const void *);
88
89 void
90 *(*relinquish_key)(void *),
91 *(*relinquish_value)(void *);
92
93 MagickBooleanType
94 balance;
95
96 void
97 *key,
98 *next;
99
cristybb503372010-05-27 20:51:26 +0000100 size_t
cristy3ed852e2009-09-05 21:47:34 +0000101 nodes;
102
103 MagickBooleanType
104 debug;
105
106 SemaphoreInfo
107 *semaphore;
108
cristybb503372010-05-27 20:51:26 +0000109 size_t
cristy3ed852e2009-09-05 21:47:34 +0000110 signature;
111};
112
113/*
114 Forward declarations.
115*/
116static int
117 IterateOverSplayTree(SplayTreeInfo *,int (*)(NodeInfo *,const void *),
118 const void *);
119
120static void
121 SplaySplayTree(SplayTreeInfo *,const void *);
122
123/*
124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125% %
126% %
127% %
128% A d d V a l u e T o S p l a y T r e e %
129% %
130% %
131% %
132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133%
anthony72feaa62012-01-17 06:46:23 +0000134% AddValueToSplayTree() adds the given key and value to the splay-tree.
cristyad2f5242012-11-08 01:12:57 +0000135% Both key and value are used as is, without coping or cloning. It returns
136% MagickTrue on success, otherwise MagickFalse.
cristy3ed852e2009-09-05 21:47:34 +0000137%
138% The format of the AddValueToSplayTree method is:
139%
140% MagickBooleanType AddValueToSplayTree(SplayTreeInfo *splay_tree,
141% const void *key,const void *value)
142%
143% A description of each parameter follows:
144%
145% o splay_tree: the splay-tree info.
146%
147% o key: the key.
148%
149% o value: the value.
150%
151*/
152MagickExport MagickBooleanType AddValueToSplayTree(SplayTreeInfo *splay_tree,
153 const void *key,const void *value)
154{
155 int
156 compare;
157
158 register NodeInfo
159 *node;
160
cristyf84a1932010-01-03 18:00:18 +0000161 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000162 SplaySplayTree(splay_tree,key);
163 compare=0;
164 if (splay_tree->root != (NodeInfo *) NULL)
165 {
166 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
167 compare=splay_tree->compare(splay_tree->root->key,key);
168 else
169 compare=(splay_tree->root->key > key) ? 1 :
170 ((splay_tree->root->key < key) ? -1 : 0);
171 if (compare == 0)
172 {
cristy6f24b182010-09-29 22:02:52 +0000173 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
174 (splay_tree->root->value != (void *) NULL))
175 splay_tree->root->value=splay_tree->relinquish_value(
176 splay_tree->root->value);
cristy3ed852e2009-09-05 21:47:34 +0000177 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
178 (splay_tree->root->key != (void *) NULL))
179 splay_tree->root->key=splay_tree->relinquish_key(
180 splay_tree->root->key);
181 splay_tree->root->key=(void *) key;
cristy3ed852e2009-09-05 21:47:34 +0000182 splay_tree->root->value=(void *) value;
cristyf84a1932010-01-03 18:00:18 +0000183 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000184 return(MagickTrue);
185 }
186 }
cristy73bd4a52010-10-05 11:24:23 +0000187 node=(NodeInfo *) AcquireMagickMemory(sizeof(*node));
cristy3ed852e2009-09-05 21:47:34 +0000188 if (node == (NodeInfo *) NULL)
189 {
cristyf84a1932010-01-03 18:00:18 +0000190 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000191 return(MagickFalse);
192 }
193 node->key=(void *) key;
194 node->value=(void *) value;
195 if (splay_tree->root == (NodeInfo *) NULL)
196 {
197 node->left=(NodeInfo *) NULL;
198 node->right=(NodeInfo *) NULL;
199 }
200 else
201 if (compare < 0)
202 {
203 node->left=splay_tree->root;
204 node->right=node->left->right;
205 node->left->right=(NodeInfo *) NULL;
206 }
207 else
208 {
209 node->right=splay_tree->root;
210 node->left=node->right->left;
211 node->right->left=(NodeInfo *) NULL;
212 }
213 splay_tree->root=node;
214 splay_tree->key=(void *) NULL;
215 splay_tree->nodes++;
cristyf84a1932010-01-03 18:00:18 +0000216 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000217 return(MagickTrue);
218}
219
220/*
221%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
222% %
223% %
224% %
225% B a l a n c e S p l a y T r e e %
226% %
227% %
228% %
229%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230%
231% BalanceSplayTree() balances the splay-tree.
232%
233% The format of the BalanceSplayTree method is:
234%
235% void *BalanceSplayTree(SplayTreeInfo *splay_tree,const void *key)
236%
237% A description of each parameter follows:
238%
239% o splay_tree: the splay-tree info.
240%
241% o key: the key.
242%
243*/
244
cristybb503372010-05-27 20:51:26 +0000245static NodeInfo *LinkSplayTreeNodes(NodeInfo **nodes,const size_t low,
246 const size_t high)
cristy3ed852e2009-09-05 21:47:34 +0000247{
248 register NodeInfo
249 *node;
250
cristybb503372010-05-27 20:51:26 +0000251 size_t
cristy3ed852e2009-09-05 21:47:34 +0000252 bisect;
253
254 bisect=low+(high-low)/2;
255 node=nodes[bisect];
256 if ((low+1) > bisect)
257 node->left=(NodeInfo *) NULL;
258 else
259 node->left=LinkSplayTreeNodes(nodes,low,bisect-1);
260 if ((bisect+1) > high)
261 node->right=(NodeInfo *) NULL;
262 else
263 node->right=LinkSplayTreeNodes(nodes,bisect+1,high);
264 return(node);
265}
266
267static int SplayTreeToNodeArray(NodeInfo *node,const void *nodes)
268{
269 register const NodeInfo
270 ***p;
271
272 p=(const NodeInfo ***) nodes;
273 *(*p)=node;
274 (*p)++;
275 return(0);
276}
277
278static void BalanceSplayTree(SplayTreeInfo *splay_tree)
279{
280 NodeInfo
281 **node,
282 **nodes;
283
284 if (splay_tree->nodes <= 2)
285 {
286 splay_tree->balance=MagickFalse;
287 return;
288 }
289 nodes=(NodeInfo **) AcquireQuantumMemory((size_t) splay_tree->nodes,
290 sizeof(*nodes));
291 if (nodes == (NodeInfo **) NULL)
292 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
293 node=nodes;
294 (void) IterateOverSplayTree(splay_tree,SplayTreeToNodeArray,
295 (const void *) &node);
296 splay_tree->root=LinkSplayTreeNodes(nodes,0,splay_tree->nodes-1);
297 splay_tree->balance=MagickFalse;
298 nodes=(NodeInfo **) RelinquishMagickMemory(nodes);
299}
300
301/*
302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303% %
304% %
305% %
306% C l o n e S p l a y T r e e %
307% %
308% %
309% %
310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311%
312% CloneSplayTree() clones the splay tree.
313%
314% The format of the CloneSplayTree method is:
315%
316% SplayTreeInfo *CloneSplayTree(SplayTreeInfo *splay_tree,
317% void *(*clone_key)(void *),void *(*cline_value)(void *))
318%
319% A description of each parameter follows:
320%
321% o splay_tree: the splay tree.
322%
323% o clone_key: the key clone method, typically ConstantString(), called
324% whenever a key is added to the splay-tree.
325%
326% o clone_value: the value clone method; typically ConstantString(), called
327% whenever a value object is added to the splay-tree.
328%
329*/
cristy7959f822010-03-07 21:47:41 +0000330
331static void *GetFirstSplayTreeNode(SplayTreeInfo *splay_tree)
332{
333 register NodeInfo
334 *node;
335
336 node=splay_tree->root;
337 if (splay_tree->root == (NodeInfo *) NULL)
338 return((NodeInfo *) NULL);
339 while (node->left != (NodeInfo *) NULL)
340 node=node->left;
341 return(node->key);
342}
343
cristy3ed852e2009-09-05 21:47:34 +0000344MagickExport SplayTreeInfo *CloneSplayTree(SplayTreeInfo *splay_tree,
345 void *(*clone_key)(void *),void *(*clone_value)(void *))
346{
cristy7959f822010-03-07 21:47:41 +0000347 register NodeInfo
348 *next,
349 *node;
350
cristy3ed852e2009-09-05 21:47:34 +0000351 SplayTreeInfo
352 *clone_tree;
353
354 assert(splay_tree != (SplayTreeInfo *) NULL);
355 assert(splay_tree->signature == MagickSignature);
356 if (splay_tree->debug != MagickFalse)
357 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
358 clone_tree=NewSplayTree(splay_tree->compare,splay_tree->relinquish_key,
359 splay_tree->relinquish_value);
cristyf84a1932010-01-03 18:00:18 +0000360 LockSemaphoreInfo(splay_tree->semaphore);
cristy7959f822010-03-07 21:47:41 +0000361 if (splay_tree->root == (NodeInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000362 {
cristy7959f822010-03-07 21:47:41 +0000363 UnlockSemaphoreInfo(splay_tree->semaphore);
364 return(clone_tree);
cristy3ed852e2009-09-05 21:47:34 +0000365 }
cristy7959f822010-03-07 21:47:41 +0000366 next=(NodeInfo *) GetFirstSplayTreeNode(splay_tree);
367 while (next != (NodeInfo *) NULL)
368 {
369 SplaySplayTree(splay_tree,next);
370 (void) AddValueToSplayTree(clone_tree,clone_key(splay_tree->root->key),
371 clone_value(splay_tree->root->value));
372 next=(NodeInfo *) NULL;
373 node=splay_tree->root->right;
374 if (node != (NodeInfo *) NULL)
375 {
376 while (node->left != (NodeInfo *) NULL)
377 node=node->left;
378 next=(NodeInfo *) node->key;
379 }
380 }
cristyf84a1932010-01-03 18:00:18 +0000381 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000382 return(clone_tree);
383}
384
385/*
386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387% %
388% %
389% %
390% C o m p a r e S p l a y T r e e S t r i n g %
391% %
392% %
393% %
394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395%
396% CompareSplayTreeString() method finds a node in a splay-tree based on the
397% contents of a string.
398%
399% The format of the CompareSplayTreeString method is:
400%
401% int CompareSplayTreeString(const void *target,const void *source)
402%
403% A description of each parameter follows:
404%
405% o target: the target string.
406%
407% o source: the source string.
408%
409*/
410MagickExport int CompareSplayTreeString(const void *target,const void *source)
411{
412 const char
413 *p,
414 *q;
415
416 p=(const char *) target;
417 q=(const char *) source;
418 return(LocaleCompare(p,q));
419}
420
421/*
422%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423% %
424% %
425% %
426% C o m p a r e S p l a y T r e e S t r i n g I n f o %
427% %
428% %
429% %
430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431%
432% CompareSplayTreeStringInfo() finds a node in a splay-tree based on the
433% contents of a string.
434%
435% The format of the CompareSplayTreeStringInfo method is:
436%
437% int CompareSplayTreeStringInfo(const void *target,const void *source)
438%
439% A description of each parameter follows:
440%
441% o target: the target string.
442%
443% o source: the source string.
444%
445*/
446MagickExport int CompareSplayTreeStringInfo(const void *target,
447 const void *source)
448{
449 const StringInfo
450 *p,
451 *q;
452
453 p=(const StringInfo *) target;
454 q=(const StringInfo *) source;
455 return(CompareStringInfo(p,q));
456}
457
458/*
459%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
460% %
461% %
462% %
463% D e l e t e N o d e B y V a l u e F r o m S p l a y T r e e %
464% %
465% %
466% %
467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
468%
469% DeleteNodeByValueFromSplayTree() deletes a node by value from the
470% splay-tree.
471%
472% The format of the DeleteNodeByValueFromSplayTree method is:
473%
474% MagickBooleanType DeleteNodeByValueFromSplayTree(
475% SplayTreeInfo *splay_tree,const void *value)
476%
477% A description of each parameter follows:
478%
479% o splay_tree: the splay-tree info.
480%
481% o value: the value.
482%
483*/
cristy3ed852e2009-09-05 21:47:34 +0000484MagickExport MagickBooleanType DeleteNodeByValueFromSplayTree(
485 SplayTreeInfo *splay_tree,const void *value)
486{
487 register NodeInfo
488 *next,
489 *node;
490
491 assert(splay_tree != (SplayTreeInfo *) NULL);
492 assert(splay_tree->signature == MagickSignature);
493 if (splay_tree->debug != MagickFalse)
494 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +0000495 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000496 if (splay_tree->root == (NodeInfo *) NULL)
497 {
cristyf84a1932010-01-03 18:00:18 +0000498 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000499 return(MagickFalse);
500 }
501 next=(NodeInfo *) GetFirstSplayTreeNode(splay_tree);
502 while (next != (NodeInfo *) NULL)
503 {
504 SplaySplayTree(splay_tree,next);
505 next=(NodeInfo *) NULL;
506 node=splay_tree->root->right;
507 if (node != (NodeInfo *) NULL)
508 {
509 while (node->left != (NodeInfo *) NULL)
510 node=node->left;
511 next=(NodeInfo *) node->key;
512 }
513 if (splay_tree->root->value == value)
514 {
515 int
516 compare;
517
518 register NodeInfo
519 *left,
520 *right;
521
522 void
523 *key;
524
525 /*
526 We found the node that matches the value; now delete it.
527 */
528 key=splay_tree->root->key;
529 SplaySplayTree(splay_tree,key);
530 splay_tree->key=(void *) NULL;
531 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
532 compare=splay_tree->compare(splay_tree->root->key,key);
533 else
534 compare=(splay_tree->root->key > key) ? 1 :
535 ((splay_tree->root->key < key) ? -1 : 0);
536 if (compare != 0)
537 {
cristyf84a1932010-01-03 18:00:18 +0000538 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000539 return(MagickFalse);
540 }
541 left=splay_tree->root->left;
542 right=splay_tree->root->right;
cristy3ed852e2009-09-05 21:47:34 +0000543 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
544 (splay_tree->root->value != (void *) NULL))
545 splay_tree->root->value=splay_tree->relinquish_value(
546 splay_tree->root->value);
cristy6f24b182010-09-29 22:02:52 +0000547 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
548 (splay_tree->root->key != (void *) NULL))
549 splay_tree->root->key=splay_tree->relinquish_key(
550 splay_tree->root->key);
cristy3ed852e2009-09-05 21:47:34 +0000551 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
552 splay_tree->nodes--;
553 if (left == (NodeInfo *) NULL)
554 {
555 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +0000556 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000557 return(MagickTrue);
558 }
559 splay_tree->root=left;
560 if (right != (NodeInfo *) NULL)
561 {
562 while (left->right != (NodeInfo *) NULL)
563 left=left->right;
564 left->right=right;
565 }
cristyf84a1932010-01-03 18:00:18 +0000566 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000567 return(MagickTrue);
568 }
569 }
cristyf84a1932010-01-03 18:00:18 +0000570 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000571 return(MagickFalse);
572}
573
574/*
575%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
576% %
577% %
578% %
579% D e l e t e N o d e F r o m S p l a y T r e e %
580% %
581% %
582% %
583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
584%
cristy4c0eee22012-03-22 18:32:34 +0000585% DeleteNodeFromSplayTree() deletes a node from the splay-tree. It returns
cristy9767b952012-03-22 18:31:22 +0000586% MagickTrue if the option is found and successfully deleted from the
587% splay-tree.
anthonyebb73a22012-03-22 14:25:52 +0000588%
cristy3ed852e2009-09-05 21:47:34 +0000589% The format of the DeleteNodeFromSplayTree method is:
590%
591% MagickBooleanType DeleteNodeFromSplayTree(SplayTreeInfo *splay_tree,
592% const void *key)
593%
594% A description of each parameter follows:
595%
596% o splay_tree: the splay-tree info.
597%
598% o key: the key.
599%
600*/
601MagickExport MagickBooleanType DeleteNodeFromSplayTree(
602 SplayTreeInfo *splay_tree,const void *key)
603{
604 int
605 compare;
606
607 register NodeInfo
608 *left,
609 *right;
610
611 assert(splay_tree != (SplayTreeInfo *) NULL);
612 assert(splay_tree->signature == MagickSignature);
613 if (splay_tree->debug != MagickFalse)
614 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
615 if (splay_tree->root == (NodeInfo *) NULL)
616 return(MagickFalse);
cristyf84a1932010-01-03 18:00:18 +0000617 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000618 SplaySplayTree(splay_tree,key);
619 splay_tree->key=(void *) NULL;
620 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
621 compare=splay_tree->compare(splay_tree->root->key,key);
622 else
623 compare=(splay_tree->root->key > key) ? 1 :
624 ((splay_tree->root->key < key) ? -1 : 0);
625 if (compare != 0)
626 {
cristyf84a1932010-01-03 18:00:18 +0000627 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000628 return(MagickFalse);
629 }
630 left=splay_tree->root->left;
631 right=splay_tree->root->right;
632 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
633 (splay_tree->root->value != (void *) NULL))
634 splay_tree->root->value=splay_tree->relinquish_value(
635 splay_tree->root->value);
636 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
637 (splay_tree->root->key != (void *) NULL))
638 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
639 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
640 splay_tree->nodes--;
641 if (left == (NodeInfo *) NULL)
642 {
643 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +0000644 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000645 return(MagickTrue);
646 }
647 splay_tree->root=left;
648 if (right != (NodeInfo *) NULL)
649 {
650 while (left->right != (NodeInfo *) NULL)
651 left=left->right;
652 left->right=right;
653 }
cristyf84a1932010-01-03 18:00:18 +0000654 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000655 return(MagickTrue);
656}
657
658/*
659%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
660% %
661% %
662% %
663% D e s t r o y S p l a y T r e e %
664% %
665% %
666% %
667%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
668%
669% DestroySplayTree() destroys the splay-tree.
670%
671% The format of the DestroySplayTree method is:
672%
673% SplayTreeInfo *DestroySplayTree(SplayTreeInfo *splay_tree)
674%
675% A description of each parameter follows:
676%
677% o splay_tree: the splay tree.
678%
679*/
680MagickExport SplayTreeInfo *DestroySplayTree(SplayTreeInfo *splay_tree)
681{
682 NodeInfo
683 *node;
684
685 register NodeInfo
686 *active,
687 *pend;
688
cristyf84a1932010-01-03 18:00:18 +0000689 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000690 if (splay_tree->root != (NodeInfo *) NULL)
691 {
cristy3ed852e2009-09-05 21:47:34 +0000692 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
693 (splay_tree->root->value != (void *) NULL))
694 splay_tree->root->value=splay_tree->relinquish_value(
695 splay_tree->root->value);
cristy6f24b182010-09-29 22:02:52 +0000696 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
697 (splay_tree->root->key != (void *) NULL))
698 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
699 splay_tree->root->key=(void *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000700 for (pend=splay_tree->root; pend != (NodeInfo *) NULL; )
701 {
702 active=pend;
703 for (pend=(NodeInfo *) NULL; active != (NodeInfo *) NULL; )
704 {
705 if (active->left != (NodeInfo *) NULL)
706 {
cristy3ed852e2009-09-05 21:47:34 +0000707 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
708 (active->left->value != (void *) NULL))
709 active->left->value=splay_tree->relinquish_value(
710 active->left->value);
cristy6f24b182010-09-29 22:02:52 +0000711 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
712 (active->left->key != (void *) NULL))
713 active->left->key=splay_tree->relinquish_key(active->left->key);
714 active->left->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +0000715 pend=active->left;
716 }
717 if (active->right != (NodeInfo *) NULL)
718 {
cristy6f24b182010-09-29 22:02:52 +0000719 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
720 (active->right->value != (void *) NULL))
721 active->right->value=splay_tree->relinquish_value(
722 active->right->value);
cristy3ed852e2009-09-05 21:47:34 +0000723 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
724 (active->right->key != (void *) NULL))
725 active->right->key=splay_tree->relinquish_key(
726 active->right->key);
727 active->right->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +0000728 pend=active->right;
729 }
730 node=active;
731 active=(NodeInfo *) node->key;
732 node=(NodeInfo *) RelinquishMagickMemory(node);
733 }
734 }
735 }
736 splay_tree->signature=(~MagickSignature);
cristyf84a1932010-01-03 18:00:18 +0000737 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000738 DestroySemaphoreInfo(&splay_tree->semaphore);
739 splay_tree=(SplayTreeInfo *) RelinquishMagickMemory(splay_tree);
740 return(splay_tree);
741}
742
743/*
744%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
745% %
746% %
747% %
748% G e t N e x t K e y I n S p l a y T r e e %
749% %
750% %
751% %
752%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
753%
754% GetNextKeyInSplayTree() gets the next key in the splay-tree.
755%
756% The format of the GetNextKeyInSplayTree method is:
757%
cristy9ce61b92010-05-12 16:30:26 +0000758% const void *GetNextKeyInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000759%
760% A description of each parameter follows:
761%
762% o splay_tree: the splay tree.
763%
764% o key: the key.
765%
766*/
cristy9ce61b92010-05-12 16:30:26 +0000767MagickExport const void *GetNextKeyInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000768{
769 register NodeInfo
770 *node;
771
772 void
773 *key;
774
775 assert(splay_tree != (SplayTreeInfo *) NULL);
776 assert(splay_tree->signature == MagickSignature);
777 if (splay_tree->debug != MagickFalse)
778 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
779 if ((splay_tree->root == (NodeInfo *) NULL) ||
780 (splay_tree->next == (void *) NULL))
781 return((void *) NULL);
cristyf84a1932010-01-03 18:00:18 +0000782 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000783 SplaySplayTree(splay_tree,splay_tree->next);
784 splay_tree->next=(void *) NULL;
785 node=splay_tree->root->right;
786 if (node != (NodeInfo *) NULL)
787 {
788 while (node->left != (NodeInfo *) NULL)
789 node=node->left;
790 splay_tree->next=node->key;
791 }
792 key=splay_tree->root->key;
cristyf84a1932010-01-03 18:00:18 +0000793 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000794 return(key);
795}
796
797/*
798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
799% %
800% %
801% %
802% G e t N e x t V a l u e I n S p l a y T r e e %
803% %
804% %
805% %
806%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
807%
808% GetNextValueInSplayTree() gets the next value in the splay-tree.
809%
810% The format of the GetNextValueInSplayTree method is:
811%
cristy9ce61b92010-05-12 16:30:26 +0000812% const void *GetNextValueInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000813%
814% A description of each parameter follows:
815%
816% o splay_tree: the splay tree.
817%
818% o key: the key.
819%
820*/
cristy9ce61b92010-05-12 16:30:26 +0000821MagickExport const void *GetNextValueInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000822{
823 register NodeInfo
824 *node;
825
826 void
827 *value;
828
829 assert(splay_tree != (SplayTreeInfo *) NULL);
830 assert(splay_tree->signature == MagickSignature);
831 if (splay_tree->debug != MagickFalse)
832 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
833 if ((splay_tree->root == (NodeInfo *) NULL) ||
834 (splay_tree->next == (void *) NULL))
835 return((void *) NULL);
cristyf84a1932010-01-03 18:00:18 +0000836 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000837 SplaySplayTree(splay_tree,splay_tree->next);
838 splay_tree->next=(void *) NULL;
839 node=splay_tree->root->right;
840 if (node != (NodeInfo *) NULL)
841 {
842 while (node->left != (NodeInfo *) NULL)
843 node=node->left;
844 splay_tree->next=node->key;
845 }
846 value=splay_tree->root->value;
cristyf84a1932010-01-03 18:00:18 +0000847 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000848 return(value);
849}
850
851/*
852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853% %
854% %
855% %
856% G e t V a l u e F r o m S p l a y T r e e %
857% %
858% %
859% %
860%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861%
862% GetValueFromSplayTree() gets a value from the splay-tree by its key.
863%
cristy9ce61b92010-05-12 16:30:26 +0000864% Note, the value is a constant. Do not attempt to free it.
anthony580609e2010-05-12 02:27:05 +0000865%
cristy3ed852e2009-09-05 21:47:34 +0000866% The format of the GetValueFromSplayTree method is:
867%
cristy9ce61b92010-05-12 16:30:26 +0000868% const void *GetValueFromSplayTree(SplayTreeInfo *splay_tree,
869% const void *key)
cristy3ed852e2009-09-05 21:47:34 +0000870%
871% A description of each parameter follows:
872%
873% o splay_tree: the splay tree.
874%
875% o key: the key.
876%
877*/
cristy9ce61b92010-05-12 16:30:26 +0000878MagickExport const void *GetValueFromSplayTree(SplayTreeInfo *splay_tree,
cristy3ed852e2009-09-05 21:47:34 +0000879 const void *key)
880{
881 int
882 compare;
883
884 void
885 *value;
886
887 assert(splay_tree != (SplayTreeInfo *) NULL);
888 assert(splay_tree->signature == MagickSignature);
889 if (splay_tree->debug != MagickFalse)
890 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
891 if (splay_tree->root == (NodeInfo *) NULL)
892 return((void *) NULL);
cristyf84a1932010-01-03 18:00:18 +0000893 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000894 SplaySplayTree(splay_tree,key);
895 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
896 compare=splay_tree->compare(splay_tree->root->key,key);
897 else
898 compare=(splay_tree->root->key > key) ? 1 :
899 ((splay_tree->root->key < key) ? -1 : 0);
900 if (compare != 0)
901 {
cristyf84a1932010-01-03 18:00:18 +0000902 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000903 return((void *) NULL);
904 }
905 value=splay_tree->root->value;
cristyf84a1932010-01-03 18:00:18 +0000906 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000907 return(value);
908}
909
910/*
911%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
912% %
913% %
914% %
915% G e t N u m b e r O f N o d e s I n S p l a y T r e e %
916% %
917% %
918% %
919%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
920%
921% GetNumberOfNodesInSplayTree() returns the number of nodes in the splay-tree.
922%
923% The format of the GetNumberOfNodesInSplayTree method is:
924%
cristybb503372010-05-27 20:51:26 +0000925% size_t GetNumberOfNodesInSplayTree(
cristy3ed852e2009-09-05 21:47:34 +0000926% const SplayTreeInfo *splay_tree)
927%
928% A description of each parameter follows:
929%
930% o splay_tree: the splay tree.
931%
932*/
cristybb503372010-05-27 20:51:26 +0000933MagickExport size_t GetNumberOfNodesInSplayTree(
cristy3ed852e2009-09-05 21:47:34 +0000934 const SplayTreeInfo *splay_tree)
935{
936 assert(splay_tree != (SplayTreeInfo *) NULL);
937 assert(splay_tree->signature == MagickSignature);
938 if (splay_tree->debug != MagickFalse)
939 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
940 return(splay_tree->nodes);
941}
942
943/*
944%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945% %
946% %
947% %
948% I t e r a t e O v e r S p l a y T r e e %
949% %
950% %
951% %
952%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953%
954% IterateOverSplayTree() iterates over the splay-tree.
955%
956% The format of the IterateOverSplayTree method is:
957%
958% int IterateOverSplayTree(SplayTreeInfo *splay_tree,
959% int (*method)(NodeInfo *,void *),const void *value)
960%
961% A description of each parameter follows:
962%
963% o splay_tree: the splay-tree info.
964%
965% o method: the method.
966%
967% o value: the value.
968%
969*/
970static int IterateOverSplayTree(SplayTreeInfo *splay_tree,
971 int (*method)(NodeInfo *,const void *),const void *value)
972{
973 typedef enum
974 {
975 LeftTransition,
976 RightTransition,
977 DownTransition,
978 UpTransition
979 } TransitionType;
980
981 int
982 status;
983
984 MagickBooleanType
985 final_transition;
986
987 NodeInfo
988 **nodes;
989
cristybb503372010-05-27 20:51:26 +0000990 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000991 i;
992
993 register NodeInfo
994 *node;
995
996 TransitionType
997 transition;
998
999 unsigned char
1000 *transitions;
1001
1002 if (splay_tree->root == (NodeInfo *) NULL)
1003 return(0);
1004 nodes=(NodeInfo **) AcquireQuantumMemory((size_t) splay_tree->nodes,
1005 sizeof(*nodes));
1006 transitions=(unsigned char *) AcquireQuantumMemory((size_t) splay_tree->nodes,
1007 sizeof(*transitions));
1008 if ((nodes == (NodeInfo **) NULL) || (transitions == (unsigned char *) NULL))
1009 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1010 status=0;
1011 final_transition=MagickFalse;
1012 nodes[0]=splay_tree->root;
1013 transitions[0]=(unsigned char) LeftTransition;
1014 for (i=0; final_transition == MagickFalse; )
1015 {
1016 node=nodes[i];
1017 transition=(TransitionType) transitions[i];
1018 switch (transition)
1019 {
1020 case LeftTransition:
1021 {
1022 transitions[i]=(unsigned char) DownTransition;
1023 if (node->left == (NodeInfo *) NULL)
1024 break;
1025 i++;
1026 nodes[i]=node->left;
1027 transitions[i]=(unsigned char) LeftTransition;
1028 break;
1029 }
1030 case RightTransition:
1031 {
1032 transitions[i]=(unsigned char) UpTransition;
1033 if (node->right == (NodeInfo *) NULL)
1034 break;
1035 i++;
1036 nodes[i]=node->right;
1037 transitions[i]=(unsigned char) LeftTransition;
1038 break;
1039 }
1040 case DownTransition:
1041 default:
1042 {
1043 transitions[i]=(unsigned char) RightTransition;
1044 status=(*method)(node,value);
1045 if (status != 0)
1046 final_transition=MagickTrue;
1047 break;
1048 }
1049 case UpTransition:
1050 {
1051 if (i == 0)
1052 {
1053 final_transition=MagickTrue;
1054 break;
1055 }
1056 i--;
1057 break;
1058 }
1059 }
1060 }
1061 nodes=(NodeInfo **) RelinquishMagickMemory(nodes);
1062 transitions=(unsigned char *) RelinquishMagickMemory(transitions);
1063 return(status);
1064}
1065
1066/*
1067%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1068% %
1069% %
1070% %
1071% N e w S p l a y T r e e %
1072% %
1073% %
1074% %
1075%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1076%
1077% NewSplayTree() returns a pointer to a SplayTreeInfo structure initialized
1078% to default values.
1079%
1080% The format of the NewSplayTree method is:
1081%
1082% SplayTreeInfo *NewSplayTree(int (*compare)(const void *,const void *),
1083% void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1084%
1085% A description of each parameter follows:
1086%
1087% o compare: the compare method.
1088%
1089% o relinquish_key: the key deallocation method, typically
1090% RelinquishMagickMemory(), called whenever a key is removed from the
1091% splay-tree.
1092%
1093% o relinquish_value: the value deallocation method; typically
1094% RelinquishMagickMemory(), called whenever a value object is removed from
1095% the splay-tree.
1096%
1097*/
1098MagickExport SplayTreeInfo *NewSplayTree(
1099 int (*compare)(const void *,const void *),void *(*relinquish_key)(void *),
1100 void *(*relinquish_value)(void *))
1101{
1102 SplayTreeInfo
1103 *splay_tree;
1104
cristy73bd4a52010-10-05 11:24:23 +00001105 splay_tree=(SplayTreeInfo *) AcquireMagickMemory(sizeof(*splay_tree));
cristy3ed852e2009-09-05 21:47:34 +00001106 if (splay_tree == (SplayTreeInfo *) NULL)
1107 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1108 (void) ResetMagickMemory(splay_tree,0,sizeof(*splay_tree));
1109 splay_tree->root=(NodeInfo *) NULL;
1110 splay_tree->compare=compare;
1111 splay_tree->relinquish_key=relinquish_key;
1112 splay_tree->relinquish_value=relinquish_value;
1113 splay_tree->balance=MagickFalse;
1114 splay_tree->key=(void *) NULL;
1115 splay_tree->next=(void *) NULL;
1116 splay_tree->nodes=0;
1117 splay_tree->debug=IsEventLogging();
1118 splay_tree->semaphore=AllocateSemaphoreInfo();
1119 splay_tree->signature=MagickSignature;
1120 return(splay_tree);
1121}
1122
1123/*
1124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1125% %
1126% %
1127% %
1128% R e m o v e N o d e B y V a l u e F r o m S p l a y T r e e %
1129% %
1130% %
1131% %
1132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1133%
1134% RemoveNodeByValueFromSplayTree() removes a node by value from the splay-tree
1135% and returns its key.
1136%
1137% The format of the RemoveNodeByValueFromSplayTree method is:
1138%
1139% void *RemoveNodeByValueFromSplayTree(SplayTreeInfo *splay_tree,
1140% const void *value)
1141%
1142% A description of each parameter follows:
1143%
1144% o splay_tree: the splay-tree info.
1145%
1146% o value: the value.
1147%
1148*/
1149MagickExport void *RemoveNodeByValueFromSplayTree(SplayTreeInfo *splay_tree,
1150 const void *value)
1151{
1152 register NodeInfo
1153 *next,
1154 *node;
1155
1156 void
1157 *key;
1158
1159 assert(splay_tree != (SplayTreeInfo *) NULL);
1160 assert(splay_tree->signature == MagickSignature);
1161 if (splay_tree->debug != MagickFalse)
1162 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1163 key=(void *) NULL;
1164 if (splay_tree->root == (NodeInfo *) NULL)
1165 return(key);
cristyf84a1932010-01-03 18:00:18 +00001166 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001167 next=(NodeInfo *) GetFirstSplayTreeNode(splay_tree);
1168 while (next != (NodeInfo *) NULL)
1169 {
1170 SplaySplayTree(splay_tree,next);
1171 next=(NodeInfo *) NULL;
1172 node=splay_tree->root->right;
1173 if (node != (NodeInfo *) NULL)
1174 {
1175 while (node->left != (NodeInfo *) NULL)
1176 node=node->left;
1177 next=(NodeInfo *) node->key;
1178 }
1179 if (splay_tree->root->value == value)
1180 {
1181 int
1182 compare;
1183
1184 register NodeInfo
1185 *left,
1186 *right;
1187
1188 /*
1189 We found the node that matches the value; now remove it.
1190 */
1191 key=splay_tree->root->key;
1192 SplaySplayTree(splay_tree,key);
1193 splay_tree->key=(void *) NULL;
1194 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1195 compare=splay_tree->compare(splay_tree->root->key,key);
1196 else
1197 compare=(splay_tree->root->key > key) ? 1 :
1198 ((splay_tree->root->key < key) ? -1 : 0);
1199 if (compare != 0)
1200 {
cristyf84a1932010-01-03 18:00:18 +00001201 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001202 return(key);
1203 }
1204 left=splay_tree->root->left;
1205 right=splay_tree->root->right;
1206 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1207 (splay_tree->root->value != (void *) NULL))
1208 splay_tree->root->value=splay_tree->relinquish_value(
1209 splay_tree->root->value);
1210 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
1211 splay_tree->nodes--;
1212 if (left == (NodeInfo *) NULL)
1213 {
1214 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +00001215 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001216 return(key);
1217 }
1218 splay_tree->root=left;
1219 if (right != (NodeInfo *) NULL)
1220 {
1221 while (left->right != (NodeInfo *) NULL)
1222 left=left->right;
1223 left->right=right;
1224 }
cristyf84a1932010-01-03 18:00:18 +00001225 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001226 return(key);
1227 }
1228 }
cristyf84a1932010-01-03 18:00:18 +00001229 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001230 return(key);
1231}
1232
1233/*
1234%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1235% %
1236% %
1237% %
1238% R e m o v e N o d e F r o m S p l a y T r e e %
1239% %
1240% %
1241% %
1242%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1243%
1244% RemoveNodeFromSplayTree() removes a node from the splay-tree and returns its
1245% value.
1246%
1247% The format of the RemoveNodeFromSplayTree method is:
1248%
1249% void *RemoveNodeFromSplayTree(SplayTreeInfo *splay_tree,const void *key)
1250%
1251% A description of each parameter follows:
1252%
1253% o splay_tree: the splay-tree info.
1254%
1255% o key: the key.
1256%
1257*/
1258MagickExport void *RemoveNodeFromSplayTree(SplayTreeInfo *splay_tree,
1259 const void *key)
1260{
1261 int
1262 compare;
1263
1264 register NodeInfo
1265 *left,
1266 *right;
1267
1268 void
1269 *value;
1270
1271 assert(splay_tree != (SplayTreeInfo *) NULL);
1272 assert(splay_tree->signature == MagickSignature);
1273 if (splay_tree->debug != MagickFalse)
1274 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1275 value=(void *) NULL;
1276 if (splay_tree->root == (NodeInfo *) NULL)
1277 return(value);
cristyf84a1932010-01-03 18:00:18 +00001278 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001279 SplaySplayTree(splay_tree,key);
1280 splay_tree->key=(void *) NULL;
1281 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1282 compare=splay_tree->compare(splay_tree->root->key,key);
1283 else
1284 compare=(splay_tree->root->key > key) ? 1 :
1285 ((splay_tree->root->key < key) ? -1 : 0);
1286 if (compare != 0)
1287 {
cristyf84a1932010-01-03 18:00:18 +00001288 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001289 return(value);
1290 }
1291 left=splay_tree->root->left;
1292 right=splay_tree->root->right;
1293 value=splay_tree->root->value;
1294 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1295 (splay_tree->root->key != (void *) NULL))
1296 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
1297 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
1298 splay_tree->nodes--;
1299 if (left == (NodeInfo *) NULL)
1300 {
1301 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +00001302 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001303 return(value);
1304 }
1305 splay_tree->root=left;
1306 if (right != (NodeInfo *) NULL)
1307 {
1308 while (left->right != (NodeInfo *) NULL)
1309 left=left->right;
1310 left->right=right;
1311 }
cristyf84a1932010-01-03 18:00:18 +00001312 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001313 return(value);
1314}
1315
1316/*
1317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1318% %
1319% %
1320% %
1321% R e s e t S p l a y T r e e %
1322% %
1323% %
1324% %
1325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1326%
1327% ResetSplayTree() resets the splay-tree. That is, it deletes all the nodes
1328% from the tree.
1329%
1330% The format of the ResetSplayTree method is:
1331%
1332% ResetSplayTree(SplayTreeInfo *splay_tree)
1333%
1334% A description of each parameter follows:
1335%
1336% o splay_tree: the splay tree.
1337%
1338*/
1339MagickExport void ResetSplayTree(SplayTreeInfo *splay_tree)
1340{
1341 NodeInfo
1342 *node;
1343
1344 register NodeInfo
1345 *active,
1346 *pend;
1347
1348 assert(splay_tree != (SplayTreeInfo *) NULL);
1349 assert(splay_tree->signature == MagickSignature);
1350 if (splay_tree->debug != MagickFalse)
1351 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00001352 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001353 if (splay_tree->root != (NodeInfo *) NULL)
1354 {
cristy3ed852e2009-09-05 21:47:34 +00001355 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1356 (splay_tree->root->value != (void *) NULL))
1357 splay_tree->root->value=splay_tree->relinquish_value(
1358 splay_tree->root->value);
cristy6f24b182010-09-29 22:02:52 +00001359 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1360 (splay_tree->root->key != (void *) NULL))
1361 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
1362 splay_tree->root->key=(void *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00001363 for (pend=splay_tree->root; pend != (NodeInfo *) NULL; )
1364 {
1365 active=pend;
1366 for (pend=(NodeInfo *) NULL; active != (NodeInfo *) NULL; )
1367 {
1368 if (active->left != (NodeInfo *) NULL)
1369 {
cristy3ed852e2009-09-05 21:47:34 +00001370 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1371 (active->left->value != (void *) NULL))
1372 active->left->value=splay_tree->relinquish_value(
1373 active->left->value);
cristy6f24b182010-09-29 22:02:52 +00001374 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1375 (active->left->key != (void *) NULL))
1376 active->left->key=splay_tree->relinquish_key(active->left->key);
1377 active->left->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +00001378 pend=active->left;
1379 }
1380 if (active->right != (NodeInfo *) NULL)
1381 {
cristy6f24b182010-09-29 22:02:52 +00001382 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1383 (active->right->value != (void *) NULL))
1384 active->right->value=splay_tree->relinquish_value(
1385 active->right->value);
cristy3ed852e2009-09-05 21:47:34 +00001386 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1387 (active->right->key != (void *) NULL))
1388 active->right->key=splay_tree->relinquish_key(
1389 active->right->key);
1390 active->right->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +00001391 pend=active->right;
1392 }
1393 node=active;
1394 active=(NodeInfo *) node->key;
1395 node=(NodeInfo *) RelinquishMagickMemory(node);
1396 }
1397 }
1398 }
1399 splay_tree->root=(NodeInfo *) NULL;
1400 splay_tree->key=(void *) NULL;
1401 splay_tree->next=(void *) NULL;
1402 splay_tree->nodes=0;
1403 splay_tree->balance=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001404 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001405}
1406
1407/*
1408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1409% %
1410% %
1411% %
1412% R e s e t S p l a y T r e e I t e r a t o r %
1413% %
1414% %
1415% %
1416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1417%
1418% ResetSplayTreeIterator() resets the splay-tree iterator. Use it in
1419% conjunction with GetNextValueInSplayTree() to iterate over all the nodes in
1420% the splay-tree.
1421%
1422% The format of the ResetSplayTreeIterator method is:
1423%
1424% ResetSplayTreeIterator(SplayTreeInfo *splay_tree)
1425%
1426% A description of each parameter follows:
1427%
1428% o splay_tree: the splay tree.
1429%
1430*/
1431MagickExport void ResetSplayTreeIterator(SplayTreeInfo *splay_tree)
1432{
1433 assert(splay_tree != (SplayTreeInfo *) NULL);
1434 assert(splay_tree->signature == MagickSignature);
1435 if (splay_tree->debug != MagickFalse)
1436 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00001437 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001438 splay_tree->next=GetFirstSplayTreeNode(splay_tree);
cristyf84a1932010-01-03 18:00:18 +00001439 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001440}
1441
1442/*
1443%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1444% %
1445% %
1446% %
1447% S p l a y S p l a y T r e e %
1448% %
1449% %
1450% %
1451%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1452%
1453% SplaySplayTree() splays the splay-tree.
1454%
1455% The format of the SplaySplayTree method is:
1456%
1457% void SplaySplayTree(SplayTreeInfo *splay_tree,const void *key,
1458% NodeInfo **node,NodeInfo **parent,NodeInfo **grandparent)
1459%
1460% A description of each parameter follows:
1461%
1462% o splay_tree: the splay-tree info.
1463%
1464% o key: the key.
1465%
1466% o node: the node.
1467%
1468% o parent: the parent node.
1469%
1470% o grandparent: the grandparent node.
1471%
1472*/
1473
cristybb503372010-05-27 20:51:26 +00001474static NodeInfo *Splay(SplayTreeInfo *splay_tree,const size_t depth,
cristy3ed852e2009-09-05 21:47:34 +00001475 const void *key,NodeInfo **node,NodeInfo **parent,NodeInfo **grandparent)
1476{
1477 int
1478 compare;
1479
1480 NodeInfo
1481 **next;
1482
1483 register NodeInfo
1484 *n,
1485 *p;
1486
1487 n=(*node);
1488 if (n == (NodeInfo *) NULL)
1489 return(*parent);
1490 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1491 compare=splay_tree->compare(n->key,key);
1492 else
1493 compare=(n->key > key) ? 1 : ((n->key < key) ? -1 : 0);
1494 next=(NodeInfo **) NULL;
1495 if (compare > 0)
1496 next=(&n->left);
1497 else
1498 if (compare < 0)
1499 next=(&n->right);
1500 if (next != (NodeInfo **) NULL)
1501 {
1502 if (depth >= MaxSplayTreeDepth)
1503 {
1504 splay_tree->balance=MagickTrue;
1505 return(n);
1506 }
1507 n=Splay(splay_tree,depth+1,key,next,node,parent);
1508 if ((n != *node) || (splay_tree->balance != MagickFalse))
1509 return(n);
1510 }
1511 if (parent == (NodeInfo **) NULL)
1512 return(n);
1513 if (grandparent == (NodeInfo **) NULL)
1514 {
1515 if (n == (*parent)->left)
1516 {
1517 *node=n->right;
1518 n->right=(*parent);
1519 }
1520 else
1521 {
1522 *node=n->left;
1523 n->left=(*parent);
1524 }
1525 *parent=n;
1526 return(n);
1527 }
1528 if ((n == (*parent)->left) && (*parent == (*grandparent)->left))
1529 {
1530 p=(*parent);
1531 (*grandparent)->left=p->right;
1532 p->right=(*grandparent);
1533 p->left=n->right;
1534 n->right=p;
1535 *grandparent=n;
1536 return(n);
1537 }
1538 if ((n == (*parent)->right) && (*parent == (*grandparent)->right))
1539 {
1540 p=(*parent);
1541 (*grandparent)->right=p->left;
1542 p->left=(*grandparent);
1543 p->right=n->left;
1544 n->left=p;
1545 *grandparent=n;
1546 return(n);
1547 }
1548 if (n == (*parent)->left)
1549 {
1550 (*parent)->left=n->right;
1551 n->right=(*parent);
1552 (*grandparent)->right=n->left;
1553 n->left=(*grandparent);
1554 *grandparent=n;
1555 return(n);
1556 }
1557 (*parent)->right=n->left;
1558 n->left=(*parent);
1559 (*grandparent)->left=n->right;
1560 n->right=(*grandparent);
1561 *grandparent=n;
1562 return(n);
1563}
1564
1565static void SplaySplayTree(SplayTreeInfo *splay_tree,const void *key)
1566{
1567 if (splay_tree->root == (NodeInfo *) NULL)
1568 return;
1569 if (splay_tree->key != (void *) NULL)
1570 {
1571 int
1572 compare;
1573
1574 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1575 compare=splay_tree->compare(splay_tree->root->key,key);
1576 else
1577 compare=(splay_tree->key > key) ? 1 :
1578 ((splay_tree->key < key) ? -1 : 0);
1579 if (compare == 0)
1580 return;
1581 }
1582 (void) Splay(splay_tree,0UL,key,&splay_tree->root,(NodeInfo **) NULL,
1583 (NodeInfo **) NULL);
1584 if (splay_tree->balance != MagickFalse)
1585 {
1586 BalanceSplayTree(splay_tree);
1587 (void) Splay(splay_tree,0UL,key,&splay_tree->root,(NodeInfo **) NULL,
1588 (NodeInfo **) NULL);
1589 if (splay_tree->balance != MagickFalse)
1590 ThrowFatalException(ResourceLimitFatalError,
1591 "MemoryAllocationFailed");
1592 }
1593 splay_tree->key=(void *) key;
1594}