blob: 0e3b231e528a47cca37c0e82df4d45790d73b038 [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.
cristy32fab702012-01-18 02:47:47 +0000135% Both key and value are 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%
cristy4c0eee22012-03-22 18:32:34 +0000584% DeleteNodeFromSplayTree() deletes a node from the splay-tree. It returns
cristy9767b952012-03-22 18:31:22 +0000585% MagickTrue if the option is found and successfully deleted from the
586% splay-tree.
anthonyebb73a22012-03-22 14:25:52 +0000587%
cristy3ed852e2009-09-05 21:47:34 +0000588% The format of the DeleteNodeFromSplayTree method is:
589%
590% MagickBooleanType DeleteNodeFromSplayTree(SplayTreeInfo *splay_tree,
591% const void *key)
592%
593% A description of each parameter follows:
594%
595% o splay_tree: the splay-tree info.
596%
597% o key: the key.
598%
599*/
600MagickExport MagickBooleanType DeleteNodeFromSplayTree(
601 SplayTreeInfo *splay_tree,const void *key)
602{
603 int
604 compare;
605
606 register NodeInfo
607 *left,
608 *right;
609
610 assert(splay_tree != (SplayTreeInfo *) NULL);
611 assert(splay_tree->signature == MagickSignature);
612 if (splay_tree->debug != MagickFalse)
613 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
614 if (splay_tree->root == (NodeInfo *) NULL)
615 return(MagickFalse);
cristyf84a1932010-01-03 18:00:18 +0000616 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000617 SplaySplayTree(splay_tree,key);
618 splay_tree->key=(void *) NULL;
619 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
620 compare=splay_tree->compare(splay_tree->root->key,key);
621 else
622 compare=(splay_tree->root->key > key) ? 1 :
623 ((splay_tree->root->key < key) ? -1 : 0);
624 if (compare != 0)
625 {
cristyf84a1932010-01-03 18:00:18 +0000626 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000627 return(MagickFalse);
628 }
629 left=splay_tree->root->left;
630 right=splay_tree->root->right;
631 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
632 (splay_tree->root->value != (void *) NULL))
633 splay_tree->root->value=splay_tree->relinquish_value(
634 splay_tree->root->value);
635 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
636 (splay_tree->root->key != (void *) NULL))
637 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
638 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
639 splay_tree->nodes--;
640 if (left == (NodeInfo *) NULL)
641 {
642 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +0000643 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000644 return(MagickTrue);
645 }
646 splay_tree->root=left;
647 if (right != (NodeInfo *) NULL)
648 {
649 while (left->right != (NodeInfo *) NULL)
650 left=left->right;
651 left->right=right;
652 }
cristyf84a1932010-01-03 18:00:18 +0000653 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000654 return(MagickTrue);
655}
656
657/*
658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659% %
660% %
661% %
662% D e s t r o y S p l a y T r e e %
663% %
664% %
665% %
666%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667%
668% DestroySplayTree() destroys the splay-tree.
669%
670% The format of the DestroySplayTree method is:
671%
672% SplayTreeInfo *DestroySplayTree(SplayTreeInfo *splay_tree)
673%
674% A description of each parameter follows:
675%
676% o splay_tree: the splay tree.
677%
678*/
679MagickExport SplayTreeInfo *DestroySplayTree(SplayTreeInfo *splay_tree)
680{
681 NodeInfo
682 *node;
683
684 register NodeInfo
685 *active,
686 *pend;
687
cristyf84a1932010-01-03 18:00:18 +0000688 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000689 if (splay_tree->root != (NodeInfo *) NULL)
690 {
cristy3ed852e2009-09-05 21:47:34 +0000691 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
692 (splay_tree->root->value != (void *) NULL))
693 splay_tree->root->value=splay_tree->relinquish_value(
694 splay_tree->root->value);
cristy6f24b182010-09-29 22:02:52 +0000695 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
696 (splay_tree->root->key != (void *) NULL))
697 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
698 splay_tree->root->key=(void *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000699 for (pend=splay_tree->root; pend != (NodeInfo *) NULL; )
700 {
701 active=pend;
702 for (pend=(NodeInfo *) NULL; active != (NodeInfo *) NULL; )
703 {
704 if (active->left != (NodeInfo *) NULL)
705 {
cristy3ed852e2009-09-05 21:47:34 +0000706 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
707 (active->left->value != (void *) NULL))
708 active->left->value=splay_tree->relinquish_value(
709 active->left->value);
cristy6f24b182010-09-29 22:02:52 +0000710 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
711 (active->left->key != (void *) NULL))
712 active->left->key=splay_tree->relinquish_key(active->left->key);
713 active->left->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +0000714 pend=active->left;
715 }
716 if (active->right != (NodeInfo *) NULL)
717 {
cristy6f24b182010-09-29 22:02:52 +0000718 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
719 (active->right->value != (void *) NULL))
720 active->right->value=splay_tree->relinquish_value(
721 active->right->value);
cristy3ed852e2009-09-05 21:47:34 +0000722 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
723 (active->right->key != (void *) NULL))
724 active->right->key=splay_tree->relinquish_key(
725 active->right->key);
726 active->right->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +0000727 pend=active->right;
728 }
729 node=active;
730 active=(NodeInfo *) node->key;
731 node=(NodeInfo *) RelinquishMagickMemory(node);
732 }
733 }
734 }
735 splay_tree->signature=(~MagickSignature);
cristyf84a1932010-01-03 18:00:18 +0000736 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000737 DestroySemaphoreInfo(&splay_tree->semaphore);
738 splay_tree=(SplayTreeInfo *) RelinquishMagickMemory(splay_tree);
739 return(splay_tree);
740}
741
742/*
743%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
744% %
745% %
746% %
747% G e t N e x t K e y I n S p l a y T r e e %
748% %
749% %
750% %
751%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
752%
753% GetNextKeyInSplayTree() gets the next key in the splay-tree.
754%
755% The format of the GetNextKeyInSplayTree method is:
756%
cristy9ce61b92010-05-12 16:30:26 +0000757% const void *GetNextKeyInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000758%
759% A description of each parameter follows:
760%
761% o splay_tree: the splay tree.
762%
763% o key: the key.
764%
765*/
cristy9ce61b92010-05-12 16:30:26 +0000766MagickExport const void *GetNextKeyInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000767{
768 register NodeInfo
769 *node;
770
771 void
772 *key;
773
774 assert(splay_tree != (SplayTreeInfo *) NULL);
775 assert(splay_tree->signature == MagickSignature);
776 if (splay_tree->debug != MagickFalse)
777 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
778 if ((splay_tree->root == (NodeInfo *) NULL) ||
779 (splay_tree->next == (void *) NULL))
780 return((void *) NULL);
cristyf84a1932010-01-03 18:00:18 +0000781 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000782 SplaySplayTree(splay_tree,splay_tree->next);
783 splay_tree->next=(void *) NULL;
784 node=splay_tree->root->right;
785 if (node != (NodeInfo *) NULL)
786 {
787 while (node->left != (NodeInfo *) NULL)
788 node=node->left;
789 splay_tree->next=node->key;
790 }
791 key=splay_tree->root->key;
cristyf84a1932010-01-03 18:00:18 +0000792 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000793 return(key);
794}
795
796/*
797%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
798% %
799% %
800% %
801% G e t N e x t V a l u e I n S p l a y T r e e %
802% %
803% %
804% %
805%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
806%
807% GetNextValueInSplayTree() gets the next value in the splay-tree.
808%
809% The format of the GetNextValueInSplayTree method is:
810%
cristy9ce61b92010-05-12 16:30:26 +0000811% const void *GetNextValueInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000812%
813% A description of each parameter follows:
814%
815% o splay_tree: the splay tree.
816%
817% o key: the key.
818%
819*/
cristy9ce61b92010-05-12 16:30:26 +0000820MagickExport const void *GetNextValueInSplayTree(SplayTreeInfo *splay_tree)
cristy3ed852e2009-09-05 21:47:34 +0000821{
822 register NodeInfo
823 *node;
824
825 void
826 *value;
827
828 assert(splay_tree != (SplayTreeInfo *) NULL);
829 assert(splay_tree->signature == MagickSignature);
830 if (splay_tree->debug != MagickFalse)
831 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
832 if ((splay_tree->root == (NodeInfo *) NULL) ||
833 (splay_tree->next == (void *) NULL))
834 return((void *) NULL);
cristyf84a1932010-01-03 18:00:18 +0000835 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000836 SplaySplayTree(splay_tree,splay_tree->next);
837 splay_tree->next=(void *) NULL;
838 node=splay_tree->root->right;
839 if (node != (NodeInfo *) NULL)
840 {
841 while (node->left != (NodeInfo *) NULL)
842 node=node->left;
843 splay_tree->next=node->key;
844 }
845 value=splay_tree->root->value;
cristyf84a1932010-01-03 18:00:18 +0000846 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000847 return(value);
848}
849
850/*
851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852% %
853% %
854% %
855% G e t V a l u e F r o m S p l a y T r e e %
856% %
857% %
858% %
859%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
860%
861% GetValueFromSplayTree() gets a value from the splay-tree by its key.
862%
cristy9ce61b92010-05-12 16:30:26 +0000863% Note, the value is a constant. Do not attempt to free it.
anthony580609e2010-05-12 02:27:05 +0000864%
cristy3ed852e2009-09-05 21:47:34 +0000865% The format of the GetValueFromSplayTree method is:
866%
cristy9ce61b92010-05-12 16:30:26 +0000867% const void *GetValueFromSplayTree(SplayTreeInfo *splay_tree,
868% const void *key)
cristy3ed852e2009-09-05 21:47:34 +0000869%
870% A description of each parameter follows:
871%
872% o splay_tree: the splay tree.
873%
874% o key: the key.
875%
876*/
cristy9ce61b92010-05-12 16:30:26 +0000877MagickExport const void *GetValueFromSplayTree(SplayTreeInfo *splay_tree,
cristy3ed852e2009-09-05 21:47:34 +0000878 const void *key)
879{
880 int
881 compare;
882
883 void
884 *value;
885
886 assert(splay_tree != (SplayTreeInfo *) NULL);
887 assert(splay_tree->signature == MagickSignature);
888 if (splay_tree->debug != MagickFalse)
889 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
890 if (splay_tree->root == (NodeInfo *) NULL)
891 return((void *) NULL);
cristyf84a1932010-01-03 18:00:18 +0000892 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000893 SplaySplayTree(splay_tree,key);
894 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
895 compare=splay_tree->compare(splay_tree->root->key,key);
896 else
897 compare=(splay_tree->root->key > key) ? 1 :
898 ((splay_tree->root->key < key) ? -1 : 0);
899 if (compare != 0)
900 {
cristyf84a1932010-01-03 18:00:18 +0000901 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000902 return((void *) NULL);
903 }
904 value=splay_tree->root->value;
cristyf84a1932010-01-03 18:00:18 +0000905 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000906 return(value);
907}
908
909/*
910%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
911% %
912% %
913% %
914% 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 %
915% %
916% %
917% %
918%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
919%
920% GetNumberOfNodesInSplayTree() returns the number of nodes in the splay-tree.
921%
922% The format of the GetNumberOfNodesInSplayTree method is:
923%
cristybb503372010-05-27 20:51:26 +0000924% size_t GetNumberOfNodesInSplayTree(
cristy3ed852e2009-09-05 21:47:34 +0000925% const SplayTreeInfo *splay_tree)
926%
927% A description of each parameter follows:
928%
929% o splay_tree: the splay tree.
930%
931*/
cristybb503372010-05-27 20:51:26 +0000932MagickExport size_t GetNumberOfNodesInSplayTree(
cristy3ed852e2009-09-05 21:47:34 +0000933 const SplayTreeInfo *splay_tree)
934{
935 assert(splay_tree != (SplayTreeInfo *) NULL);
936 assert(splay_tree->signature == MagickSignature);
937 if (splay_tree->debug != MagickFalse)
938 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
939 return(splay_tree->nodes);
940}
941
942/*
943%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
944% %
945% %
946% %
947% I t e r a t e O v e r S p l a y T r e e %
948% %
949% %
950% %
951%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952%
953% IterateOverSplayTree() iterates over the splay-tree.
954%
955% The format of the IterateOverSplayTree method is:
956%
957% int IterateOverSplayTree(SplayTreeInfo *splay_tree,
958% int (*method)(NodeInfo *,void *),const void *value)
959%
960% A description of each parameter follows:
961%
962% o splay_tree: the splay-tree info.
963%
964% o method: the method.
965%
966% o value: the value.
967%
968*/
969static int IterateOverSplayTree(SplayTreeInfo *splay_tree,
970 int (*method)(NodeInfo *,const void *),const void *value)
971{
972 typedef enum
973 {
974 LeftTransition,
975 RightTransition,
976 DownTransition,
977 UpTransition
978 } TransitionType;
979
980 int
981 status;
982
983 MagickBooleanType
984 final_transition;
985
986 NodeInfo
987 **nodes;
988
cristybb503372010-05-27 20:51:26 +0000989 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000990 i;
991
992 register NodeInfo
993 *node;
994
995 TransitionType
996 transition;
997
998 unsigned char
999 *transitions;
1000
1001 if (splay_tree->root == (NodeInfo *) NULL)
1002 return(0);
1003 nodes=(NodeInfo **) AcquireQuantumMemory((size_t) splay_tree->nodes,
1004 sizeof(*nodes));
1005 transitions=(unsigned char *) AcquireQuantumMemory((size_t) splay_tree->nodes,
1006 sizeof(*transitions));
1007 if ((nodes == (NodeInfo **) NULL) || (transitions == (unsigned char *) NULL))
1008 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1009 status=0;
1010 final_transition=MagickFalse;
1011 nodes[0]=splay_tree->root;
1012 transitions[0]=(unsigned char) LeftTransition;
1013 for (i=0; final_transition == MagickFalse; )
1014 {
1015 node=nodes[i];
1016 transition=(TransitionType) transitions[i];
1017 switch (transition)
1018 {
1019 case LeftTransition:
1020 {
1021 transitions[i]=(unsigned char) DownTransition;
1022 if (node->left == (NodeInfo *) NULL)
1023 break;
1024 i++;
1025 nodes[i]=node->left;
1026 transitions[i]=(unsigned char) LeftTransition;
1027 break;
1028 }
1029 case RightTransition:
1030 {
1031 transitions[i]=(unsigned char) UpTransition;
1032 if (node->right == (NodeInfo *) NULL)
1033 break;
1034 i++;
1035 nodes[i]=node->right;
1036 transitions[i]=(unsigned char) LeftTransition;
1037 break;
1038 }
1039 case DownTransition:
1040 default:
1041 {
1042 transitions[i]=(unsigned char) RightTransition;
1043 status=(*method)(node,value);
1044 if (status != 0)
1045 final_transition=MagickTrue;
1046 break;
1047 }
1048 case UpTransition:
1049 {
1050 if (i == 0)
1051 {
1052 final_transition=MagickTrue;
1053 break;
1054 }
1055 i--;
1056 break;
1057 }
1058 }
1059 }
1060 nodes=(NodeInfo **) RelinquishMagickMemory(nodes);
1061 transitions=(unsigned char *) RelinquishMagickMemory(transitions);
1062 return(status);
1063}
1064
1065/*
1066%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1067% %
1068% %
1069% %
1070% N e w S p l a y T r e e %
1071% %
1072% %
1073% %
1074%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1075%
1076% NewSplayTree() returns a pointer to a SplayTreeInfo structure initialized
1077% to default values.
1078%
1079% The format of the NewSplayTree method is:
1080%
1081% SplayTreeInfo *NewSplayTree(int (*compare)(const void *,const void *),
1082% void *(*relinquish_key)(void *),void *(*relinquish_value)(void *))
1083%
1084% A description of each parameter follows:
1085%
1086% o compare: the compare method.
1087%
1088% o relinquish_key: the key deallocation method, typically
1089% RelinquishMagickMemory(), called whenever a key is removed from the
1090% splay-tree.
1091%
1092% o relinquish_value: the value deallocation method; typically
1093% RelinquishMagickMemory(), called whenever a value object is removed from
1094% the splay-tree.
1095%
1096*/
1097MagickExport SplayTreeInfo *NewSplayTree(
1098 int (*compare)(const void *,const void *),void *(*relinquish_key)(void *),
1099 void *(*relinquish_value)(void *))
1100{
1101 SplayTreeInfo
1102 *splay_tree;
1103
cristy73bd4a52010-10-05 11:24:23 +00001104 splay_tree=(SplayTreeInfo *) AcquireMagickMemory(sizeof(*splay_tree));
cristy3ed852e2009-09-05 21:47:34 +00001105 if (splay_tree == (SplayTreeInfo *) NULL)
1106 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1107 (void) ResetMagickMemory(splay_tree,0,sizeof(*splay_tree));
1108 splay_tree->root=(NodeInfo *) NULL;
1109 splay_tree->compare=compare;
1110 splay_tree->relinquish_key=relinquish_key;
1111 splay_tree->relinquish_value=relinquish_value;
1112 splay_tree->balance=MagickFalse;
1113 splay_tree->key=(void *) NULL;
1114 splay_tree->next=(void *) NULL;
1115 splay_tree->nodes=0;
1116 splay_tree->debug=IsEventLogging();
1117 splay_tree->semaphore=AllocateSemaphoreInfo();
1118 splay_tree->signature=MagickSignature;
1119 return(splay_tree);
1120}
1121
1122/*
1123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1124% %
1125% %
1126% %
1127% 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 %
1128% %
1129% %
1130% %
1131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1132%
1133% RemoveNodeByValueFromSplayTree() removes a node by value from the splay-tree
1134% and returns its key.
1135%
1136% The format of the RemoveNodeByValueFromSplayTree method is:
1137%
1138% void *RemoveNodeByValueFromSplayTree(SplayTreeInfo *splay_tree,
1139% const void *value)
1140%
1141% A description of each parameter follows:
1142%
1143% o splay_tree: the splay-tree info.
1144%
1145% o value: the value.
1146%
1147*/
1148MagickExport void *RemoveNodeByValueFromSplayTree(SplayTreeInfo *splay_tree,
1149 const void *value)
1150{
1151 register NodeInfo
1152 *next,
1153 *node;
1154
1155 void
1156 *key;
1157
1158 assert(splay_tree != (SplayTreeInfo *) NULL);
1159 assert(splay_tree->signature == MagickSignature);
1160 if (splay_tree->debug != MagickFalse)
1161 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1162 key=(void *) NULL;
1163 if (splay_tree->root == (NodeInfo *) NULL)
1164 return(key);
cristyf84a1932010-01-03 18:00:18 +00001165 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001166 next=(NodeInfo *) GetFirstSplayTreeNode(splay_tree);
1167 while (next != (NodeInfo *) NULL)
1168 {
1169 SplaySplayTree(splay_tree,next);
1170 next=(NodeInfo *) NULL;
1171 node=splay_tree->root->right;
1172 if (node != (NodeInfo *) NULL)
1173 {
1174 while (node->left != (NodeInfo *) NULL)
1175 node=node->left;
1176 next=(NodeInfo *) node->key;
1177 }
1178 if (splay_tree->root->value == value)
1179 {
1180 int
1181 compare;
1182
1183 register NodeInfo
1184 *left,
1185 *right;
1186
1187 /*
1188 We found the node that matches the value; now remove it.
1189 */
1190 key=splay_tree->root->key;
1191 SplaySplayTree(splay_tree,key);
1192 splay_tree->key=(void *) NULL;
1193 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1194 compare=splay_tree->compare(splay_tree->root->key,key);
1195 else
1196 compare=(splay_tree->root->key > key) ? 1 :
1197 ((splay_tree->root->key < key) ? -1 : 0);
1198 if (compare != 0)
1199 {
cristyf84a1932010-01-03 18:00:18 +00001200 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001201 return(key);
1202 }
1203 left=splay_tree->root->left;
1204 right=splay_tree->root->right;
1205 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1206 (splay_tree->root->value != (void *) NULL))
1207 splay_tree->root->value=splay_tree->relinquish_value(
1208 splay_tree->root->value);
1209 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
1210 splay_tree->nodes--;
1211 if (left == (NodeInfo *) NULL)
1212 {
1213 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +00001214 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001215 return(key);
1216 }
1217 splay_tree->root=left;
1218 if (right != (NodeInfo *) NULL)
1219 {
1220 while (left->right != (NodeInfo *) NULL)
1221 left=left->right;
1222 left->right=right;
1223 }
cristyf84a1932010-01-03 18:00:18 +00001224 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001225 return(key);
1226 }
1227 }
cristyf84a1932010-01-03 18:00:18 +00001228 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001229 return(key);
1230}
1231
1232/*
1233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1234% %
1235% %
1236% %
1237% R e m o v e N o d e F r o m S p l a y T r e e %
1238% %
1239% %
1240% %
1241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1242%
1243% RemoveNodeFromSplayTree() removes a node from the splay-tree and returns its
1244% value.
1245%
1246% The format of the RemoveNodeFromSplayTree method is:
1247%
1248% void *RemoveNodeFromSplayTree(SplayTreeInfo *splay_tree,const void *key)
1249%
1250% A description of each parameter follows:
1251%
1252% o splay_tree: the splay-tree info.
1253%
1254% o key: the key.
1255%
1256*/
1257MagickExport void *RemoveNodeFromSplayTree(SplayTreeInfo *splay_tree,
1258 const void *key)
1259{
1260 int
1261 compare;
1262
1263 register NodeInfo
1264 *left,
1265 *right;
1266
1267 void
1268 *value;
1269
1270 assert(splay_tree != (SplayTreeInfo *) NULL);
1271 assert(splay_tree->signature == MagickSignature);
1272 if (splay_tree->debug != MagickFalse)
1273 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1274 value=(void *) NULL;
1275 if (splay_tree->root == (NodeInfo *) NULL)
1276 return(value);
cristyf84a1932010-01-03 18:00:18 +00001277 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001278 SplaySplayTree(splay_tree,key);
1279 splay_tree->key=(void *) NULL;
1280 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1281 compare=splay_tree->compare(splay_tree->root->key,key);
1282 else
1283 compare=(splay_tree->root->key > key) ? 1 :
1284 ((splay_tree->root->key < key) ? -1 : 0);
1285 if (compare != 0)
1286 {
cristyf84a1932010-01-03 18:00:18 +00001287 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001288 return(value);
1289 }
1290 left=splay_tree->root->left;
1291 right=splay_tree->root->right;
1292 value=splay_tree->root->value;
1293 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1294 (splay_tree->root->key != (void *) NULL))
1295 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
1296 splay_tree->root=(NodeInfo *) RelinquishMagickMemory(splay_tree->root);
1297 splay_tree->nodes--;
1298 if (left == (NodeInfo *) NULL)
1299 {
1300 splay_tree->root=right;
cristyf84a1932010-01-03 18:00:18 +00001301 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001302 return(value);
1303 }
1304 splay_tree->root=left;
1305 if (right != (NodeInfo *) NULL)
1306 {
1307 while (left->right != (NodeInfo *) NULL)
1308 left=left->right;
1309 left->right=right;
1310 }
cristyf84a1932010-01-03 18:00:18 +00001311 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001312 return(value);
1313}
1314
1315/*
1316%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1317% %
1318% %
1319% %
1320% R e s e t S p l a y T r e e %
1321% %
1322% %
1323% %
1324%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1325%
1326% ResetSplayTree() resets the splay-tree. That is, it deletes all the nodes
1327% from the tree.
1328%
1329% The format of the ResetSplayTree method is:
1330%
1331% ResetSplayTree(SplayTreeInfo *splay_tree)
1332%
1333% A description of each parameter follows:
1334%
1335% o splay_tree: the splay tree.
1336%
1337*/
1338MagickExport void ResetSplayTree(SplayTreeInfo *splay_tree)
1339{
1340 NodeInfo
1341 *node;
1342
1343 register NodeInfo
1344 *active,
1345 *pend;
1346
1347 assert(splay_tree != (SplayTreeInfo *) NULL);
1348 assert(splay_tree->signature == MagickSignature);
1349 if (splay_tree->debug != MagickFalse)
1350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00001351 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001352 if (splay_tree->root != (NodeInfo *) NULL)
1353 {
cristy3ed852e2009-09-05 21:47:34 +00001354 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1355 (splay_tree->root->value != (void *) NULL))
1356 splay_tree->root->value=splay_tree->relinquish_value(
1357 splay_tree->root->value);
cristy6f24b182010-09-29 22:02:52 +00001358 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1359 (splay_tree->root->key != (void *) NULL))
1360 splay_tree->root->key=splay_tree->relinquish_key(splay_tree->root->key);
1361 splay_tree->root->key=(void *) NULL;
cristy3ed852e2009-09-05 21:47:34 +00001362 for (pend=splay_tree->root; pend != (NodeInfo *) NULL; )
1363 {
1364 active=pend;
1365 for (pend=(NodeInfo *) NULL; active != (NodeInfo *) NULL; )
1366 {
1367 if (active->left != (NodeInfo *) NULL)
1368 {
cristy3ed852e2009-09-05 21:47:34 +00001369 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1370 (active->left->value != (void *) NULL))
1371 active->left->value=splay_tree->relinquish_value(
1372 active->left->value);
cristy6f24b182010-09-29 22:02:52 +00001373 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1374 (active->left->key != (void *) NULL))
1375 active->left->key=splay_tree->relinquish_key(active->left->key);
1376 active->left->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +00001377 pend=active->left;
1378 }
1379 if (active->right != (NodeInfo *) NULL)
1380 {
cristy6f24b182010-09-29 22:02:52 +00001381 if ((splay_tree->relinquish_value != (void *(*)(void *)) NULL) &&
1382 (active->right->value != (void *) NULL))
1383 active->right->value=splay_tree->relinquish_value(
1384 active->right->value);
cristy3ed852e2009-09-05 21:47:34 +00001385 if ((splay_tree->relinquish_key != (void *(*)(void *)) NULL) &&
1386 (active->right->key != (void *) NULL))
1387 active->right->key=splay_tree->relinquish_key(
1388 active->right->key);
1389 active->right->key=(void *) pend;
cristy3ed852e2009-09-05 21:47:34 +00001390 pend=active->right;
1391 }
1392 node=active;
1393 active=(NodeInfo *) node->key;
1394 node=(NodeInfo *) RelinquishMagickMemory(node);
1395 }
1396 }
1397 }
1398 splay_tree->root=(NodeInfo *) NULL;
1399 splay_tree->key=(void *) NULL;
1400 splay_tree->next=(void *) NULL;
1401 splay_tree->nodes=0;
1402 splay_tree->balance=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001403 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001404}
1405
1406/*
1407%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1408% %
1409% %
1410% %
1411% R e s e t S p l a y T r e e I t e r a t o r %
1412% %
1413% %
1414% %
1415%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1416%
1417% ResetSplayTreeIterator() resets the splay-tree iterator. Use it in
1418% conjunction with GetNextValueInSplayTree() to iterate over all the nodes in
1419% the splay-tree.
1420%
1421% The format of the ResetSplayTreeIterator method is:
1422%
1423% ResetSplayTreeIterator(SplayTreeInfo *splay_tree)
1424%
1425% A description of each parameter follows:
1426%
1427% o splay_tree: the splay tree.
1428%
1429*/
1430MagickExport void ResetSplayTreeIterator(SplayTreeInfo *splay_tree)
1431{
1432 assert(splay_tree != (SplayTreeInfo *) NULL);
1433 assert(splay_tree->signature == MagickSignature);
1434 if (splay_tree->debug != MagickFalse)
1435 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristyf84a1932010-01-03 18:00:18 +00001436 LockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001437 splay_tree->next=GetFirstSplayTreeNode(splay_tree);
cristyf84a1932010-01-03 18:00:18 +00001438 UnlockSemaphoreInfo(splay_tree->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001439}
1440
1441/*
1442%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1443% %
1444% %
1445% %
1446% S p l a y S p l a y T r e e %
1447% %
1448% %
1449% %
1450%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1451%
1452% SplaySplayTree() splays the splay-tree.
1453%
1454% The format of the SplaySplayTree method is:
1455%
1456% void SplaySplayTree(SplayTreeInfo *splay_tree,const void *key,
1457% NodeInfo **node,NodeInfo **parent,NodeInfo **grandparent)
1458%
1459% A description of each parameter follows:
1460%
1461% o splay_tree: the splay-tree info.
1462%
1463% o key: the key.
1464%
1465% o node: the node.
1466%
1467% o parent: the parent node.
1468%
1469% o grandparent: the grandparent node.
1470%
1471*/
1472
cristybb503372010-05-27 20:51:26 +00001473static NodeInfo *Splay(SplayTreeInfo *splay_tree,const size_t depth,
cristy3ed852e2009-09-05 21:47:34 +00001474 const void *key,NodeInfo **node,NodeInfo **parent,NodeInfo **grandparent)
1475{
1476 int
1477 compare;
1478
1479 NodeInfo
1480 **next;
1481
1482 register NodeInfo
1483 *n,
1484 *p;
1485
1486 n=(*node);
1487 if (n == (NodeInfo *) NULL)
1488 return(*parent);
1489 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1490 compare=splay_tree->compare(n->key,key);
1491 else
1492 compare=(n->key > key) ? 1 : ((n->key < key) ? -1 : 0);
1493 next=(NodeInfo **) NULL;
1494 if (compare > 0)
1495 next=(&n->left);
1496 else
1497 if (compare < 0)
1498 next=(&n->right);
1499 if (next != (NodeInfo **) NULL)
1500 {
1501 if (depth >= MaxSplayTreeDepth)
1502 {
1503 splay_tree->balance=MagickTrue;
1504 return(n);
1505 }
1506 n=Splay(splay_tree,depth+1,key,next,node,parent);
1507 if ((n != *node) || (splay_tree->balance != MagickFalse))
1508 return(n);
1509 }
1510 if (parent == (NodeInfo **) NULL)
1511 return(n);
1512 if (grandparent == (NodeInfo **) NULL)
1513 {
1514 if (n == (*parent)->left)
1515 {
1516 *node=n->right;
1517 n->right=(*parent);
1518 }
1519 else
1520 {
1521 *node=n->left;
1522 n->left=(*parent);
1523 }
1524 *parent=n;
1525 return(n);
1526 }
1527 if ((n == (*parent)->left) && (*parent == (*grandparent)->left))
1528 {
1529 p=(*parent);
1530 (*grandparent)->left=p->right;
1531 p->right=(*grandparent);
1532 p->left=n->right;
1533 n->right=p;
1534 *grandparent=n;
1535 return(n);
1536 }
1537 if ((n == (*parent)->right) && (*parent == (*grandparent)->right))
1538 {
1539 p=(*parent);
1540 (*grandparent)->right=p->left;
1541 p->left=(*grandparent);
1542 p->right=n->left;
1543 n->left=p;
1544 *grandparent=n;
1545 return(n);
1546 }
1547 if (n == (*parent)->left)
1548 {
1549 (*parent)->left=n->right;
1550 n->right=(*parent);
1551 (*grandparent)->right=n->left;
1552 n->left=(*grandparent);
1553 *grandparent=n;
1554 return(n);
1555 }
1556 (*parent)->right=n->left;
1557 n->left=(*parent);
1558 (*grandparent)->left=n->right;
1559 n->right=(*grandparent);
1560 *grandparent=n;
1561 return(n);
1562}
1563
1564static void SplaySplayTree(SplayTreeInfo *splay_tree,const void *key)
1565{
1566 if (splay_tree->root == (NodeInfo *) NULL)
1567 return;
1568 if (splay_tree->key != (void *) NULL)
1569 {
1570 int
1571 compare;
1572
1573 if (splay_tree->compare != (int (*)(const void *,const void *)) NULL)
1574 compare=splay_tree->compare(splay_tree->root->key,key);
1575 else
1576 compare=(splay_tree->key > key) ? 1 :
1577 ((splay_tree->key < key) ? -1 : 0);
1578 if (compare == 0)
1579 return;
1580 }
1581 (void) Splay(splay_tree,0UL,key,&splay_tree->root,(NodeInfo **) NULL,
1582 (NodeInfo **) NULL);
1583 if (splay_tree->balance != MagickFalse)
1584 {
1585 BalanceSplayTree(splay_tree);
1586 (void) Splay(splay_tree,0UL,key,&splay_tree->root,(NodeInfo **) NULL,
1587 (NodeInfo **) NULL);
1588 if (splay_tree->balance != MagickFalse)
1589 ThrowFatalException(ResourceLimitFatalError,
1590 "MemoryAllocationFailed");
1591 }
1592 splay_tree->key=(void *) key;
1593}