blob: c54f21bdcb2f4a89f7c208e0b711274580e17e83 [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.
135% The both key and value is used as is, without coping or cloning.
cristy3ed852e2009-09-05 21:47:34 +0000136%
137% The format of the AddValueToSplayTree method is:
138%
139% MagickBooleanType AddValueToSplayTree(SplayTreeInfo *splay_tree,
140% const void *key,const void *value)
141%
142% A description of each parameter follows:
143%
144% o splay_tree: the splay-tree info.
145%
146% o key: the key.
147%
148% o value: the value.
149%
150*/
151MagickExport MagickBooleanType AddValueToSplayTree(SplayTreeInfo *splay_tree,
152 const void *key,const void *value)
153{
154 int
155 compare;
156
157 register NodeInfo
158 *node;
159
cristyf84a1932010-01-03 18:00:18 +0000160 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000161 SplaySplayTree(splay_tree,key);
162 compare=0;
163 if (splay_tree->root != (NodeInfo *) NULL)
164 {
165 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
166 compare=splay_tree->compare(splay_tree->root->key,key);
167 else
168 compare=(splay_tree->root->key > key) ? 1 :
169 ((splay_tree->root->key < key) ? -1 : 0);
170 if (compare == 0)
171 {
cristy6f24b182010-09-29 22:02:52 +0000172 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
173 (splay_tree->root->value != (void *) NULL))
174 splay_tree->root->value=splay_tree->relinquish_value(
175 splay_tree->root->value);
cristy3ed852e2009-09-05 21:47:34 +0000176 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
177 (splay_tree->root->key != (void *) NULL))
178 splay_tree->root->key=splay_tree->relinquish_key(
179 splay_tree->root->key);
180 splay_tree->root->key=(void *) key;
cristy3ed852e2009-09-05 21:47:34 +0000181 splay_tree->root->value=(void *) value;
cristyf84a1932010-01-03 18:00:18 +0000182 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000183 return(MagickTrue);
184 }
185 }
cristy73bd4a52010-10-05 11:24:23 +0000186 node=(NodeInfo *) AcquireMagickMemory(sizeof(*node));
cristy3ed852e2009-09-05 21:47:34 +0000187 if (node == (NodeInfo *) NULL)
188 {
cristyf84a1932010-01-03 18:00:18 +0000189 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000190 return(MagickFalse);
191 }
192 node->key=(void *) key;
193 node->value=(void *) value;
194 if (splay_tree->root == (NodeInfo *) NULL)
195 {
196 node->left=(NodeInfo *) NULL;
197 node->right=(NodeInfo *) NULL;
198 }
199 else
200 if (compare < 0)
201 {
202 node->left=splay_tree->root;
203 node->right=node->left->right;
204 node->left->right=(NodeInfo *) NULL;
205 }
206 else
207 {
208 node->right=splay_tree->root;
209 node->left=node->right->left;
210 node->right->left=(NodeInfo *) NULL;
211 }
212 splay_tree->root=node;
213 splay_tree->key=(void *) NULL;
214 splay_tree->nodes++;
cristyf84a1932010-01-03 18:00:18 +0000215 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000216 return(MagickTrue);
217}
218
219/*
220%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221% %
222% %
223% %
224% B a l a n c e S p l a y T r e e %
225% %
226% %
227% %
228%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
229%
230% BalanceSplayTree() balances the splay-tree.
231%
232% The format of the BalanceSplayTree method is:
233%
234% void *BalanceSplayTree(SplayTreeInfo *splay_tree,const void *key)
235%
236% A description of each parameter follows:
237%
238% o splay_tree: the splay-tree info.
239%
240% o key: the key.
241%
242*/
243
cristybb503372010-05-27 20:51:26 +0000244static NodeInfo *LinkSplayTreeNodes(NodeInfo **nodes,const size_t low,
245 const size_t high)
cristy3ed852e2009-09-05 21:47:34 +0000246{
247 register NodeInfo
248 *node;
249
cristybb503372010-05-27 20:51:26 +0000250 size_t
cristy3ed852e2009-09-05 21:47:34 +0000251 bisect;
252
253 bisect=low+(high-low)/2;
254 node=nodes[bisect];
255 if ((low+1) > bisect)
256 node->left=(NodeInfo *) NULL;
257 else
258 node->left=LinkSplayTreeNodes(nodes,low,bisect-1);
259 if ((bisect+1) > high)
260 node->right=(NodeInfo *) NULL;
261 else
262 node->right=LinkSplayTreeNodes(nodes,bisect+1,high);
263 return(node);
264}
265
266static int SplayTreeToNodeArray(NodeInfo *node,const void *nodes)
267{
268 register const NodeInfo
269 ***p;
270
271 p=(const NodeInfo ***) nodes;
272 *(*p)=node;
273 (*p)++;
274 return(0);
275}
276
277static void BalanceSplayTree(SplayTreeInfo *splay_tree)
278{
279 NodeInfo
280 **node,
281 **nodes;
282
283 if (splay_tree->nodes <= 2)
284 {
285 splay_tree->balance=MagickFalse;
286 return;
287 }
288 nodes=(NodeInfo **) AcquireQuantumMemory((size_t) splay_tree->nodes,
289 sizeof(*nodes));
290 if (nodes == (NodeInfo **) NULL)
291 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
292 node=nodes;
293 (void) IterateOverSplayTree(splay_tree,SplayTreeToNodeArray,
294 (const void *) &node);
295 splay_tree->root=LinkSplayTreeNodes(nodes,0,splay_tree->nodes-1);
296 splay_tree->balance=MagickFalse;
297 nodes=(NodeInfo **) RelinquishMagickMemory(nodes);
298}
299
300/*
301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302% %
303% %
304% %
305% C l o n e S p l a y T r e e %
306% %
307% %
308% %
309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310%
311% CloneSplayTree() clones the splay tree.
312%
313% The format of the CloneSplayTree method is:
314%
315% SplayTreeInfo *CloneSplayTree(SplayTreeInfo *splay_tree,
316% void *(*clone_key)(void *),void *(*cline_value)(void *))
317%
318% A description of each parameter follows:
319%
320% o splay_tree: the splay tree.
321%
322% o clone_key: the key clone method, typically ConstantString(), called
323% whenever a key is added to the splay-tree.
324%
325% o clone_value: the value clone method; typically ConstantString(), called
326% whenever a value object is added to the splay-tree.
327%
328*/
cristy7959f822010-03-07 21:47:41 +0000329
330static void *GetFirstSplayTreeNode(SplayTreeInfo *splay_tree)
331{
332 register NodeInfo
333 *node;
334
335 node=splay_tree->root;
336 if (splay_tree->root == (NodeInfo *) NULL)
337 return((NodeInfo *) NULL);
338 while (node->left != (NodeInfo *) NULL)
339 node=node->left;
340 return(node->key);
341}
342
cristy3ed852e2009-09-05 21:47:34 +0000343MagickExport SplayTreeInfo *CloneSplayTree(SplayTreeInfo *splay_tree,
344 void *(*clone_key)(void *),void *(*clone_value)(void *))
345{
cristy7959f822010-03-07 21:47:41 +0000346 register NodeInfo
347 *next,
348 *node;
349
cristy3ed852e2009-09-05 21:47:34 +0000350 SplayTreeInfo
351 *clone_tree;
352
353 assert(splay_tree != (SplayTreeInfo *) NULL);
354 assert(splay_tree->signature == MagickSignature);
355 if (splay_tree->debug != MagickFalse)
356 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
357 clone_tree=NewSplayTree(splay_tree->compare,splay_tree->relinquish_key,
358 splay_tree->relinquish_value);
cristyf84a1932010-01-03 18:00:18 +0000359 LockSemaphoreInfo(splay_tree->semaphore);
cristy7959f822010-03-07 21:47:41 +0000360 if (splay_tree->root == (NodeInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +0000361 {
cristy7959f822010-03-07 21:47:41 +0000362 UnlockSemaphoreInfo(splay_tree->semaphore);
363 return(clone_tree);
cristy3ed852e2009-09-05 21:47:34 +0000364 }
cristy7959f822010-03-07 21:47:41 +0000365 next=(NodeInfo *) GetFirstSplayTreeNode(splay_tree);
366 while (next != (NodeInfo *) NULL)
367 {
368 SplaySplayTree(splay_tree,next);
369 (void) AddValueToSplayTree(clone_tree,clone_key(splay_tree->root->key),
370 clone_value(splay_tree->root->value));
371 next=(NodeInfo *) NULL;
372 node=splay_tree->root->right;
373 if (node != (NodeInfo *) NULL)
374 {
375 while (node->left != (NodeInfo *) NULL)
376 node=node->left;
377 next=(NodeInfo *) node->key;
378 }
379 }
cristyf84a1932010-01-03 18:00:18 +0000380 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000381 return(clone_tree);
382}
383
384/*
385%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386% %
387% %
388% %
389% C o m p a r e S p l a y T r e e S t r i n g %
390% %
391% %
392% %
393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394%
395% CompareSplayTreeString() method finds a node in a splay-tree based on the
396% contents of a string.
397%
398% The format of the CompareSplayTreeString method is:
399%
400% int CompareSplayTreeString(const void *target,const void *source)
401%
402% A description of each parameter follows:
403%
404% o target: the target string.
405%
406% o source: the source string.
407%
408*/
409MagickExport int CompareSplayTreeString(const void *target,const void *source)
410{
411 const char
412 *p,
413 *q;
414
415 p=(const char *) target;
416 q=(const char *) source;
417 return(LocaleCompare(p,q));
418}
419
420/*
421%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422% %
423% %
424% %
425% 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 %
426% %
427% %
428% %
429%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430%
431% CompareSplayTreeStringInfo() finds a node in a splay-tree based on the
432% contents of a string.
433%
434% The format of the CompareSplayTreeStringInfo method is:
435%
436% int CompareSplayTreeStringInfo(const void *target,const void *source)
437%
438% A description of each parameter follows:
439%
440% o target: the target string.
441%
442% o source: the source string.
443%
444*/
445MagickExport int CompareSplayTreeStringInfo(const void *target,
446 const void *source)
447{
448 const StringInfo
449 *p,
450 *q;
451
452 p=(const StringInfo *) target;
453 q=(const StringInfo *) source;
454 return(CompareStringInfo(p,q));
455}
456
457/*
458%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459% %
460% %
461% %
462% 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 %
463% %
464% %
465% %
466%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
467%
468% DeleteNodeByValueFromSplayTree() deletes a node by value from the
469% splay-tree.
470%
471% The format of the DeleteNodeByValueFromSplayTree method is:
472%
473% MagickBooleanType DeleteNodeByValueFromSplayTree(
474% SplayTreeInfo *splay_tree,const void *value)
475%
476% A description of each parameter follows:
477%
478% o splay_tree: the splay-tree info.
479%
480% o value: the value.
481%
482*/
cristy3ed852e2009-09-05 21:47:34 +0000483MagickExport MagickBooleanType DeleteNodeByValueFromSplayTree(
484 SplayTreeInfo *splay_tree,const void *value)
485{
486 register NodeInfo
487 *next,
488 *node;
489
490 assert(splay_tree != (SplayTreeInfo *) NULL);
491 assert(splay_tree->signature == MagickSignature);
492 if (splay_tree->debug != MagickFalse)
493 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +0000494 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000495 if (splay_tree->root == (NodeInfo *) NULL)
496 {
cristyf84a1932010-01-03 18:00:18 +0000497 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000498 return(MagickFalse);
499 }
500 next=(NodeInfo *) GetFirstSplayTreeNode(splay_tree);
501 while (next != (NodeInfo *) NULL)
502 {
503 SplaySplayTree(splay_tree,next);
504 next=(NodeInfo *) NULL;
505 node=splay_tree->root->right;
506 if (node != (NodeInfo *) NULL)
507 {
508 while (node->left != (NodeInfo *) NULL)
509 node=node->left;
510 next=(NodeInfo *) node->key;
511 }
512 if (splay_tree->root->value == value)
513 {
514 int
515 compare;
516
517 register NodeInfo
518 *left,
519 *right;
520
521 void
522 *key;
523
524 /*
525 We found the node that matches the value; now delete it.
526 */
527 key=splay_tree->root->key;
528 SplaySplayTree(splay_tree,key);
529 splay_tree->key=(void *) NULL;
530 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
531 compare=splay_tree->compare(splay_tree->root->key,key);
532 else
533 compare=(splay_tree->root->key > key) ? 1 :
534 ((splay_tree->root->key < key) ? -1 : 0);
535 if (compare != 0)
536 {
cristyf84a1932010-01-03 18:00:18 +0000537 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000538 return(MagickFalse);
539 }
540 left=splay_tree->root->left;
541 right=splay_tree->root->right;
cristy3ed852e2009-09-05 21:47:34 +0000542 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
543 (splay_tree->root->value != (void *) NULL))
544 splay_tree->root->value=splay_tree->relinquish_value(
545 splay_tree->root->value);
cristy6f24b182010-09-29 22:02:52 +0000546 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
547 (splay_tree->root->key != (void *) NULL))
548 splay_tree->root->key=splay_tree->relinquish_key(
549 splay_tree->root->key);
cristy3ed852e2009-09-05 21:47:34 +0000550 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
551 splay_tree->nodes--;
552 if (left == (NodeInfo *) NULL)
553 {
554 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +0000555 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000556 return(MagickTrue);
557 }
558 splay_tree->root=left;
559 if (right != (NodeInfo *) NULL)
560 {
561 while (left->right != (NodeInfo *) NULL)
562 left=left->right;
563 left->right=right;
564 }
cristyf84a1932010-01-03 18:00:18 +0000565 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000566 return(MagickTrue);
567 }
568 }
cristyf84a1932010-01-03 18:00:18 +0000569 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000570 return(MagickFalse);
571}
572
573/*
574%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575% %
576% %
577% %
578% D e l e t e N o d e F r o m S p l a y T r e e %
579% %
580% %
581% %
582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583%
584% DeleteNodeFromSplayTree() deletes a node from the splay-tree.
585%
586% The format of the DeleteNodeFromSplayTree method is:
587%
588% MagickBooleanType DeleteNodeFromSplayTree(SplayTreeInfo *splay_tree,
589% const void *key)
590%
591% A description of each parameter follows:
592%
593% o splay_tree: the splay-tree info.
594%
595% o key: the key.
596%
597*/
598MagickExport MagickBooleanType DeleteNodeFromSplayTree(
599 SplayTreeInfo *splay_tree,const void *key)
600{
601 int
602 compare;
603
604 register NodeInfo
605 *left,
606 *right;
607
608 assert(splay_tree != (SplayTreeInfo *) NULL);
609 assert(splay_tree->signature == MagickSignature);
610 if (splay_tree->debug != MagickFalse)
611 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
612 if (splay_tree->root == (NodeInfo *) NULL)
613 return(MagickFalse);
cristyf84a1932010-01-03 18:00:18 +0000614 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000615 SplaySplayTree(splay_tree,key);
616 splay_tree->key=(void *) NULL;
617 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
618 compare=splay_tree->compare(splay_tree->root->key,key);
619 else
620 compare=(splay_tree->root->key > key) ? 1 :
621 ((splay_tree->root->key < key) ? -1 : 0);
622 if (compare != 0)
623 {
cristyf84a1932010-01-03 18:00:18 +0000624 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000625 return(MagickFalse);
626 }
627 left=splay_tree->root->left;
628 right=splay_tree->root->right;
629 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
630 (splay_tree->root->value != (void *) NULL))
631 splay_tree->root->value=splay_tree->relinquish_value(
632 splay_tree->root->value);
633 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
634 (splay_tree->root->key != (void *) NULL))
635 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
636 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
637 splay_tree->nodes--;
638 if (left == (NodeInfo *) NULL)
639 {
640 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +0000641 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000642 return(MagickTrue);
643 }
644 splay_tree->root=left;
645 if (right != (NodeInfo *) NULL)
646 {
647 while (left->right != (NodeInfo *) NULL)
648 left=left->right;
649 left->right=right;
650 }
cristyf84a1932010-01-03 18:00:18 +0000651 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000652 return(MagickTrue);
653}
654
655/*
656%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
657% %
658% %
659% %
660% D e s t r o y S p l a y T r e e %
661% %
662% %
663% %
664%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
665%
666% DestroySplayTree() destroys the splay-tree.
667%
668% The format of the DestroySplayTree method is:
669%
670% SplayTreeInfo *DestroySplayTree(SplayTreeInfo *splay_tree)
671%
672% A description of each parameter follows:
673%
674% o splay_tree: the splay tree.
675%
676*/
677MagickExport SplayTreeInfo *DestroySplayTree(SplayTreeInfo *splay_tree)
678{
679 NodeInfo
680 *node;
681
682 register NodeInfo
683 *active,
684 *pend;
685
cristyf84a1932010-01-03 18:00:18 +0000686 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000687 if (splay_tree->root != (NodeInfo *) NULL)
688 {
cristy3ed852e2009-09-05 21:47:34 +0000689 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
690 (splay_tree->root->value != (void *) NULL))
691 splay_tree->root->value=splay_tree->relinquish_value(
692 splay_tree->root->value);
cristy6f24b182010-09-29 22:02:52 +0000693 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
694 (splay_tree->root->key != (void *) NULL))
695 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
696 splay_tree->root->key=(void *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000697 for (pend=splay_tree->root; pend != (NodeInfo *) NULL; )
698 {
699 active=pend;
700 for (pend=(NodeInfo *) NULL; active != (NodeInfo *) NULL; )
701 {
702 if (active->left != (NodeInfo *) NULL)
703 {
cristy3ed852e2009-09-05 21:47:34 +0000704 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
705 (active->left->value != (void *) NULL))
706 active->left->value=splay_tree->relinquish_value(
707 active->left->value);
cristy6f24b182010-09-29 22:02:52 +0000708 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
709 (active->left->key != (void *) NULL))
710 active->left->key=splay_tree->relinquish_key(active->left->key);
711 active->left->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +0000712 pend=active->left;
713 }
714 if (active->right != (NodeInfo *) NULL)
715 {
cristy6f24b182010-09-29 22:02:52 +0000716 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
717 (active->right->value != (void *) NULL))
718 active->right->value=splay_tree->relinquish_value(
719 active->right->value);
cristy3ed852e2009-09-05 21:47:34 +0000720 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
721 (active->right->key != (void *) NULL))
722 active->right->key=splay_tree->relinquish_key(
723 active->right->key);
724 active->right->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +0000725 pend=active->right;
726 }
727 node=active;
728 active=(NodeInfo *) node->key;
729 node=(NodeInfo *) RelinquishMagickMemory(node);
730 }
731 }
732 }
733 splay_tree->signature=(~MagickSignature);
cristyf84a1932010-01-03 18:00:18 +0000734 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000735 DestroySemaphoreInfo(&splay_tree->semaphore);
736 splay_tree=(SplayTreeInfo *) RelinquishMagickMemory(splay_tree);
737 return(splay_tree);
738}
739
740/*
741%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
742% %
743% %
744% %
745% G e t N e x t K e y I n S p l a y T r e e %
746% %
747% %
748% %
749%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
750%
751% GetNextKeyInSplayTree() gets the next key in the splay-tree.
752%
753% The format of the GetNextKeyInSplayTree method is:
754%
cristy9ce61b92010-05-12 16:30:26 +0000755% const void *GetNextKeyInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000756%
757% A description of each parameter follows:
758%
759% o splay_tree: the splay tree.
760%
761% o key: the key.
762%
763*/
cristy9ce61b92010-05-12 16:30:26 +0000764MagickExport const void *GetNextKeyInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000765{
766 register NodeInfo
767 *node;
768
769 void
770 *key;
771
772 assert(splay_tree != (SplayTreeInfo *) NULL);
773 assert(splay_tree->signature == MagickSignature);
774 if (splay_tree->debug != MagickFalse)
775 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
776 if ((splay_tree->root == (NodeInfo *) NULL) ||
777 (splay_tree->next == (void *) NULL))
778 return((void *) NULL);
cristyf84a1932010-01-03 18:00:18 +0000779 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000780 SplaySplayTree(splay_tree,splay_tree->next);
781 splay_tree->next=(void *) NULL;
782 node=splay_tree->root->right;
783 if (node != (NodeInfo *) NULL)
784 {
785 while (node->left != (NodeInfo *) NULL)
786 node=node->left;
787 splay_tree->next=node->key;
788 }
789 key=splay_tree->root->key;
cristyf84a1932010-01-03 18:00:18 +0000790 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000791 return(key);
792}
793
794/*
795%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796% %
797% %
798% %
799% G e t N e x t V a l u e I n S p l a y T r e e %
800% %
801% %
802% %
803%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804%
805% GetNextValueInSplayTree() gets the next value in the splay-tree.
806%
807% The format of the GetNextValueInSplayTree method is:
808%
cristy9ce61b92010-05-12 16:30:26 +0000809% const void *GetNextValueInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000810%
811% A description of each parameter follows:
812%
813% o splay_tree: the splay tree.
814%
815% o key: the key.
816%
817*/
cristy9ce61b92010-05-12 16:30:26 +0000818MagickExport const void *GetNextValueInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000819{
820 register NodeInfo
821 *node;
822
823 void
824 *value;
825
826 assert(splay_tree != (SplayTreeInfo *) NULL);
827 assert(splay_tree->signature == MagickSignature);
828 if (splay_tree->debug != MagickFalse)
829 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
830 if ((splay_tree->root == (NodeInfo *) NULL) ||
831 (splay_tree->next == (void *) NULL))
832 return((void *) NULL);
cristyf84a1932010-01-03 18:00:18 +0000833 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000834 SplaySplayTree(splay_tree,splay_tree->next);
835 splay_tree->next=(void *) NULL;
836 node=splay_tree->root->right;
837 if (node != (NodeInfo *) NULL)
838 {
839 while (node->left != (NodeInfo *) NULL)
840 node=node->left;
841 splay_tree->next=node->key;
842 }
843 value=splay_tree->root->value;
cristyf84a1932010-01-03 18:00:18 +0000844 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000845 return(value);
846}
847
848/*
849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850% %
851% %
852% %
853% G e t V a l u e F r o m S p l a y T r e e %
854% %
855% %
856% %
857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858%
859% GetValueFromSplayTree() gets a value from the splay-tree by its key.
860%
cristy9ce61b92010-05-12 16:30:26 +0000861% Note, the value is a constant. Do not attempt to free it.
anthony580609e2010-05-12 02:27:05 +0000862%
cristy3ed852e2009-09-05 21:47:34 +0000863% The format of the GetValueFromSplayTree method is:
864%
cristy9ce61b92010-05-12 16:30:26 +0000865% const void *GetValueFromSplayTree(SplayTreeInfo *splay_tree,
866% const void *key)
cristy3ed852e2009-09-05 21:47:34 +0000867%
868% A description of each parameter follows:
869%
870% o splay_tree: the splay tree.
871%
872% o key: the key.
873%
874*/
cristy9ce61b92010-05-12 16:30:26 +0000875MagickExport const void *GetValueFromSplayTree(SplayTreeInfo *splay_tree,
cristy3ed852e2009-09-05 21:47:34 +0000876 const void *key)
877{
878 int
879 compare;
880
881 void
882 *value;
883
884 assert(splay_tree != (SplayTreeInfo *) NULL);
885 assert(splay_tree->signature == MagickSignature);
886 if (splay_tree->debug != MagickFalse)
887 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
888 if (splay_tree->root == (NodeInfo *) NULL)
889 return((void *) NULL);
cristyf84a1932010-01-03 18:00:18 +0000890 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000891 SplaySplayTree(splay_tree,key);
892 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
893 compare=splay_tree->compare(splay_tree->root->key,key);
894 else
895 compare=(splay_tree->root->key > key) ? 1 :
896 ((splay_tree->root->key < key) ? -1 : 0);
897 if (compare != 0)
898 {
cristyf84a1932010-01-03 18:00:18 +0000899 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000900 return((void *) NULL);
901 }
902 value=splay_tree->root->value;
cristyf84a1932010-01-03 18:00:18 +0000903 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000904 return(value);
905}
906
907/*
908%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909% %
910% %
911% %
912% 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 %
913% %
914% %
915% %
916%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
917%
918% GetNumberOfNodesInSplayTree() returns the number of nodes in the splay-tree.
919%
920% The format of the GetNumberOfNodesInSplayTree method is:
921%
cristybb503372010-05-27 20:51:26 +0000922% size_t GetNumberOfNodesInSplayTree(
cristy3ed852e2009-09-05 21:47:34 +0000923% const SplayTreeInfo *splay_tree)
924%
925% A description of each parameter follows:
926%
927% o splay_tree: the splay tree.
928%
929*/
cristybb503372010-05-27 20:51:26 +0000930MagickExport size_t GetNumberOfNodesInSplayTree(
cristy3ed852e2009-09-05 21:47:34 +0000931 const SplayTreeInfo *splay_tree)
932{
933 assert(splay_tree != (SplayTreeInfo *) NULL);
934 assert(splay_tree->signature == MagickSignature);
935 if (splay_tree->debug != MagickFalse)
936 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
937 return(splay_tree->nodes);
938}
939
940/*
941%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942% %
943% %
944% %
945% I t e r a t e O v e r S p l a y T r e e %
946% %
947% %
948% %
949%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
950%
951% IterateOverSplayTree() iterates over the splay-tree.
952%
953% The format of the IterateOverSplayTree method is:
954%
955% int IterateOverSplayTree(SplayTreeInfo *splay_tree,
956% int (*method)(NodeInfo *,void *),const void *value)
957%
958% A description of each parameter follows:
959%
960% o splay_tree: the splay-tree info.
961%
962% o method: the method.
963%
964% o value: the value.
965%
966*/
967static int IterateOverSplayTree(SplayTreeInfo *splay_tree,
968 int (*method)(NodeInfo *,const void *),const void *value)
969{
970 typedef enum
971 {
972 LeftTransition,
973 RightTransition,
974 DownTransition,
975 UpTransition
976 } TransitionType;
977
978 int
979 status;
980
981 MagickBooleanType
982 final_transition;
983
984 NodeInfo
985 **nodes;
986
cristybb503372010-05-27 20:51:26 +0000987 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000988 i;
989
990 register NodeInfo
991 *node;
992
993 TransitionType
994 transition;
995
996 unsigned char
997 *transitions;
998
999 if (splay_tree->root == (NodeInfo *) NULL)
1000 return(0);
1001 nodes=(NodeInfo **) AcquireQuantumMemory((size_t) splay_tree->nodes,
1002 sizeof(*nodes));
1003 transitions=(unsigned char *) AcquireQuantumMemory((size_t) splay_tree->nodes,
1004 sizeof(*transitions));
1005 if ((nodes == (NodeInfo **) NULL) || (transitions == (unsigned char *) NULL))
1006 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1007 status=0;
1008 final_transition=MagickFalse;
1009 nodes[0]=splay_tree->root;
1010 transitions[0]=(unsigned char) LeftTransition;
1011 for (i=0; final_transition == MagickFalse; )
1012 {
1013 node=nodes[i];
1014 transition=(TransitionType) transitions[i];
1015 switch (transition)
1016 {
1017 case LeftTransition:
1018 {
1019 transitions[i]=(unsigned char) DownTransition;
1020 if (node->left == (NodeInfo *) NULL)
1021 break;
1022 i++;
1023 nodes[i]=node->left;
1024 transitions[i]=(unsigned char) LeftTransition;
1025 break;
1026 }
1027 case RightTransition:
1028 {
1029 transitions[i]=(unsigned char) UpTransition;
1030 if (node->right == (NodeInfo *) NULL)
1031 break;
1032 i++;
1033 nodes[i]=node->right;
1034 transitions[i]=(unsigned char) LeftTransition;
1035 break;
1036 }
1037 case DownTransition:
1038 default:
1039 {
1040 transitions[i]=(unsigned char) RightTransition;
1041 status=(*method)(node,value);
1042 if (status != 0)
1043 final_transition=MagickTrue;
1044 break;
1045 }
1046 case UpTransition:
1047 {
1048 if (i == 0)
1049 {
1050 final_transition=MagickTrue;
1051 break;
1052 }
1053 i--;
1054 break;
1055 }
1056 }
1057 }
1058 nodes=(NodeInfo **) RelinquishMagickMemory(nodes);
1059 transitions=(unsigned char *) RelinquishMagickMemory(transitions);
1060 return(status);
1061}
1062
1063/*
1064%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1065% %
1066% %
1067% %
1068% N e w S p l a y T r e e %
1069% %
1070% %
1071% %
1072%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1073%
1074% NewSplayTree() returns a pointer to a SplayTreeInfo structure initialized
1075% to default values.
1076%
1077% The format of the NewSplayTree method is:
1078%
1079% SplayTreeInfo *NewSplayTree(int (*compare)(const void *,const void *),
1080% void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1081%
1082% A description of each parameter follows:
1083%
1084% o compare: the compare method.
1085%
1086% o relinquish_key: the key deallocation method, typically
1087% RelinquishMagickMemory(), called whenever a key is removed from the
1088% splay-tree.
1089%
1090% o relinquish_value: the value deallocation method; typically
1091% RelinquishMagickMemory(), called whenever a value object is removed from
1092% the splay-tree.
1093%
1094*/
1095MagickExport SplayTreeInfo *NewSplayTree(
1096 int (*compare)(const void *,const void *),void *(*relinquish_key)(void *),
1097 void *(*relinquish_value)(void *))
1098{
1099 SplayTreeInfo
1100 *splay_tree;
1101
cristy73bd4a52010-10-05 11:24:23 +00001102 splay_tree=(SplayTreeInfo *) AcquireMagickMemory(sizeof(*splay_tree));
cristy3ed852e2009-09-05 21:47:34 +00001103 if (splay_tree == (SplayTreeInfo *) NULL)
1104 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1105 (void) ResetMagickMemory(splay_tree,0,sizeof(*splay_tree));
1106 splay_tree->root=(NodeInfo *) NULL;
1107 splay_tree->compare=compare;
1108 splay_tree->relinquish_key=relinquish_key;
1109 splay_tree->relinquish_value=relinquish_value;
1110 splay_tree->balance=MagickFalse;
1111 splay_tree->key=(void *) NULL;
1112 splay_tree->next=(void *) NULL;
1113 splay_tree->nodes=0;
1114 splay_tree->debug=IsEventLogging();
1115 splay_tree->semaphore=AllocateSemaphoreInfo();
1116 splay_tree->signature=MagickSignature;
1117 return(splay_tree);
1118}
1119
1120/*
1121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1122% %
1123% %
1124% %
1125% 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 %
1126% %
1127% %
1128% %
1129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1130%
1131% RemoveNodeByValueFromSplayTree() removes a node by value from the splay-tree
1132% and returns its key.
1133%
1134% The format of the RemoveNodeByValueFromSplayTree method is:
1135%
1136% void *RemoveNodeByValueFromSplayTree(SplayTreeInfo *splay_tree,
1137% const void *value)
1138%
1139% A description of each parameter follows:
1140%
1141% o splay_tree: the splay-tree info.
1142%
1143% o value: the value.
1144%
1145*/
1146MagickExport void *RemoveNodeByValueFromSplayTree(SplayTreeInfo *splay_tree,
1147 const void *value)
1148{
1149 register NodeInfo
1150 *next,
1151 *node;
1152
1153 void
1154 *key;
1155
1156 assert(splay_tree != (SplayTreeInfo *) NULL);
1157 assert(splay_tree->signature == MagickSignature);
1158 if (splay_tree->debug != MagickFalse)
1159 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1160 key=(void *) NULL;
1161 if (splay_tree->root == (NodeInfo *) NULL)
1162 return(key);
cristyf84a1932010-01-03 18:00:18 +00001163 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001164 next=(NodeInfo *) GetFirstSplayTreeNode(splay_tree);
1165 while (next != (NodeInfo *) NULL)
1166 {
1167 SplaySplayTree(splay_tree,next);
1168 next=(NodeInfo *) NULL;
1169 node=splay_tree->root->right;
1170 if (node != (NodeInfo *) NULL)
1171 {
1172 while (node->left != (NodeInfo *) NULL)
1173 node=node->left;
1174 next=(NodeInfo *) node->key;
1175 }
1176 if (splay_tree->root->value == value)
1177 {
1178 int
1179 compare;
1180
1181 register NodeInfo
1182 *left,
1183 *right;
1184
1185 /*
1186 We found the node that matches the value; now remove it.
1187 */
1188 key=splay_tree->root->key;
1189 SplaySplayTree(splay_tree,key);
1190 splay_tree->key=(void *) NULL;
1191 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1192 compare=splay_tree->compare(splay_tree->root->key,key);
1193 else
1194 compare=(splay_tree->root->key > key) ? 1 :
1195 ((splay_tree->root->key < key) ? -1 : 0);
1196 if (compare != 0)
1197 {
cristyf84a1932010-01-03 18:00:18 +00001198 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001199 return(key);
1200 }
1201 left=splay_tree->root->left;
1202 right=splay_tree->root->right;
1203 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1204 (splay_tree->root->value != (void *) NULL))
1205 splay_tree->root->value=splay_tree->relinquish_value(
1206 splay_tree->root->value);
1207 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
1208 splay_tree->nodes--;
1209 if (left == (NodeInfo *) NULL)
1210 {
1211 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +00001212 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001213 return(key);
1214 }
1215 splay_tree->root=left;
1216 if (right != (NodeInfo *) NULL)
1217 {
1218 while (left->right != (NodeInfo *) NULL)
1219 left=left->right;
1220 left->right=right;
1221 }
cristyf84a1932010-01-03 18:00:18 +00001222 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001223 return(key);
1224 }
1225 }
cristyf84a1932010-01-03 18:00:18 +00001226 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001227 return(key);
1228}
1229
1230/*
1231%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1232% %
1233% %
1234% %
1235% R e m o v e N o d e F r o m S p l a y T r e e %
1236% %
1237% %
1238% %
1239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1240%
1241% RemoveNodeFromSplayTree() removes a node from the splay-tree and returns its
1242% value.
1243%
1244% The format of the RemoveNodeFromSplayTree method is:
1245%
1246% void *RemoveNodeFromSplayTree(SplayTreeInfo *splay_tree,const void *key)
1247%
1248% A description of each parameter follows:
1249%
1250% o splay_tree: the splay-tree info.
1251%
1252% o key: the key.
1253%
1254*/
1255MagickExport void *RemoveNodeFromSplayTree(SplayTreeInfo *splay_tree,
1256 const void *key)
1257{
1258 int
1259 compare;
1260
1261 register NodeInfo
1262 *left,
1263 *right;
1264
1265 void
1266 *value;
1267
1268 assert(splay_tree != (SplayTreeInfo *) NULL);
1269 assert(splay_tree->signature == MagickSignature);
1270 if (splay_tree->debug != MagickFalse)
1271 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1272 value=(void *) NULL;
1273 if (splay_tree->root == (NodeInfo *) NULL)
1274 return(value);
cristyf84a1932010-01-03 18:00:18 +00001275 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001276 SplaySplayTree(splay_tree,key);
1277 splay_tree->key=(void *) NULL;
1278 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1279 compare=splay_tree->compare(splay_tree->root->key,key);
1280 else
1281 compare=(splay_tree->root->key > key) ? 1 :
1282 ((splay_tree->root->key < key) ? -1 : 0);
1283 if (compare != 0)
1284 {
cristyf84a1932010-01-03 18:00:18 +00001285 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001286 return(value);
1287 }
1288 left=splay_tree->root->left;
1289 right=splay_tree->root->right;
1290 value=splay_tree->root->value;
1291 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1292 (splay_tree->root->key != (void *) NULL))
1293 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
1294 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
1295 splay_tree->nodes--;
1296 if (left == (NodeInfo *) NULL)
1297 {
1298 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +00001299 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001300 return(value);
1301 }
1302 splay_tree->root=left;
1303 if (right != (NodeInfo *) NULL)
1304 {
1305 while (left->right != (NodeInfo *) NULL)
1306 left=left->right;
1307 left->right=right;
1308 }
cristyf84a1932010-01-03 18:00:18 +00001309 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001310 return(value);
1311}
1312
1313/*
1314%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1315% %
1316% %
1317% %
1318% R e s e t S p l a y T r e e %
1319% %
1320% %
1321% %
1322%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1323%
1324% ResetSplayTree() resets the splay-tree. That is, it deletes all the nodes
1325% from the tree.
1326%
1327% The format of the ResetSplayTree method is:
1328%
1329% ResetSplayTree(SplayTreeInfo *splay_tree)
1330%
1331% A description of each parameter follows:
1332%
1333% o splay_tree: the splay tree.
1334%
1335*/
1336MagickExport void ResetSplayTree(SplayTreeInfo *splay_tree)
1337{
1338 NodeInfo
1339 *node;
1340
1341 register NodeInfo
1342 *active,
1343 *pend;
1344
1345 assert(splay_tree != (SplayTreeInfo *) NULL);
1346 assert(splay_tree->signature == MagickSignature);
1347 if (splay_tree->debug != MagickFalse)
1348 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00001349 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001350 if (splay_tree->root != (NodeInfo *) NULL)
1351 {
cristy3ed852e2009-09-05 21:47:34 +00001352 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1353 (splay_tree->root->value != (void *) NULL))
1354 splay_tree->root->value=splay_tree->relinquish_value(
1355 splay_tree->root->value);
cristy6f24b182010-09-29 22:02:52 +00001356 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1357 (splay_tree->root->key != (void *) NULL))
1358 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
1359 splay_tree->root->key=(void *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00001360 for (pend=splay_tree->root; pend != (NodeInfo *) NULL; )
1361 {
1362 active=pend;
1363 for (pend=(NodeInfo *) NULL; active != (NodeInfo *) NULL; )
1364 {
1365 if (active->left != (NodeInfo *) NULL)
1366 {
cristy3ed852e2009-09-05 21:47:34 +00001367 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1368 (active->left->value != (void *) NULL))
1369 active->left->value=splay_tree->relinquish_value(
1370 active->left->value);
cristy6f24b182010-09-29 22:02:52 +00001371 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1372 (active->left->key != (void *) NULL))
1373 active->left->key=splay_tree->relinquish_key(active->left->key);
1374 active->left->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +00001375 pend=active->left;
1376 }
1377 if (active->right != (NodeInfo *) NULL)
1378 {
cristy6f24b182010-09-29 22:02:52 +00001379 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1380 (active->right->value != (void *) NULL))
1381 active->right->value=splay_tree->relinquish_value(
1382 active->right->value);
cristy3ed852e2009-09-05 21:47:34 +00001383 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1384 (active->right->key != (void *) NULL))
1385 active->right->key=splay_tree->relinquish_key(
1386 active->right->key);
1387 active->right->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +00001388 pend=active->right;
1389 }
1390 node=active;
1391 active=(NodeInfo *) node->key;
1392 node=(NodeInfo *) RelinquishMagickMemory(node);
1393 }
1394 }
1395 }
1396 splay_tree->root=(NodeInfo *) NULL;
1397 splay_tree->key=(void *) NULL;
1398 splay_tree->next=(void *) NULL;
1399 splay_tree->nodes=0;
1400 splay_tree->balance=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001401 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001402}
1403
1404/*
1405%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1406% %
1407% %
1408% %
1409% R e s e t S p l a y T r e e I t e r a t o r %
1410% %
1411% %
1412% %
1413%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1414%
1415% ResetSplayTreeIterator() resets the splay-tree iterator. Use it in
1416% conjunction with GetNextValueInSplayTree() to iterate over all the nodes in
1417% the splay-tree.
1418%
1419% The format of the ResetSplayTreeIterator method is:
1420%
1421% ResetSplayTreeIterator(SplayTreeInfo *splay_tree)
1422%
1423% A description of each parameter follows:
1424%
1425% o splay_tree: the splay tree.
1426%
1427*/
1428MagickExport void ResetSplayTreeIterator(SplayTreeInfo *splay_tree)
1429{
1430 assert(splay_tree != (SplayTreeInfo *) NULL);
1431 assert(splay_tree->signature == MagickSignature);
1432 if (splay_tree->debug != MagickFalse)
1433 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00001434 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001435 splay_tree->next=GetFirstSplayTreeNode(splay_tree);
cristyf84a1932010-01-03 18:00:18 +00001436 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001437}
1438
1439/*
1440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1441% %
1442% %
1443% %
1444% S p l a y S p l a y T r e e %
1445% %
1446% %
1447% %
1448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1449%
1450% SplaySplayTree() splays the splay-tree.
1451%
1452% The format of the SplaySplayTree method is:
1453%
1454% void SplaySplayTree(SplayTreeInfo *splay_tree,const void *key,
1455% NodeInfo **node,NodeInfo **parent,NodeInfo **grandparent)
1456%
1457% A description of each parameter follows:
1458%
1459% o splay_tree: the splay-tree info.
1460%
1461% o key: the key.
1462%
1463% o node: the node.
1464%
1465% o parent: the parent node.
1466%
1467% o grandparent: the grandparent node.
1468%
1469*/
1470
cristybb503372010-05-27 20:51:26 +00001471static NodeInfo *Splay(SplayTreeInfo *splay_tree,const size_t depth,
cristy3ed852e2009-09-05 21:47:34 +00001472 const void *key,NodeInfo **node,NodeInfo **parent,NodeInfo **grandparent)
1473{
1474 int
1475 compare;
1476
1477 NodeInfo
1478 **next;
1479
1480 register NodeInfo
1481 *n,
1482 *p;
1483
1484 n=(*node);
1485 if (n == (NodeInfo *) NULL)
1486 return(*parent);
1487 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1488 compare=splay_tree->compare(n->key,key);
1489 else
1490 compare=(n->key > key) ? 1 : ((n->key < key) ? -1 : 0);
1491 next=(NodeInfo **) NULL;
1492 if (compare > 0)
1493 next=(&n->left);
1494 else
1495 if (compare < 0)
1496 next=(&n->right);
1497 if (next != (NodeInfo **) NULL)
1498 {
1499 if (depth >= MaxSplayTreeDepth)
1500 {
1501 splay_tree->balance=MagickTrue;
1502 return(n);
1503 }
1504 n=Splay(splay_tree,depth+1,key,next,node,parent);
1505 if ((n != *node) || (splay_tree->balance != MagickFalse))
1506 return(n);
1507 }
1508 if (parent == (NodeInfo **) NULL)
1509 return(n);
1510 if (grandparent == (NodeInfo **) NULL)
1511 {
1512 if (n == (*parent)->left)
1513 {
1514 *node=n->right;
1515 n->right=(*parent);
1516 }
1517 else
1518 {
1519 *node=n->left;
1520 n->left=(*parent);
1521 }
1522 *parent=n;
1523 return(n);
1524 }
1525 if ((n == (*parent)->left) && (*parent == (*grandparent)->left))
1526 {
1527 p=(*parent);
1528 (*grandparent)->left=p->right;
1529 p->right=(*grandparent);
1530 p->left=n->right;
1531 n->right=p;
1532 *grandparent=n;
1533 return(n);
1534 }
1535 if ((n == (*parent)->right) && (*parent == (*grandparent)->right))
1536 {
1537 p=(*parent);
1538 (*grandparent)->right=p->left;
1539 p->left=(*grandparent);
1540 p->right=n->left;
1541 n->left=p;
1542 *grandparent=n;
1543 return(n);
1544 }
1545 if (n == (*parent)->left)
1546 {
1547 (*parent)->left=n->right;
1548 n->right=(*parent);
1549 (*grandparent)->right=n->left;
1550 n->left=(*grandparent);
1551 *grandparent=n;
1552 return(n);
1553 }
1554 (*parent)->right=n->left;
1555 n->left=(*parent);
1556 (*grandparent)->left=n->right;
1557 n->right=(*grandparent);
1558 *grandparent=n;
1559 return(n);
1560}
1561
1562static void SplaySplayTree(SplayTreeInfo *splay_tree,const void *key)
1563{
1564 if (splay_tree->root == (NodeInfo *) NULL)
1565 return;
1566 if (splay_tree->key != (void *) NULL)
1567 {
1568 int
1569 compare;
1570
1571 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1572 compare=splay_tree->compare(splay_tree->root->key,key);
1573 else
1574 compare=(splay_tree->key > key) ? 1 :
1575 ((splay_tree->key < key) ? -1 : 0);
1576 if (compare == 0)
1577 return;
1578 }
1579 (void) Splay(splay_tree,0UL,key,&splay_tree->root,(NodeInfo **) NULL,
1580 (NodeInfo **) NULL);
1581 if (splay_tree->balance != MagickFalse)
1582 {
1583 BalanceSplayTree(splay_tree);
1584 (void) Splay(splay_tree,0UL,key,&splay_tree->root,(NodeInfo **) NULL,
1585 (NodeInfo **) NULL);
1586 if (splay_tree->balance != MagickFalse)
1587 ThrowFatalException(ResourceLimitFatalError,
1588 "MemoryAllocationFailed");
1589 }
1590 splay_tree->key=(void *) key;
1591}