Merge from mainline
[official-gcc.git] / gcc / ada / a-ciorse.adb
blob0e11e6506edc766c21986a2400e427c54292f70a
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT LIBRARY COMPONENTS --
4 -- --
5 -- A D A . C O N T A I N E R S . --
6 -- I N D E F I N I T E _ O R D E R E D _ S E T 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 with Ada.Containers.Red_Black_Trees.Generic_Operations;
38 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
40 with Ada.Containers.Red_Black_Trees.Generic_Keys;
41 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
43 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
44 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
46 with Ada.Unchecked_Deallocation;
48 package body Ada.Containers.Indefinite_Ordered_Sets is
50 -----------------------
51 -- Local Subprograms --
52 -----------------------
54 function Color (Node : Node_Access) return Color_Type;
55 pragma Inline (Color);
57 function Copy_Node (Source : Node_Access) return Node_Access;
58 pragma Inline (Copy_Node);
60 procedure Free (X : in out Node_Access);
62 procedure Insert_Sans_Hint
63 (Tree : in out Tree_Type;
64 New_Item : Element_Type;
65 Node : out Node_Access;
66 Inserted : out Boolean);
68 procedure Insert_With_Hint
69 (Dst_Tree : in out Tree_Type;
70 Dst_Hint : Node_Access;
71 Src_Node : Node_Access;
72 Dst_Node : out Node_Access);
74 function Is_Greater_Element_Node
75 (Left : Element_Type;
76 Right : Node_Access) return Boolean;
77 pragma Inline (Is_Greater_Element_Node);
79 function Is_Less_Element_Node
80 (Left : Element_Type;
81 Right : Node_Access) return Boolean;
82 pragma Inline (Is_Less_Element_Node);
84 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
85 pragma Inline (Is_Less_Node_Node);
87 function Left (Node : Node_Access) return Node_Access;
88 pragma Inline (Left);
90 function Parent (Node : Node_Access) return Node_Access;
91 pragma Inline (Parent);
93 procedure Replace_Element
94 (Tree : in out Tree_Type;
95 Node : Node_Access;
96 Item : Element_Type);
98 function Right (Node : Node_Access) return Node_Access;
99 pragma Inline (Right);
101 procedure Set_Color (Node : Node_Access; Color : Color_Type);
102 pragma Inline (Set_Color);
104 procedure Set_Left (Node : Node_Access; Left : Node_Access);
105 pragma Inline (Set_Left);
107 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
108 pragma Inline (Set_Parent);
110 procedure Set_Right (Node : Node_Access; Right : Node_Access);
111 pragma Inline (Set_Right);
113 --------------------------
114 -- Local Instantiations --
115 --------------------------
117 procedure Free_Element is
118 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
120 package Tree_Operations is
121 new Red_Black_Trees.Generic_Operations (Tree_Types);
123 procedure Delete_Tree is
124 new Tree_Operations.Generic_Delete_Tree (Free);
126 function Copy_Tree is
127 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
129 use Tree_Operations;
131 package Element_Keys is
132 new Red_Black_Trees.Generic_Keys
133 (Tree_Operations => Tree_Operations,
134 Key_Type => Element_Type,
135 Is_Less_Key_Node => Is_Less_Element_Node,
136 Is_Greater_Key_Node => Is_Greater_Element_Node);
138 package Set_Ops is
139 new Generic_Set_Operations
140 (Tree_Operations => Tree_Operations,
141 Insert_With_Hint => Insert_With_Hint,
142 Copy_Tree => Copy_Tree,
143 Delete_Tree => Delete_Tree,
144 Is_Less => Is_Less_Node_Node,
145 Free => Free);
147 ---------
148 -- "<" --
149 ---------
151 function "<" (Left, Right : Cursor) return Boolean is
152 begin
153 if Left.Node = null then
154 raise Constraint_Error with "Left cursor equals No_Element";
155 end if;
157 if Right.Node = null then
158 raise Constraint_Error with "Right cursor equals No_Element";
159 end if;
161 if Left.Node.Element = null then
162 raise Program_Error with "Left cursor is bad";
163 end if;
165 if Right.Node.Element = null then
166 raise Program_Error with "Right cursor is bad";
167 end if;
169 pragma Assert (Vet (Left.Container.Tree, Left.Node),
170 "bad Left cursor in ""<""");
172 pragma Assert (Vet (Right.Container.Tree, Right.Node),
173 "bad Right cursor in ""<""");
175 return Left.Node.Element.all < Right.Node.Element.all;
176 end "<";
178 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
179 begin
180 if Left.Node = null then
181 raise Constraint_Error with "Left cursor equals No_Element";
182 end if;
184 if Left.Node.Element = null then
185 raise Program_Error with "Left cursor is bad";
186 end if;
188 pragma Assert (Vet (Left.Container.Tree, Left.Node),
189 "bad Left cursor in ""<""");
191 return Left.Node.Element.all < Right;
192 end "<";
194 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
195 begin
196 if Right.Node = null then
197 raise Constraint_Error with "Right cursor equals No_Element";
198 end if;
200 if Right.Node.Element = null then
201 raise Program_Error with "Right cursor is bad";
202 end if;
204 pragma Assert (Vet (Right.Container.Tree, Right.Node),
205 "bad Right cursor in ""<""");
207 return Left < Right.Node.Element.all;
208 end "<";
210 ---------
211 -- "=" --
212 ---------
214 function "=" (Left, Right : Set) return Boolean is
216 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
217 pragma Inline (Is_Equal_Node_Node);
219 function Is_Equal is
220 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
222 ------------------------
223 -- Is_Equal_Node_Node --
224 ------------------------
226 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
227 begin
228 return L.Element.all = R.Element.all;
229 end Is_Equal_Node_Node;
231 -- Start of processing for "="
233 begin
234 return Is_Equal (Left.Tree, Right.Tree);
235 end "=";
237 ---------
238 -- ">" --
239 ---------
241 function ">" (Left, Right : Cursor) return Boolean is
242 begin
243 if Left.Node = null then
244 raise Constraint_Error with "Left cursor equals No_Element";
245 end if;
247 if Right.Node = null then
248 raise Constraint_Error with "Right cursor equals No_Element";
249 end if;
251 if Left.Node.Element = null then
252 raise Program_Error with "Left cursor is bad";
253 end if;
255 if Right.Node.Element = null then
256 raise Program_Error with "Right cursor is bad";
257 end if;
259 pragma Assert (Vet (Left.Container.Tree, Left.Node),
260 "bad Left cursor in "">""");
262 pragma Assert (Vet (Right.Container.Tree, Right.Node),
263 "bad Right cursor in "">""");
265 -- L > R same as R < L
267 return Right.Node.Element.all < Left.Node.Element.all;
268 end ">";
270 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
271 begin
272 if Left.Node = null then
273 raise Constraint_Error with "Left cursor equals No_Element";
274 end if;
276 if Left.Node.Element = null then
277 raise Program_Error with "Left cursor is bad";
278 end if;
280 pragma Assert (Vet (Left.Container.Tree, Left.Node),
281 "bad Left cursor in "">""");
283 return Right < Left.Node.Element.all;
284 end ">";
286 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
287 begin
288 if Right.Node = null then
289 raise Constraint_Error with "Right cursor equals No_Element";
290 end if;
292 if Right.Node.Element = null then
293 raise Program_Error with "Right cursor is bad";
294 end if;
296 pragma Assert (Vet (Right.Container.Tree, Right.Node),
297 "bad Right cursor in "">""");
299 return Right.Node.Element.all < Left;
300 end ">";
302 ------------
303 -- Adjust --
304 ------------
306 procedure Adjust is
307 new Tree_Operations.Generic_Adjust (Copy_Tree);
309 procedure Adjust (Container : in out Set) is
310 begin
311 Adjust (Container.Tree);
312 end Adjust;
314 -------------
315 -- Ceiling --
316 -------------
318 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
319 Node : constant Node_Access :=
320 Element_Keys.Ceiling (Container.Tree, Item);
322 begin
323 if Node = null then
324 return No_Element;
325 end if;
327 return Cursor'(Container'Unrestricted_Access, Node);
328 end Ceiling;
330 -----------
331 -- Clear --
332 -----------
334 procedure Clear is
335 new Tree_Operations.Generic_Clear (Delete_Tree);
337 procedure Clear (Container : in out Set) is
338 begin
339 Clear (Container.Tree);
340 end Clear;
342 -----------
343 -- Color --
344 -----------
346 function Color (Node : Node_Access) return Color_Type is
347 begin
348 return Node.Color;
349 end Color;
351 --------------
352 -- Contains --
353 --------------
355 function Contains (Container : Set; Item : Element_Type) return Boolean is
356 begin
357 return Find (Container, Item) /= No_Element;
358 end Contains;
360 ---------------
361 -- Copy_Node --
362 ---------------
364 function Copy_Node (Source : Node_Access) return Node_Access is
365 Element : Element_Access := new Element_Type'(Source.Element.all);
367 begin
368 return new Node_Type'(Parent => null,
369 Left => null,
370 Right => null,
371 Color => Source.Color,
372 Element => Element);
373 exception
374 when others =>
375 Free_Element (Element);
376 raise;
377 end Copy_Node;
379 ------------
380 -- Delete --
381 ------------
383 procedure Delete (Container : in out Set; Position : in out Cursor) is
384 begin
385 if Position.Node = null then
386 raise Constraint_Error with "Position cursor equals No_Element";
387 end if;
389 if Position.Node.Element = null then
390 raise Program_Error with "Position cursor is bad";
391 end if;
393 if Position.Container /= Container'Unrestricted_Access then
394 raise Program_Error with "Position cursor designates wrong set";
395 end if;
397 pragma Assert (Vet (Container.Tree, Position.Node),
398 "bad cursor in Delete");
400 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
401 Free (Position.Node);
402 Position.Container := null;
403 end Delete;
405 procedure Delete (Container : in out Set; Item : Element_Type) is
406 X : Node_Access :=
407 Element_Keys.Find (Container.Tree, Item);
409 begin
410 if X = null then
411 raise Constraint_Error with "attempt to delete element not in set";
412 end if;
414 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
415 Free (X);
416 end Delete;
418 ------------------
419 -- Delete_First --
420 ------------------
422 procedure Delete_First (Container : in out Set) is
423 Tree : Tree_Type renames Container.Tree;
424 X : Node_Access := Tree.First;
426 begin
427 if X /= null then
428 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
429 Free (X);
430 end if;
431 end Delete_First;
433 -----------------
434 -- Delete_Last --
435 -----------------
437 procedure Delete_Last (Container : in out Set) is
438 Tree : Tree_Type renames Container.Tree;
439 X : Node_Access := Tree.Last;
441 begin
442 if X /= null then
443 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
444 Free (X);
445 end if;
446 end Delete_Last;
448 ----------------
449 -- Difference --
450 ----------------
452 procedure Difference (Target : in out Set; Source : Set) is
453 begin
454 Set_Ops.Difference (Target.Tree, Source.Tree);
455 end Difference;
457 function Difference (Left, Right : Set) return Set is
458 Tree : constant Tree_Type :=
459 Set_Ops.Difference (Left.Tree, Right.Tree);
460 begin
461 return Set'(Controlled with Tree);
462 end Difference;
464 -------------
465 -- Element --
466 -------------
468 function Element (Position : Cursor) return Element_Type is
469 begin
470 if Position.Node = null then
471 raise Constraint_Error with "Position cursor equals No_Element";
472 end if;
474 if Position.Node.Element = null then
475 raise Program_Error with "Position cursor is bad";
476 end if;
478 pragma Assert (Vet (Position.Container.Tree, Position.Node),
479 "bad cursor in Element");
481 return Position.Node.Element.all;
482 end Element;
484 -------------------------
485 -- Equivalent_Elements --
486 -------------------------
488 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
489 begin
490 if Left < Right
491 or else Right < Left
492 then
493 return False;
494 else
495 return True;
496 end if;
497 end Equivalent_Elements;
499 ---------------------
500 -- Equivalent_Sets --
501 ---------------------
503 function Equivalent_Sets (Left, Right : Set) return Boolean is
505 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
506 pragma Inline (Is_Equivalent_Node_Node);
508 function Is_Equivalent is
509 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
511 -----------------------------
512 -- Is_Equivalent_Node_Node --
513 -----------------------------
515 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
516 begin
517 if L.Element.all < R.Element.all then
518 return False;
519 elsif R.Element.all < L.Element.all then
520 return False;
521 else
522 return True;
523 end if;
524 end Is_Equivalent_Node_Node;
526 -- Start of processing for Equivalent_Sets
528 begin
529 return Is_Equivalent (Left.Tree, Right.Tree);
530 end Equivalent_Sets;
532 -------------
533 -- Exclude --
534 -------------
536 procedure Exclude (Container : in out Set; Item : Element_Type) is
537 X : Node_Access :=
538 Element_Keys.Find (Container.Tree, Item);
540 begin
541 if X /= null then
542 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
543 Free (X);
544 end if;
545 end Exclude;
547 ----------
548 -- Find --
549 ----------
551 function Find (Container : Set; Item : Element_Type) return Cursor is
552 Node : constant Node_Access :=
553 Element_Keys.Find (Container.Tree, Item);
555 begin
556 if Node = null then
557 return No_Element;
558 end if;
560 return Cursor'(Container'Unrestricted_Access, Node);
561 end Find;
563 -----------
564 -- First --
565 -----------
567 function First (Container : Set) return Cursor is
568 begin
569 if Container.Tree.First = null then
570 return No_Element;
571 end if;
573 return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
574 end First;
576 -------------------
577 -- First_Element --
578 -------------------
580 function First_Element (Container : Set) return Element_Type is
581 begin
582 if Container.Tree.First = null then
583 raise Constraint_Error with "set is empty";
584 end if;
586 return Container.Tree.First.Element.all;
587 end First_Element;
589 -----------
590 -- Floor --
591 -----------
593 function Floor (Container : Set; Item : Element_Type) return Cursor is
594 Node : constant Node_Access :=
595 Element_Keys.Floor (Container.Tree, Item);
597 begin
598 if Node = null then
599 return No_Element;
600 end if;
602 return Cursor'(Container'Unrestricted_Access, Node);
603 end Floor;
605 ----------
606 -- Free --
607 ----------
609 procedure Free (X : in out Node_Access) is
610 procedure Deallocate is
611 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
613 begin
614 if X = null then
615 return;
616 end if;
618 X.Parent := X;
619 X.Left := X;
620 X.Right := X;
622 begin
623 Free_Element (X.Element);
624 exception
625 when others =>
626 X.Element := null;
627 Deallocate (X);
628 raise;
629 end;
631 Deallocate (X);
632 end Free;
634 ------------------
635 -- Generic_Keys --
636 ------------------
638 package body Generic_Keys is
640 -----------------------
641 -- Local Subprograms --
642 -----------------------
644 function Is_Greater_Key_Node
645 (Left : Key_Type;
646 Right : Node_Access) return Boolean;
647 pragma Inline (Is_Greater_Key_Node);
649 function Is_Less_Key_Node
650 (Left : Key_Type;
651 Right : Node_Access) return Boolean;
652 pragma Inline (Is_Less_Key_Node);
654 --------------------------
655 -- Local Instantiations --
656 --------------------------
658 package Key_Keys is
659 new Red_Black_Trees.Generic_Keys
660 (Tree_Operations => Tree_Operations,
661 Key_Type => Key_Type,
662 Is_Less_Key_Node => Is_Less_Key_Node,
663 Is_Greater_Key_Node => Is_Greater_Key_Node);
665 -------------
666 -- Ceiling --
667 -------------
669 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
670 Node : constant Node_Access :=
671 Key_Keys.Ceiling (Container.Tree, Key);
673 begin
674 if Node = null then
675 return No_Element;
676 end if;
678 return Cursor'(Container'Unrestricted_Access, Node);
679 end Ceiling;
681 --------------
682 -- Contains --
683 --------------
685 function Contains (Container : Set; Key : Key_Type) return Boolean is
686 begin
687 return Find (Container, Key) /= No_Element;
688 end Contains;
690 ------------
691 -- Delete --
692 ------------
694 procedure Delete (Container : in out Set; Key : Key_Type) is
695 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
697 begin
698 if X = null then
699 raise Constraint_Error with "attempt to delete key not in set";
700 end if;
702 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
703 Free (X);
704 end Delete;
706 -------------
707 -- Element --
708 -------------
710 function Element (Container : Set; Key : Key_Type) return Element_Type is
711 Node : constant Node_Access :=
712 Key_Keys.Find (Container.Tree, Key);
714 begin
715 if Node = null then
716 raise Constraint_Error with "key not in set";
717 end if;
719 return Node.Element.all;
720 end Element;
722 ---------------------
723 -- Equivalent_Keys --
724 ---------------------
726 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
727 begin
728 if Left < Right
729 or else Right < Left
730 then
731 return False;
732 else
733 return True;
734 end if;
735 end Equivalent_Keys;
737 -------------
738 -- Exclude --
739 -------------
741 procedure Exclude (Container : in out Set; Key : Key_Type) is
742 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
744 begin
745 if X /= null then
746 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
747 Free (X);
748 end if;
749 end Exclude;
751 ----------
752 -- Find --
753 ----------
755 function Find (Container : Set; Key : Key_Type) return Cursor is
756 Node : constant Node_Access :=
757 Key_Keys.Find (Container.Tree, Key);
759 begin
760 if Node = null then
761 return No_Element;
762 end if;
764 return Cursor'(Container'Unrestricted_Access, Node);
765 end Find;
767 -----------
768 -- Floor --
769 -----------
771 function Floor (Container : Set; Key : Key_Type) return Cursor is
772 Node : constant Node_Access :=
773 Key_Keys.Floor (Container.Tree, Key);
775 begin
776 if Node = null then
777 return No_Element;
778 end if;
780 return Cursor'(Container'Unrestricted_Access, Node);
781 end Floor;
783 -------------------------
784 -- Is_Greater_Key_Node --
785 -------------------------
787 function Is_Greater_Key_Node
788 (Left : Key_Type;
789 Right : Node_Access) return Boolean is
790 begin
791 return Key (Right.Element.all) < Left;
792 end Is_Greater_Key_Node;
794 ----------------------
795 -- Is_Less_Key_Node --
796 ----------------------
798 function Is_Less_Key_Node
799 (Left : Key_Type;
800 Right : Node_Access) return Boolean is
801 begin
802 return Left < Key (Right.Element.all);
803 end Is_Less_Key_Node;
805 ---------
806 -- Key --
807 ---------
809 function Key (Position : Cursor) return Key_Type is
810 begin
811 if Position.Node = null then
812 raise Constraint_Error with
813 "Position cursor equals No_Element";
814 end if;
816 if Position.Node.Element = null then
817 raise Program_Error with
818 "Position cursor is bad";
819 end if;
821 pragma Assert (Vet (Position.Container.Tree, Position.Node),
822 "bad cursor in Key");
824 return Key (Position.Node.Element.all);
825 end Key;
827 -------------
828 -- Replace --
829 -------------
831 procedure Replace
832 (Container : in out Set;
833 Key : Key_Type;
834 New_Item : Element_Type)
836 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
838 begin
839 if Node = null then
840 raise Constraint_Error with
841 "attempt to replace key not in set";
842 end if;
844 Replace_Element (Container.Tree, Node, New_Item);
845 end Replace;
847 -----------------------------------
848 -- Update_Element_Preserving_Key --
849 -----------------------------------
851 procedure Update_Element_Preserving_Key
852 (Container : in out Set;
853 Position : Cursor;
854 Process : not null access
855 procedure (Element : in out Element_Type))
857 Tree : Tree_Type renames Container.Tree;
859 begin
860 if Position.Node = null then
861 raise Constraint_Error with "Position cursor equals No_Element";
862 end if;
864 if Position.Node.Element = null then
865 raise Program_Error with "Position cursor is bad";
866 end if;
868 if Position.Container /= Container'Unrestricted_Access then
869 raise Program_Error with "Position cursor designates wrong set";
870 end if;
872 pragma Assert (Vet (Container.Tree, Position.Node),
873 "bad cursor in Update_Element_Preserving_Key");
875 declare
876 E : Element_Type renames Position.Node.Element.all;
877 K : constant Key_Type := Key (E);
879 B : Natural renames Tree.Busy;
880 L : Natural renames Tree.Lock;
882 begin
883 B := B + 1;
884 L := L + 1;
886 begin
887 Process (E);
888 exception
889 when others =>
890 L := L - 1;
891 B := B - 1;
892 raise;
893 end;
895 L := L - 1;
896 B := B - 1;
898 if Equivalent_Keys (K, Key (E)) then
899 return;
900 end if;
901 end;
903 declare
904 X : Node_Access := Position.Node;
905 begin
906 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
907 Free (X);
908 end;
910 raise Program_Error with "key was modified";
911 end Update_Element_Preserving_Key;
913 end Generic_Keys;
915 -----------------
916 -- Has_Element --
917 -----------------
919 function Has_Element (Position : Cursor) return Boolean is
920 begin
921 return Position /= No_Element;
922 end Has_Element;
924 -------------
925 -- Include --
926 -------------
928 procedure Include (Container : in out Set; New_Item : Element_Type) is
929 Position : Cursor;
930 Inserted : Boolean;
932 X : Element_Access;
934 begin
935 Insert (Container, New_Item, Position, Inserted);
937 if not Inserted then
938 if Container.Tree.Lock > 0 then
939 raise Program_Error with
940 "attempt to tamper with cursors (set is locked)";
941 end if;
943 X := Position.Node.Element;
944 Position.Node.Element := new Element_Type'(New_Item);
945 Free_Element (X);
946 end if;
947 end Include;
949 ------------
950 -- Insert --
951 ------------
953 procedure Insert
954 (Container : in out Set;
955 New_Item : Element_Type;
956 Position : out Cursor;
957 Inserted : out Boolean)
959 begin
960 Insert_Sans_Hint
961 (Container.Tree,
962 New_Item,
963 Position.Node,
964 Inserted);
966 Position.Container := Container'Unrestricted_Access;
967 end Insert;
969 procedure Insert (Container : in out Set; New_Item : Element_Type) is
970 Position : Cursor;
971 Inserted : Boolean;
972 begin
973 Insert (Container, New_Item, Position, Inserted);
975 if not Inserted then
976 raise Constraint_Error with
977 "attempt to insert element already in set";
978 end if;
979 end Insert;
981 ----------------------
982 -- Insert_Sans_Hint --
983 ----------------------
985 procedure Insert_Sans_Hint
986 (Tree : in out Tree_Type;
987 New_Item : Element_Type;
988 Node : out Node_Access;
989 Inserted : out Boolean)
991 function New_Node return Node_Access;
992 pragma Inline (New_Node);
994 procedure Insert_Post is
995 new Element_Keys.Generic_Insert_Post (New_Node);
997 procedure Conditional_Insert_Sans_Hint is
998 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1000 --------------
1001 -- New_Node --
1002 --------------
1004 function New_Node return Node_Access is
1005 Element : Element_Access := new Element_Type'(New_Item);
1007 begin
1008 return new Node_Type'(Parent => null,
1009 Left => null,
1010 Right => null,
1011 Color => Red_Black_Trees.Red,
1012 Element => Element);
1013 exception
1014 when others =>
1015 Free_Element (Element);
1016 raise;
1017 end New_Node;
1019 -- Start of processing for Insert_Sans_Hint
1021 begin
1022 Conditional_Insert_Sans_Hint
1023 (Tree,
1024 New_Item,
1025 Node,
1026 Inserted);
1027 end Insert_Sans_Hint;
1029 ----------------------
1030 -- Insert_With_Hint --
1031 ----------------------
1033 procedure Insert_With_Hint
1034 (Dst_Tree : in out Tree_Type;
1035 Dst_Hint : Node_Access;
1036 Src_Node : Node_Access;
1037 Dst_Node : out Node_Access)
1039 Success : Boolean;
1041 function New_Node return Node_Access;
1043 procedure Insert_Post is
1044 new Element_Keys.Generic_Insert_Post (New_Node);
1046 procedure Insert_Sans_Hint is
1047 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1049 procedure Insert_With_Hint is
1050 new Element_Keys.Generic_Conditional_Insert_With_Hint
1051 (Insert_Post,
1052 Insert_Sans_Hint);
1054 --------------
1055 -- New_Node --
1056 --------------
1058 function New_Node return Node_Access is
1059 Element : Element_Access :=
1060 new Element_Type'(Src_Node.Element.all);
1061 Node : Node_Access;
1063 begin
1064 begin
1065 Node := new Node_Type;
1066 exception
1067 when others =>
1068 Free_Element (Element);
1069 raise;
1070 end;
1072 Node.Element := Element;
1073 return Node;
1074 end New_Node;
1076 -- Start of processing for Insert_With_Hint
1078 begin
1079 Insert_With_Hint
1080 (Dst_Tree,
1081 Dst_Hint,
1082 Src_Node.Element.all,
1083 Dst_Node,
1084 Success);
1085 end Insert_With_Hint;
1087 ------------------
1088 -- Intersection --
1089 ------------------
1091 procedure Intersection (Target : in out Set; Source : Set) is
1092 begin
1093 Set_Ops.Intersection (Target.Tree, Source.Tree);
1094 end Intersection;
1096 function Intersection (Left, Right : Set) return Set is
1097 Tree : constant Tree_Type :=
1098 Set_Ops.Intersection (Left.Tree, Right.Tree);
1099 begin
1100 return Set'(Controlled with Tree);
1101 end Intersection;
1103 --------------
1104 -- Is_Empty --
1105 --------------
1107 function Is_Empty (Container : Set) return Boolean is
1108 begin
1109 return Container.Tree.Length = 0;
1110 end Is_Empty;
1112 -----------------------------
1113 -- Is_Greater_Element_Node --
1114 -----------------------------
1116 function Is_Greater_Element_Node
1117 (Left : Element_Type;
1118 Right : Node_Access) return Boolean is
1119 begin
1120 -- e > node same as node < e
1122 return Right.Element.all < Left;
1123 end Is_Greater_Element_Node;
1125 --------------------------
1126 -- Is_Less_Element_Node --
1127 --------------------------
1129 function Is_Less_Element_Node
1130 (Left : Element_Type;
1131 Right : Node_Access) return Boolean is
1132 begin
1133 return Left < Right.Element.all;
1134 end Is_Less_Element_Node;
1136 -----------------------
1137 -- Is_Less_Node_Node --
1138 -----------------------
1140 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1141 begin
1142 return L.Element.all < R.Element.all;
1143 end Is_Less_Node_Node;
1145 ---------------
1146 -- Is_Subset --
1147 ---------------
1149 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1150 begin
1151 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1152 end Is_Subset;
1154 -------------
1155 -- Iterate --
1156 -------------
1158 procedure Iterate
1159 (Container : Set;
1160 Process : not null access procedure (Position : Cursor))
1162 procedure Process_Node (Node : Node_Access);
1163 pragma Inline (Process_Node);
1165 procedure Local_Iterate is
1166 new Tree_Operations.Generic_Iteration (Process_Node);
1168 ------------------
1169 -- Process_Node --
1170 ------------------
1172 procedure Process_Node (Node : Node_Access) is
1173 begin
1174 Process (Cursor'(Container'Unrestricted_Access, Node));
1175 end Process_Node;
1177 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1178 B : Natural renames T.Busy;
1180 -- Start of prccessing for Iterate
1182 begin
1183 B := B + 1;
1185 begin
1186 Local_Iterate (T);
1187 exception
1188 when others =>
1189 B := B - 1;
1190 raise;
1191 end;
1193 B := B - 1;
1194 end Iterate;
1196 ----------
1197 -- Last --
1198 ----------
1200 function Last (Container : Set) return Cursor is
1201 begin
1202 if Container.Tree.Last = null then
1203 return No_Element;
1204 end if;
1206 return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
1207 end Last;
1209 ------------------
1210 -- Last_Element --
1211 ------------------
1213 function Last_Element (Container : Set) return Element_Type is
1214 begin
1215 if Container.Tree.Last = null then
1216 raise Constraint_Error with "set is empty";
1217 end if;
1219 return Container.Tree.Last.Element.all;
1220 end Last_Element;
1222 ----------
1223 -- Left --
1224 ----------
1226 function Left (Node : Node_Access) return Node_Access is
1227 begin
1228 return Node.Left;
1229 end Left;
1231 ------------
1232 -- Length --
1233 ------------
1235 function Length (Container : Set) return Count_Type is
1236 begin
1237 return Container.Tree.Length;
1238 end Length;
1240 ----------
1241 -- Move --
1242 ----------
1244 procedure Move is
1245 new Tree_Operations.Generic_Move (Clear);
1247 procedure Move (Target : in out Set; Source : in out Set) is
1248 begin
1249 Move (Target => Target.Tree, Source => Source.Tree);
1250 end Move;
1252 ----------
1253 -- Next --
1254 ----------
1256 procedure Next (Position : in out Cursor) is
1257 begin
1258 Position := Next (Position);
1259 end Next;
1261 function Next (Position : Cursor) return Cursor is
1262 begin
1263 if Position = No_Element then
1264 return No_Element;
1265 end if;
1267 if Position.Node.Element = null then
1268 raise Program_Error with "Position cursor is bad";
1269 end if;
1271 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1272 "bad cursor in Next");
1274 declare
1275 Node : constant Node_Access :=
1276 Tree_Operations.Next (Position.Node);
1278 begin
1279 if Node = null then
1280 return No_Element;
1281 end if;
1283 return Cursor'(Position.Container, Node);
1284 end;
1285 end Next;
1287 -------------
1288 -- Overlap --
1289 -------------
1291 function Overlap (Left, Right : Set) return Boolean is
1292 begin
1293 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1294 end Overlap;
1296 ------------
1297 -- Parent --
1298 ------------
1300 function Parent (Node : Node_Access) return Node_Access is
1301 begin
1302 return Node.Parent;
1303 end Parent;
1305 --------------
1306 -- Previous --
1307 --------------
1309 procedure Previous (Position : in out Cursor) is
1310 begin
1311 Position := Previous (Position);
1312 end Previous;
1314 function Previous (Position : Cursor) return Cursor is
1315 begin
1316 if Position = No_Element then
1317 return No_Element;
1318 end if;
1320 if Position.Node.Element = null then
1321 raise Program_Error with "Position cursor is bad";
1322 end if;
1324 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1325 "bad cursor in Previous");
1327 declare
1328 Node : constant Node_Access :=
1329 Tree_Operations.Previous (Position.Node);
1331 begin
1332 if Node = null then
1333 return No_Element;
1334 end if;
1336 return Cursor'(Position.Container, Node);
1337 end;
1338 end Previous;
1340 -------------------
1341 -- Query_Element --
1342 -------------------
1344 procedure Query_Element
1345 (Position : Cursor;
1346 Process : not null access procedure (Element : Element_Type))
1348 begin
1349 if Position.Node = null then
1350 raise Constraint_Error with "Position cursor equals No_Element";
1351 end if;
1353 if Position.Node.Element = null then
1354 raise Program_Error with "Position cursor is bad";
1355 end if;
1357 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1358 "bad cursor in Query_Element");
1360 declare
1361 T : Tree_Type renames Position.Container.Tree;
1363 B : Natural renames T.Busy;
1364 L : Natural renames T.Lock;
1366 begin
1367 B := B + 1;
1368 L := L + 1;
1370 begin
1371 Process (Position.Node.Element.all);
1372 exception
1373 when others =>
1374 L := L - 1;
1375 B := B - 1;
1376 raise;
1377 end;
1379 L := L - 1;
1380 B := B - 1;
1381 end;
1382 end Query_Element;
1384 ----------
1385 -- Read --
1386 ----------
1388 procedure Read
1389 (Stream : access Root_Stream_Type'Class;
1390 Container : out Set)
1392 function Read_Node
1393 (Stream : access Root_Stream_Type'Class) return Node_Access;
1394 pragma Inline (Read_Node);
1396 procedure Read is
1397 new Tree_Operations.Generic_Read (Clear, Read_Node);
1399 ---------------
1400 -- Read_Node --
1401 ---------------
1403 function Read_Node
1404 (Stream : access Root_Stream_Type'Class) return Node_Access
1406 Node : Node_Access := new Node_Type;
1408 begin
1409 Node.Element := new Element_Type'(Element_Type'Input (Stream));
1410 return Node;
1412 exception
1413 when others =>
1414 Free (Node); -- Note that Free deallocates elem too
1415 raise;
1416 end Read_Node;
1418 -- Start of processing for Read
1420 begin
1421 Read (Stream, Container.Tree);
1422 end Read;
1424 procedure Read
1425 (Stream : access Root_Stream_Type'Class;
1426 Item : out Cursor)
1428 begin
1429 raise Program_Error with "attempt to stream set cursor";
1430 end Read;
1432 -------------
1433 -- Replace --
1434 -------------
1436 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1437 Node : constant Node_Access :=
1438 Element_Keys.Find (Container.Tree, New_Item);
1440 X : Element_Access;
1442 begin
1443 if Node = null then
1444 raise Constraint_Error with "attempt to replace element not in set";
1445 end if;
1447 if Container.Tree.Lock > 0 then
1448 raise Program_Error with
1449 "attempt to tamper with cursors (set is locked)";
1450 end if;
1452 X := Node.Element;
1453 Node.Element := new Element_Type'(New_Item);
1454 Free_Element (X);
1455 end Replace;
1457 ---------------------
1458 -- Replace_Element --
1459 ---------------------
1461 procedure Replace_Element
1462 (Tree : in out Tree_Type;
1463 Node : Node_Access;
1464 Item : Element_Type)
1466 begin
1467 if Item < Node.Element.all
1468 or else Node.Element.all < Item
1469 then
1470 null;
1471 else
1472 if Tree.Lock > 0 then
1473 raise Program_Error with
1474 "attempt to tamper with cursors (set is locked)";
1475 end if;
1477 declare
1478 X : Element_Access := Node.Element;
1479 begin
1480 Node.Element := new Element_Type'(Item);
1481 Free_Element (X);
1482 end;
1484 return;
1485 end if;
1487 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1489 Insert_New_Item : declare
1490 function New_Node return Node_Access;
1491 pragma Inline (New_Node);
1493 procedure Insert_Post is
1494 new Element_Keys.Generic_Insert_Post (New_Node);
1496 procedure Insert is
1497 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1499 --------------
1500 -- New_Node --
1501 --------------
1503 function New_Node return Node_Access is
1504 begin
1505 Node.Element := new Element_Type'(Item); -- OK if fails
1506 Node.Color := Red;
1507 Node.Parent := null;
1508 Node.Right := null;
1509 Node.Left := null;
1511 return Node;
1512 end New_Node;
1514 Result : Node_Access;
1515 Inserted : Boolean;
1517 X : Element_Access := Node.Element;
1519 -- Start of processing for Insert_New_Item
1521 begin
1522 Attempt_Insert : begin
1523 Insert
1524 (Tree => Tree,
1525 Key => Item,
1526 Node => Result,
1527 Success => Inserted); -- TODO: change name of formal param
1528 exception
1529 when others =>
1530 Inserted := False;
1531 end Attempt_Insert;
1533 if Inserted then
1534 pragma Assert (Result = Node);
1535 Free_Element (X); -- OK if fails
1536 return;
1537 end if;
1538 end Insert_New_Item;
1540 Reinsert_Old_Element : declare
1541 function New_Node return Node_Access;
1542 pragma Inline (New_Node);
1544 procedure Insert_Post is
1545 new Element_Keys.Generic_Insert_Post (New_Node);
1547 procedure Insert is
1548 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1550 --------------
1551 -- New_Node --
1552 --------------
1554 function New_Node return Node_Access is
1555 begin
1556 Node.Color := Red;
1557 Node.Parent := null;
1558 Node.Right := null;
1559 Node.Left := null;
1561 return Node;
1562 end New_Node;
1564 Result : Node_Access;
1565 Inserted : Boolean;
1567 -- Start of processing for Reinsert_Old_Element
1569 begin
1570 Insert
1571 (Tree => Tree,
1572 Key => Node.Element.all,
1573 Node => Result,
1574 Success => Inserted); -- TODO: change name of formal param
1575 exception
1576 when others =>
1577 null;
1578 end Reinsert_Old_Element;
1580 raise Program_Error with "attempt to replace existing element";
1581 end Replace_Element;
1583 procedure Replace_Element
1584 (Container : in out Set;
1585 Position : Cursor;
1586 New_Item : Element_Type)
1588 begin
1589 if Position.Node = null then
1590 raise Constraint_Error with "Position cursor equals No_Element";
1591 end if;
1593 if Position.Node.Element = null then
1594 raise Program_Error with "Position cursor is bad";
1595 end if;
1597 if Position.Container /= Container'Unrestricted_Access then
1598 raise Program_Error with "Position cursor designates wrong set";
1599 end if;
1601 pragma Assert (Vet (Container.Tree, Position.Node),
1602 "bad cursor in Replace_Element");
1604 Replace_Element (Container.Tree, Position.Node, New_Item);
1605 end Replace_Element;
1607 ---------------------
1608 -- Reverse_Iterate --
1609 ---------------------
1611 procedure Reverse_Iterate
1612 (Container : Set;
1613 Process : not null access procedure (Position : Cursor))
1615 procedure Process_Node (Node : Node_Access);
1616 pragma Inline (Process_Node);
1618 procedure Local_Reverse_Iterate is
1619 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1621 ------------------
1622 -- Process_Node --
1623 ------------------
1625 procedure Process_Node (Node : Node_Access) is
1626 begin
1627 Process (Cursor'(Container'Unrestricted_Access, Node));
1628 end Process_Node;
1630 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1631 B : Natural renames T.Busy;
1633 -- Start of processing for Reverse_Iterate
1635 begin
1636 B := B + 1;
1638 begin
1639 Local_Reverse_Iterate (T);
1640 exception
1641 when others =>
1642 B := B - 1;
1643 raise;
1644 end;
1646 B := B - 1;
1647 end Reverse_Iterate;
1649 -----------
1650 -- Right --
1651 -----------
1653 function Right (Node : Node_Access) return Node_Access is
1654 begin
1655 return Node.Right;
1656 end Right;
1658 ---------------
1659 -- Set_Color --
1660 ---------------
1662 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1663 begin
1664 Node.Color := Color;
1665 end Set_Color;
1667 --------------
1668 -- Set_Left --
1669 --------------
1671 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1672 begin
1673 Node.Left := Left;
1674 end Set_Left;
1676 ----------------
1677 -- Set_Parent --
1678 ----------------
1680 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1681 begin
1682 Node.Parent := Parent;
1683 end Set_Parent;
1685 ---------------
1686 -- Set_Right --
1687 ---------------
1689 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1690 begin
1691 Node.Right := Right;
1692 end Set_Right;
1694 --------------------------
1695 -- Symmetric_Difference --
1696 --------------------------
1698 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1699 begin
1700 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1701 end Symmetric_Difference;
1703 function Symmetric_Difference (Left, Right : Set) return Set is
1704 Tree : constant Tree_Type :=
1705 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1706 begin
1707 return Set'(Controlled with Tree);
1708 end Symmetric_Difference;
1710 ------------
1711 -- To_Set --
1712 ------------
1714 function To_Set (New_Item : Element_Type) return Set is
1715 Tree : Tree_Type;
1716 Node : Node_Access;
1717 Inserted : Boolean;
1719 begin
1720 Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
1721 return Set'(Controlled with Tree);
1722 end To_Set;
1724 -----------
1725 -- Union --
1726 -----------
1728 procedure Union (Target : in out Set; Source : Set) is
1729 begin
1730 Set_Ops.Union (Target.Tree, Source.Tree);
1731 end Union;
1733 function Union (Left, Right : Set) return Set is
1734 Tree : constant Tree_Type :=
1735 Set_Ops.Union (Left.Tree, Right.Tree);
1736 begin
1737 return Set'(Controlled with Tree);
1738 end Union;
1740 -----------
1741 -- Write --
1742 -----------
1744 procedure Write
1745 (Stream : access Root_Stream_Type'Class;
1746 Container : Set)
1748 procedure Write_Node
1749 (Stream : access Root_Stream_Type'Class;
1750 Node : Node_Access);
1751 pragma Inline (Write_Node);
1753 procedure Write is
1754 new Tree_Operations.Generic_Write (Write_Node);
1756 ----------------
1757 -- Write_Node --
1758 ----------------
1760 procedure Write_Node
1761 (Stream : access Root_Stream_Type'Class;
1762 Node : Node_Access)
1764 begin
1765 Element_Type'Output (Stream, Node.Element.all);
1766 end Write_Node;
1768 -- Start of processing for Write
1770 begin
1771 Write (Stream, Container.Tree);
1772 end Write;
1774 procedure Write
1775 (Stream : access Root_Stream_Type'Class;
1776 Item : Cursor)
1778 begin
1779 raise Program_Error with "attempt to stream set cursor";
1780 end Write;
1782 end Ada.Containers.Indefinite_Ordered_Sets;