1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . R E D _ B L A C K _ T R E E S . --
6 -- G E N E R I C _ K E Y S --
10 -- Copyright (C) 2004-2005, Free Software Foundation, Inc. --
12 -- This specification is derived from the Ada Reference Manual for use with --
13 -- GNAT. The copyright notice above, and the license provisions that follow --
14 -- apply solely to the contents of the part following the private keyword. --
16 -- GNAT is free software; you can redistribute it and/or modify it under --
17 -- terms of the GNU General Public License as published by the Free Soft- --
18 -- ware Foundation; either version 2, or (at your option) any later ver- --
19 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
20 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
21 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
22 -- for more details. You should have received a copy of the GNU General --
23 -- Public License distributed with GNAT; see file COPYING. If not, write --
24 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
25 -- Boston, MA 02110-1301, USA. --
27 -- As a special exception, if other files instantiate generics from this --
28 -- unit, or you link this unit with other files to produce an executable, --
29 -- this unit does not by itself cause the resulting executable to be --
30 -- covered by the GNU General Public License. This exception does not --
31 -- however invalidate any other reasons why the executable file might be --
32 -- covered by the GNU Public License. --
34 -- This unit was originally developed by Matthew J Heaney. --
35 ------------------------------------------------------------------------------
37 package body Ada.Containers.Red_Black_Trees.Generic_Keys is
39 package Ops renames Tree_Operations;
47 function Ceiling (Tree : Tree_Type; Key : Key_Type) return Node_Access is
49 X : Node_Access := Tree.Root;
53 if Is_Greater_Key_Node (Key, X) then
68 function Find (Tree : Tree_Type; Key : Key_Type) return Node_Access is
70 X : Node_Access := Tree.Root;
74 if Is_Greater_Key_Node (Key, X) then
86 if Is_Less_Key_Node (Key, Y) then
97 function Floor (Tree : Tree_Type; Key : Key_Type) return Node_Access is
99 X : Node_Access := Tree.Root;
103 if Is_Less_Key_Node (Key, X) then
114 --------------------------------
115 -- Generic_Conditional_Insert --
116 --------------------------------
118 procedure Generic_Conditional_Insert
119 (Tree : in out Tree_Type;
121 Node : out Node_Access;
122 Success : out Boolean)
124 Y : Node_Access := null;
125 X : Node_Access := Tree.Root;
131 Success := Is_Less_Key_Node (Key, X);
143 if Node = Tree.First then
144 Insert_Post (Tree, X, Y, Key, Node);
148 Node := Ops.Previous (Node);
151 if Is_Greater_Key_Node (Key, Node) then
152 Insert_Post (Tree, X, Y, Key, Node);
158 end Generic_Conditional_Insert;
160 ------------------------------------------
161 -- Generic_Conditional_Insert_With_Hint --
162 ------------------------------------------
164 procedure Generic_Conditional_Insert_With_Hint
165 (Tree : in out Tree_Type;
166 Position : Node_Access;
168 Node : out Node_Access;
169 Success : out Boolean)
172 if Position = null then -- largest
174 and then Is_Greater_Key_Node (Key, Tree.Last)
176 Insert_Post (Tree, null, Tree.Last, Key, Node);
179 Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
185 pragma Assert (Tree.Length > 0);
187 if Is_Less_Key_Node (Key, Position) then
188 if Position = Tree.First then
189 Insert_Post (Tree, Position, Position, Key, Node);
195 Before : constant Node_Access := Ops.Previous (Position);
198 if Is_Greater_Key_Node (Key, Before) then
199 if Ops.Right (Before) = null then
200 Insert_Post (Tree, null, Before, Key, Node);
202 Insert_Post (Tree, Position, Position, Key, Node);
208 Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
215 if Is_Greater_Key_Node (Key, Position) then
216 if Position = Tree.Last then
217 Insert_Post (Tree, null, Tree.Last, Key, Node);
223 After : constant Node_Access := Ops.Next (Position);
226 if Is_Less_Key_Node (Key, After) then
227 if Ops.Right (Position) = null then
228 Insert_Post (Tree, null, Position, Key, Node);
230 Insert_Post (Tree, After, After, Key, Node);
236 Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
245 end Generic_Conditional_Insert_With_Hint;
247 -------------------------
248 -- Generic_Insert_Post --
249 -------------------------
251 procedure Generic_Insert_Post
252 (Tree : in out Tree_Type;
258 if Tree.Length = Count_Type'Last then
259 raise Constraint_Error with "too many elements";
262 if Tree.Busy > 0 then
263 raise Program_Error with
264 "attempt to tamper with cursors (container is busy)";
269 or else Is_Less_Key_Node (Key, Y)
271 pragma Assert (Y = null
272 or else Ops.Left (Y) = null);
274 -- Delay allocation as long as we can, in order to defend
275 -- against exceptions propagated by relational operators.
279 pragma Assert (Z /= null);
280 pragma Assert (Ops.Color (Z) = Red);
283 pragma Assert (Tree.Length = 0);
284 pragma Assert (Tree.Root = null);
285 pragma Assert (Tree.First = null);
286 pragma Assert (Tree.Last = null);
295 if Y = Tree.First then
301 pragma Assert (Ops.Right (Y) = null);
303 -- Delay allocation as long as we can, in order to defend
304 -- against exceptions propagated by relational operators.
308 pragma Assert (Z /= null);
309 pragma Assert (Ops.Color (Z) = Red);
311 Ops.Set_Right (Y, Z);
313 if Y = Tree.Last then
318 Ops.Set_Parent (Z, Y);
319 Ops.Rebalance_For_Insert (Tree, Z);
320 Tree.Length := Tree.Length + 1;
321 end Generic_Insert_Post;
323 -----------------------
324 -- Generic_Iteration --
325 -----------------------
327 procedure Generic_Iteration
331 procedure Iterate (Node : Node_Access);
337 procedure Iterate (Node : Node_Access) is
338 N : Node_Access := Node;
341 if Is_Less_Key_Node (Key, N) then
343 elsif Is_Greater_Key_Node (Key, N) then
346 Iterate (Ops.Left (N));
353 -- Start of processing for Generic_Iteration
357 end Generic_Iteration;
359 -------------------------------
360 -- Generic_Reverse_Iteration --
361 -------------------------------
363 procedure Generic_Reverse_Iteration
367 procedure Iterate (Node : Node_Access);
373 procedure Iterate (Node : Node_Access) is
374 N : Node_Access := Node;
377 if Is_Less_Key_Node (Key, N) then
379 elsif Is_Greater_Key_Node (Key, N) then
382 Iterate (Ops.Right (N));
389 -- Start of processing for Generic_Reverse_Iteration
393 end Generic_Reverse_Iteration;
395 ----------------------------------
396 -- Generic_Unconditional_Insert --
397 ----------------------------------
399 procedure Generic_Unconditional_Insert
400 (Tree : in out Tree_Type;
402 Node : out Node_Access)
404 Y : Node_Access := null;
405 X : Node_Access := Tree.Root;
411 if Is_Less_Key_Node (Key, X) then
418 Insert_Post (Tree, X, Y, Key, Node);
419 end Generic_Unconditional_Insert;
421 --------------------------------------------
422 -- Generic_Unconditional_Insert_With_Hint --
423 --------------------------------------------
425 procedure Generic_Unconditional_Insert_With_Hint
426 (Tree : in out Tree_Type;
429 Node : out Node_Access)
431 -- TODO: verify this algorithm. It was (quickly) adapted it from the
432 -- same algorithm for conditional_with_hint. It may be that the test
433 -- Key > Hint should be something like a Key >= Hint, to handle the
434 -- case when Hint is The Last Item of A (Contiguous) sequence of
435 -- Equivalent Items. (The Key < Hint Test is probably OK. It is not
436 -- clear that you can use Key <= Hint, since new items are always
437 -- inserted last in the sequence of equivalent items.) ???
440 if Hint = null then -- largest
442 and then Is_Greater_Key_Node (Key, Tree.Last)
444 Insert_Post (Tree, null, Tree.Last, Key, Node);
446 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
452 pragma Assert (Tree.Length > 0);
454 if Is_Less_Key_Node (Key, Hint) then
455 if Hint = Tree.First then
456 Insert_Post (Tree, Hint, Hint, Key, Node);
461 Before : constant Node_Access := Ops.Previous (Hint);
463 if Is_Greater_Key_Node (Key, Before) then
464 if Ops.Right (Before) = null then
465 Insert_Post (Tree, null, Before, Key, Node);
467 Insert_Post (Tree, Hint, Hint, Key, Node);
470 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
477 if Is_Greater_Key_Node (Key, Hint) then
478 if Hint = Tree.Last then
479 Insert_Post (Tree, null, Tree.Last, Key, Node);
484 After : constant Node_Access := Ops.Next (Hint);
486 if Is_Less_Key_Node (Key, After) then
487 if Ops.Right (Hint) = null then
488 Insert_Post (Tree, null, Hint, Key, Node);
490 Insert_Post (Tree, After, After, Key, Node);
493 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
500 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
501 end Generic_Unconditional_Insert_With_Hint;
509 Key : Key_Type) return Node_Access
512 X : Node_Access := Tree.Root;
516 if Is_Less_Key_Node (Key, X) then
527 end Ada.Containers.Red_Black_Trees.Generic_Keys;