2005-12-29 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / ada / a-crbtgk.adb
blob6d748a30ec3855ca40f39ef0e03afa1e91954562
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
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 --
7 -- --
8 -- B o d y --
9 -- --
10 -- Copyright (C) 2004-2005, Free Software Foundation, Inc. --
11 -- --
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. --
15 -- --
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. --
26 -- --
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. --
33 -- --
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;
41 -------------
42 -- Ceiling --
43 -------------
45 -- AKA Lower_Bound
47 function Ceiling (Tree : Tree_Type; Key : Key_Type) return Node_Access is
48 Y : Node_Access;
49 X : Node_Access := Tree.Root;
51 begin
52 while X /= null loop
53 if Is_Greater_Key_Node (Key, X) then
54 X := Ops.Right (X);
55 else
56 Y := X;
57 X := Ops.Left (X);
58 end if;
59 end loop;
61 return Y;
62 end Ceiling;
64 ----------
65 -- Find --
66 ----------
68 function Find (Tree : Tree_Type; Key : Key_Type) return Node_Access is
69 Y : Node_Access;
70 X : Node_Access := Tree.Root;
72 begin
73 while X /= null loop
74 if Is_Greater_Key_Node (Key, X) then
75 X := Ops.Right (X);
76 else
77 Y := X;
78 X := Ops.Left (X);
79 end if;
80 end loop;
82 if Y = null then
83 return null;
84 end if;
86 if Is_Less_Key_Node (Key, Y) then
87 return null;
88 end if;
90 return Y;
91 end Find;
93 -----------
94 -- Floor --
95 -----------
97 function Floor (Tree : Tree_Type; Key : Key_Type) return Node_Access is
98 Y : Node_Access;
99 X : Node_Access := Tree.Root;
101 begin
102 while X /= null loop
103 if Is_Less_Key_Node (Key, X) then
104 X := Ops.Left (X);
105 else
106 Y := X;
107 X := Ops.Right (X);
108 end if;
109 end loop;
111 return Y;
112 end Floor;
114 --------------------------------
115 -- Generic_Conditional_Insert --
116 --------------------------------
118 procedure Generic_Conditional_Insert
119 (Tree : in out Tree_Type;
120 Key : Key_Type;
121 Node : out Node_Access;
122 Success : out Boolean)
124 Y : Node_Access := null;
125 X : Node_Access := Tree.Root;
127 begin
128 Success := True;
129 while X /= null loop
130 Y := X;
131 Success := Is_Less_Key_Node (Key, X);
133 if Success then
134 X := Ops.Left (X);
135 else
136 X := Ops.Right (X);
137 end if;
138 end loop;
140 Node := Y;
142 if Success then
143 if Node = Tree.First then
144 Insert_Post (Tree, X, Y, Key, Node);
145 return;
146 end if;
148 Node := Ops.Previous (Node);
149 end if;
151 if Is_Greater_Key_Node (Key, Node) then
152 Insert_Post (Tree, X, Y, Key, Node);
153 Success := True;
154 return;
155 end if;
157 Success := False;
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;
167 Key : Key_Type;
168 Node : out Node_Access;
169 Success : out Boolean)
171 begin
172 if Position = null then -- largest
173 if Tree.Length > 0
174 and then Is_Greater_Key_Node (Key, Tree.Last)
175 then
176 Insert_Post (Tree, null, Tree.Last, Key, Node);
177 Success := True;
178 else
179 Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
180 end if;
182 return;
183 end if;
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);
190 Success := True;
191 return;
192 end if;
194 declare
195 Before : constant Node_Access := Ops.Previous (Position);
197 begin
198 if Is_Greater_Key_Node (Key, Before) then
199 if Ops.Right (Before) = null then
200 Insert_Post (Tree, null, Before, Key, Node);
201 else
202 Insert_Post (Tree, Position, Position, Key, Node);
203 end if;
205 Success := True;
207 else
208 Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
209 end if;
210 end;
212 return;
213 end if;
215 if Is_Greater_Key_Node (Key, Position) then
216 if Position = Tree.Last then
217 Insert_Post (Tree, null, Tree.Last, Key, Node);
218 Success := True;
219 return;
220 end if;
222 declare
223 After : constant Node_Access := Ops.Next (Position);
225 begin
226 if Is_Less_Key_Node (Key, After) then
227 if Ops.Right (Position) = null then
228 Insert_Post (Tree, null, Position, Key, Node);
229 else
230 Insert_Post (Tree, After, After, Key, Node);
231 end if;
233 Success := True;
235 else
236 Conditional_Insert_Sans_Hint (Tree, Key, Node, Success);
237 end if;
238 end;
240 return;
241 end if;
243 Node := Position;
244 Success := False;
245 end Generic_Conditional_Insert_With_Hint;
247 -------------------------
248 -- Generic_Insert_Post --
249 -------------------------
251 procedure Generic_Insert_Post
252 (Tree : in out Tree_Type;
253 X, Y : Node_Access;
254 Key : Key_Type;
255 Z : out Node_Access)
257 subtype Length_Subtype is Count_Type range 0 .. Count_Type'Last - 1;
259 New_Length : constant Count_Type := Length_Subtype'(Tree.Length) + 1;
261 begin
262 if Tree.Busy > 0 then
263 raise Program_Error;
264 end if;
266 if Y = null
267 or else X /= null
268 or else Is_Less_Key_Node (Key, Y)
269 then
270 pragma Assert (Y = null
271 or else Ops.Left (Y) = null);
273 -- Delay allocation as long as we can, in order to defend
274 -- against exceptions propagated by relational operators.
276 Z := New_Node;
278 pragma Assert (Z /= null);
279 pragma Assert (Ops.Color (Z) = Red);
281 if Y = null then
282 pragma Assert (Tree.Length = 0);
283 pragma Assert (Tree.Root = null);
284 pragma Assert (Tree.First = null);
285 pragma Assert (Tree.Last = null);
287 Tree.Root := Z;
288 Tree.First := Z;
289 Tree.Last := Z;
291 else
292 Ops.Set_Left (Y, Z);
294 if Y = Tree.First then
295 Tree.First := Z;
296 end if;
297 end if;
299 else
300 pragma Assert (Ops.Right (Y) = null);
302 -- Delay allocation as long as we can, in order to defend
303 -- against exceptions propagated by relational operators.
305 Z := New_Node;
307 pragma Assert (Z /= null);
308 pragma Assert (Ops.Color (Z) = Red);
310 Ops.Set_Right (Y, Z);
312 if Y = Tree.Last then
313 Tree.Last := Z;
314 end if;
315 end if;
317 Ops.Set_Parent (Z, Y);
318 Ops.Rebalance_For_Insert (Tree, Z);
319 Tree.Length := New_Length;
320 end Generic_Insert_Post;
322 -----------------------
323 -- Generic_Iteration --
324 -----------------------
326 procedure Generic_Iteration
327 (Tree : Tree_Type;
328 Key : Key_Type)
330 procedure Iterate (Node : Node_Access);
332 -------------
333 -- Iterate --
334 -------------
336 procedure Iterate (Node : Node_Access) is
337 N : Node_Access := Node;
338 begin
339 while N /= null loop
340 if Is_Less_Key_Node (Key, N) then
341 N := Ops.Left (N);
342 elsif Is_Greater_Key_Node (Key, N) then
343 N := Ops.Right (N);
344 else
345 Iterate (Ops.Left (N));
346 Process (N);
347 N := Ops.Right (N);
348 end if;
349 end loop;
350 end Iterate;
352 -- Start of processing for Generic_Iteration
354 begin
355 Iterate (Tree.Root);
356 end Generic_Iteration;
358 -------------------------------
359 -- Generic_Reverse_Iteration --
360 -------------------------------
362 procedure Generic_Reverse_Iteration
363 (Tree : Tree_Type;
364 Key : Key_Type)
366 procedure Iterate (Node : Node_Access);
368 -------------
369 -- Iterate --
370 -------------
372 procedure Iterate (Node : Node_Access) is
373 N : Node_Access := Node;
374 begin
375 while N /= null loop
376 if Is_Less_Key_Node (Key, N) then
377 N := Ops.Left (N);
378 elsif Is_Greater_Key_Node (Key, N) then
379 N := Ops.Right (N);
380 else
381 Iterate (Ops.Right (N));
382 Process (N);
383 N := Ops.Left (N);
384 end if;
385 end loop;
386 end Iterate;
388 -- Start of processing for Generic_Reverse_Iteration
390 begin
391 Iterate (Tree.Root);
392 end Generic_Reverse_Iteration;
394 ----------------------------------
395 -- Generic_Unconditional_Insert --
396 ----------------------------------
398 procedure Generic_Unconditional_Insert
399 (Tree : in out Tree_Type;
400 Key : Key_Type;
401 Node : out Node_Access)
403 Y : Node_Access := null;
404 X : Node_Access := Tree.Root;
406 begin
407 while X /= null loop
408 Y := X;
410 if Is_Less_Key_Node (Key, X) then
411 X := Ops.Left (X);
412 else
413 X := Ops.Right (X);
414 end if;
415 end loop;
417 Insert_Post (Tree, X, Y, Key, Node);
418 end Generic_Unconditional_Insert;
420 --------------------------------------------
421 -- Generic_Unconditional_Insert_With_Hint --
422 --------------------------------------------
424 procedure Generic_Unconditional_Insert_With_Hint
425 (Tree : in out Tree_Type;
426 Hint : Node_Access;
427 Key : Key_Type;
428 Node : out Node_Access)
430 -- TODO: verify this algorithm. It was (quickly) adapted it from the
431 -- same algorithm for conditional_with_hint. It may be that the test
432 -- Key > Hint should be something like a Key >= Hint, to handle the
433 -- case when Hint is The Last Item of A (Contiguous) sequence of
434 -- Equivalent Items. (The Key < Hint Test is probably OK. It is not
435 -- clear that you can use Key <= Hint, since new items are always
436 -- inserted last in the sequence of equivalent items.) ???
438 begin
439 if Hint = null then -- largest
440 if Tree.Length > 0
441 and then Is_Greater_Key_Node (Key, Tree.Last)
442 then
443 Insert_Post (Tree, null, Tree.Last, Key, Node);
444 else
445 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
446 end if;
448 return;
449 end if;
451 pragma Assert (Tree.Length > 0);
453 if Is_Less_Key_Node (Key, Hint) then
454 if Hint = Tree.First then
455 Insert_Post (Tree, Hint, Hint, Key, Node);
456 return;
457 end if;
459 declare
460 Before : constant Node_Access := Ops.Previous (Hint);
461 begin
462 if Is_Greater_Key_Node (Key, Before) then
463 if Ops.Right (Before) = null then
464 Insert_Post (Tree, null, Before, Key, Node);
465 else
466 Insert_Post (Tree, Hint, Hint, Key, Node);
467 end if;
468 else
469 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
470 end if;
471 end;
473 return;
474 end if;
476 if Is_Greater_Key_Node (Key, Hint) then
477 if Hint = Tree.Last then
478 Insert_Post (Tree, null, Tree.Last, Key, Node);
479 return;
480 end if;
482 declare
483 After : constant Node_Access := Ops.Next (Hint);
484 begin
485 if Is_Less_Key_Node (Key, After) then
486 if Ops.Right (Hint) = null then
487 Insert_Post (Tree, null, Hint, Key, Node);
488 else
489 Insert_Post (Tree, After, After, Key, Node);
490 end if;
491 else
492 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
493 end if;
494 end;
496 return;
497 end if;
499 Unconditional_Insert_Sans_Hint (Tree, Key, Node);
500 end Generic_Unconditional_Insert_With_Hint;
502 -----------------
503 -- Upper_Bound --
504 -----------------
506 function Upper_Bound
507 (Tree : Tree_Type;
508 Key : Key_Type) return Node_Access
510 Y : Node_Access;
511 X : Node_Access := Tree.Root;
513 begin
514 while X /= null loop
515 if Is_Less_Key_Node (Key, X) then
516 Y := X;
517 X := Ops.Left (X);
518 else
519 X := Ops.Right (X);
520 end if;
521 end loop;
523 return Y;
524 end Upper_Bound;
526 end Ada.Containers.Red_Black_Trees.Generic_Keys;