Mark ChangeLog
[official-gcc.git] / gcc / ada / a-crbtgk.adb
blob70c8f35278c6a92fdae74e27949a255f60da281f
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- ADA.CONTAINERS.RED_BLACK_TREES.GENERIC_KEYS --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2004 Free Software Foundation, Inc. --
10 -- --
11 -- This specification is derived from the Ada Reference Manual for use with --
12 -- GNAT. The copyright notice above, and the license provisions that follow --
13 -- apply solely to the contents of the part following the private keyword. --
14 -- --
15 -- GNAT is free software; you can redistribute it and/or modify it under --
16 -- terms of the GNU General Public License as published by the Free Soft- --
17 -- ware Foundation; either version 2, or (at your option) any later ver- --
18 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
19 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
20 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
21 -- for more details. You should have received a copy of the GNU General --
22 -- Public License distributed with GNAT; see file COPYING. If not, write --
23 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
24 -- MA 02111-1307, USA. --
25 -- --
26 -- As a special exception, if other files instantiate generics from this --
27 -- unit, or you link this unit with other files to produce an executable, --
28 -- this unit does not by itself cause the resulting executable to be --
29 -- covered by the GNU General Public License. This exception does not --
30 -- however invalidate any other reasons why the executable file might be --
31 -- covered by the GNU Public License. --
32 -- --
33 -- This unit was originally developed by Matthew J Heaney. --
34 ------------------------------------------------------------------------------
36 package body Ada.Containers.Red_Black_Trees.Generic_Keys is
38 package Ops renames Tree_Operations;
40 -------------
41 -- Ceiling --
42 -------------
44 -- AKA Lower_Bound
46 function Ceiling (Tree : Tree_Type; Key : Key_Type) return Node_Access is
47 Y : Node_Access;
48 X : Node_Access := Tree.Root;
50 begin
51 while X /= Ops.Null_Node loop
52 if Is_Greater_Key_Node (Key, X) then
53 X := Ops.Right (X);
54 else
55 Y := X;
56 X := Ops.Left (X);
57 end if;
58 end loop;
60 return Y;
61 end Ceiling;
63 ----------
64 -- Find --
65 ----------
67 function Find (Tree : Tree_Type; Key : Key_Type) return Node_Access is
68 Y : Node_Access;
69 X : Node_Access := Tree.Root;
71 begin
72 while X /= Ops.Null_Node loop
73 if Is_Greater_Key_Node (Key, X) then
74 X := Ops.Right (X);
75 else
76 Y := X;
77 X := Ops.Left (X);
78 end if;
79 end loop;
81 if Y = Ops.Null_Node then
82 return Ops.Null_Node;
83 end if;
85 if Is_Less_Key_Node (Key, Y) then
86 return Ops.Null_Node;
87 end if;
89 return Y;
90 end Find;
92 -----------
93 -- Floor --
94 -----------
96 function Floor (Tree : Tree_Type; Key : Key_Type) return Node_Access is
97 Y : Node_Access;
98 X : Node_Access := Tree.Root;
100 begin
101 while X /= Ops.Null_Node loop
102 if Is_Less_Key_Node (Key, X) then
103 X := Ops.Left (X);
104 else
105 Y := X;
106 X := Ops.Right (X);
107 end if;
108 end loop;
110 return Y;
111 end Floor;
113 --------------------------------
114 -- Generic_Conditional_Insert --
115 --------------------------------
117 procedure Generic_Conditional_Insert
118 (Tree : in out Tree_Type;
119 Key : Key_Type;
120 Node : out Node_Access;
121 Success : out Boolean)
123 Y : Node_Access := Ops.Null_Node;
124 X : Node_Access := Tree.Root;
126 begin
127 Success := True;
128 while X /= Ops.Null_Node loop
129 Y := X;
130 Success := Is_Less_Key_Node (Key, X);
132 if Success then
133 X := Ops.Left (X);
134 else
135 X := Ops.Right (X);
136 end if;
137 end loop;
139 Node := Y;
141 if Success then
142 if Node = Tree.First then
143 Insert_Post (Tree, X, Y, Key, Node);
144 return;
145 end if;
147 Node := Ops.Previous (Node);
148 end if;
150 if Is_Greater_Key_Node (Key, Node) then
151 Insert_Post (Tree, X, Y, Key, Node);
152 Success := True;
153 return;
154 end if;
156 Success := False;
157 end Generic_Conditional_Insert;
159 ------------------------------------------
160 -- Generic_Conditional_Insert_With_Hint --
161 ------------------------------------------
163 procedure Generic_Conditional_Insert_With_Hint
164 (Tree : in out Tree_Type;
165 Position : Node_Access;
166 Key : Key_Type;
167 Node : out Node_Access;
168 Success : out Boolean)
170 begin
171 if Position = Ops.Null_Node then -- largest
172 if Tree.Length > 0
173 and then Is_Greater_Key_Node (Key, Tree.Last)
174 then
175 Insert_Post (Tree, Ops.Null_Node, Tree.Last, Key, Node);
176 Success := True;
177 else
178 Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
179 end if;
181 return;
182 end if;
184 pragma Assert (Tree.Length > 0);
186 if Is_Less_Key_Node (Key, Position) then
187 if Position = Tree.First then
188 Insert_Post (Tree, Position, Position, Key, Node);
189 Success := True;
190 return;
191 end if;
193 declare
194 Before : constant Node_Access := Ops.Previous (Position);
196 begin
197 if Is_Greater_Key_Node (Key, Before) then
198 if Ops.Right (Before) = Ops.Null_Node then
199 Insert_Post (Tree, Ops.Null_Node, Before, Key, Node);
200 else
201 Insert_Post (Tree, Position, Position, Key, Node);
202 end if;
204 Success := True;
206 else
207 Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
208 end if;
209 end;
211 return;
212 end if;
214 if Is_Greater_Key_Node (Key, Position) then
215 if Position = Tree.Last then
216 Insert_Post (Tree, Ops.Null_Node, Tree.Last, Key, Node);
217 Success := True;
218 return;
219 end if;
221 declare
222 After : constant Node_Access := Ops.Next (Position);
224 begin
225 if Is_Less_Key_Node (Key, After) then
226 if Ops.Right (Position) = Ops.Null_Node then
227 Insert_Post (Tree, Ops.Null_Node, Position, Key, Node);
228 else
229 Insert_Post (Tree, After, After, Key, Node);
230 end if;
232 Success := True;
234 else
235 Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
236 end if;
237 end;
239 return;
240 end if;
242 Node := Position;
243 Success := False;
244 end Generic_Conditional_Insert_With_Hint;
246 -------------------------
247 -- Generic_Insert_Post --
248 -------------------------
250 procedure Generic_Insert_Post
251 (Tree : in out Tree_Type;
252 X, Y : Node_Access;
253 Key : Key_Type;
254 Z : out Node_Access)
256 subtype Length_Subtype is Count_Type range 0 .. Count_Type'Last - 1;
258 New_Length : constant Count_Type := Length_Subtype'(Tree.Length) + 1;
260 begin
261 if Y = Ops.Null_Node
262 or else X /= Ops.Null_Node
263 or else Is_Less_Key_Node (Key, Y)
264 then
265 pragma Assert (Y = Ops.Null_Node
266 or else Ops.Left (Y) = Ops.Null_Node);
268 -- Delay allocation as long as we can, in order to defend
269 -- against exceptions propagated by relational operators.
271 Z := New_Node;
273 pragma Assert (Z /= Ops.Null_Node);
274 pragma Assert (Ops.Color (Z) = Red);
276 if Y = Ops.Null_Node then
277 pragma Assert (Tree.Length = 0);
278 pragma Assert (Tree.Root = Ops.Null_Node);
279 pragma Assert (Tree.First = Ops.Null_Node);
280 pragma Assert (Tree.Last = Ops.Null_Node);
282 Tree.Root := Z;
283 Tree.First := Z;
284 Tree.Last := Z;
286 else
287 Ops.Set_Left (Y, Z);
289 if Y = Tree.First then
290 Tree.First := Z;
291 end if;
292 end if;
294 else
295 pragma Assert (Ops.Right (Y) = Ops.Null_Node);
297 -- Delay allocation as long as we can, in order to defend
298 -- against exceptions propagated by relational operators.
300 Z := New_Node;
302 pragma Assert (Z /= Ops.Null_Node);
303 pragma Assert (Ops.Color (Z) = Red);
305 Ops.Set_Right (Y, Z);
307 if Y = Tree.Last then
308 Tree.Last := Z;
309 end if;
310 end if;
312 Ops.Set_Parent (Z, Y);
313 Ops.Rebalance_For_Insert (Tree, Z);
314 Tree.Length := New_Length;
315 end Generic_Insert_Post;
317 -----------------------
318 -- Generic_Iteration --
319 -----------------------
321 procedure Generic_Iteration
322 (Tree : Tree_Type;
323 Key : Key_Type)
325 procedure Iterate (Node : Node_Access);
327 -------------
328 -- Iterate --
329 -------------
331 procedure Iterate (Node : Node_Access) is
332 N : Node_Access := Node;
333 begin
334 while N /= Ops.Null_Node loop
335 if Is_Less_Key_Node (Key, N) then
336 N := Ops.Left (N);
337 elsif Is_Greater_Key_Node (Key, N) then
338 N := Ops.Right (N);
339 else
340 Iterate (Ops.Left (N));
341 Process (N);
342 N := Ops.Right (N);
343 end if;
344 end loop;
345 end Iterate;
347 -- Start of processing for Generic_Iteration
349 begin
350 Iterate (Tree.Root);
351 end Generic_Iteration;
353 -------------------------------
354 -- Generic_Reverse_Iteration --
355 -------------------------------
357 procedure Generic_Reverse_Iteration
358 (Tree : Tree_Type;
359 Key : Key_Type)
361 procedure Iterate (Node : Node_Access);
363 -------------
364 -- Iterate --
365 -------------
367 procedure Iterate (Node : Node_Access) is
368 N : Node_Access := Node;
369 begin
370 while N /= Ops.Null_Node loop
371 if Is_Less_Key_Node (Key, N) then
372 N := Ops.Left (N);
373 elsif Is_Greater_Key_Node (Key, N) then
374 N := Ops.Right (N);
375 else
376 Iterate (Ops.Right (N));
377 Process (N);
378 N := Ops.Left (N);
379 end if;
380 end loop;
381 end Iterate;
383 -- Start of processing for Generic_Reverse_Iteration
385 begin
386 Iterate (Tree.Root);
387 end Generic_Reverse_Iteration;
389 ----------------------------------
390 -- Generic_Unconditional_Insert --
391 ----------------------------------
393 procedure Generic_Unconditional_Insert
394 (Tree : in out Tree_Type;
395 Key : Key_Type;
396 Node : out Node_Access)
398 Y : Node_Access := Ops.Null_Node;
399 X : Node_Access := Tree.Root;
401 begin
402 while X /= Ops.Null_Node loop
403 Y := X;
405 if Is_Less_Key_Node (Key, X) then
406 X := Ops.Left (X);
407 else
408 X := Ops.Right (X);
409 end if;
410 end loop;
412 Insert_Post (Tree, X, Y, Key, Node);
413 end Generic_Unconditional_Insert;
415 --------------------------------------------
416 -- Generic_Unconditional_Insert_With_Hint --
417 --------------------------------------------
419 procedure Generic_Unconditional_Insert_With_Hint
420 (Tree : in out Tree_Type;
421 Hint : Node_Access;
422 Key : Key_Type;
423 Node : out Node_Access)
425 -- TODO: verify this algorithm. It was (quickly) adapted it from the
426 -- same algorithm for conditional_with_hint. It may be that the test
427 -- Key > Hint should be something like a Key >= Hint, to handle the
428 -- case when Hint is The Last Item of A (Contiguous) sequence of
429 -- Equivalent Items. (The Key < Hint Test is probably OK. It is not
430 -- clear that you can use Key <= Hint, since new items are always
431 -- inserted last in the sequence of equivalent items.) ???
433 begin
434 if Hint = Ops.Null_Node then -- largest
435 if Tree.Length > 0
436 and then Is_Greater_Key_Node (Key, Tree.Last)
437 then
438 Insert_Post (Tree, Ops.Null_Node, Tree.Last, Key, Node);
439 else
440 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
441 end if;
443 return;
444 end if;
446 pragma Assert (Tree.Length > 0);
448 if Is_Less_Key_Node (Key, Hint) then
449 if Hint = Tree.First then
450 Insert_Post (Tree, Hint, Hint, Key, Node);
451 return;
452 end if;
454 declare
455 Before : constant Node_Access := Ops.Previous (Hint);
456 begin
457 if Is_Greater_Key_Node (Key, Before) then
458 if Ops.Right (Before) = Ops.Null_Node then
459 Insert_Post (Tree, Ops.Null_Node, Before, Key, Node);
460 else
461 Insert_Post (Tree, Hint, Hint, Key, Node);
462 end if;
463 else
464 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
465 end if;
466 end;
468 return;
469 end if;
471 if Is_Greater_Key_Node (Key, Hint) then
472 if Hint = Tree.Last then
473 Insert_Post (Tree, Ops.Null_Node, Tree.Last, Key, Node);
474 return;
475 end if;
477 declare
478 After : constant Node_Access := Ops.Next (Hint);
479 begin
480 if Is_Less_Key_Node (Key, After) then
481 if Ops.Right (Hint) = Ops.Null_Node then
482 Insert_Post (Tree, Ops.Null_Node, Hint, Key, Node);
483 else
484 Insert_Post (Tree, After, After, Key, Node);
485 end if;
486 else
487 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
488 end if;
489 end;
491 return;
492 end if;
494 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
495 end Generic_Unconditional_Insert_With_Hint;
497 -----------------
498 -- Upper_Bound --
499 -----------------
501 function Upper_Bound
502 (Tree : Tree_Type;
503 Key : Key_Type) return Node_Access
505 Y : Node_Access;
506 X : Node_Access := Tree.Root;
508 begin
509 while X /= Ops.Null_Node loop
510 if Is_Less_Key_Node (Key, X) then
511 Y := X;
512 X := Ops.Left (X);
513 else
514 X := Ops.Right (X);
515 end if;
516 end loop;
518 return Y;
519 end Upper_Bound;
521 end Ada.Containers.Red_Black_Trees.Generic_Keys;