1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- ADA.CONTAINERS.INDEFINITE_ORDERED_SETS --
9 -- Copyright (C) 2004-2011, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- This unit was originally developed by Matthew J Heaney. --
28 ------------------------------------------------------------------------------
30 with Ada.Containers.Red_Black_Trees.Generic_Operations;
31 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
33 with Ada.Containers.Red_Black_Trees.Generic_Keys;
34 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
36 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
37 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
39 with Ada.Unchecked_Deallocation;
41 package body Ada.Containers.Indefinite_Ordered_Sets is
44 Ordered_Set_Iterator_Interfaces.Reversible_Iterator with record
45 Container : access constant Set;
49 overriding function First (Object : Iterator) return Cursor;
51 overriding function Last (Object : Iterator) return Cursor;
53 overriding function Next
55 Position : Cursor) return Cursor;
57 overriding function Previous
59 Position : Cursor) return Cursor;
61 -----------------------
62 -- Local Subprograms --
63 -----------------------
65 function Color (Node : Node_Access) return Color_Type;
66 pragma Inline (Color);
68 function Copy_Node (Source : Node_Access) return Node_Access;
69 pragma Inline (Copy_Node);
71 procedure Free (X : in out Node_Access);
73 procedure Insert_Sans_Hint
74 (Tree : in out Tree_Type;
75 New_Item : Element_Type;
76 Node : out Node_Access;
77 Inserted : out Boolean);
79 procedure Insert_With_Hint
80 (Dst_Tree : in out Tree_Type;
81 Dst_Hint : Node_Access;
82 Src_Node : Node_Access;
83 Dst_Node : out Node_Access);
85 function Is_Greater_Element_Node
87 Right : Node_Access) return Boolean;
88 pragma Inline (Is_Greater_Element_Node);
90 function Is_Less_Element_Node
92 Right : Node_Access) return Boolean;
93 pragma Inline (Is_Less_Element_Node);
95 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
96 pragma Inline (Is_Less_Node_Node);
98 function Left (Node : Node_Access) return Node_Access;
101 function Parent (Node : Node_Access) return Node_Access;
102 pragma Inline (Parent);
104 procedure Replace_Element
105 (Tree : in out Tree_Type;
107 Item : Element_Type);
109 function Right (Node : Node_Access) return Node_Access;
110 pragma Inline (Right);
112 procedure Set_Color (Node : Node_Access; Color : Color_Type);
113 pragma Inline (Set_Color);
115 procedure Set_Left (Node : Node_Access; Left : Node_Access);
116 pragma Inline (Set_Left);
118 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
119 pragma Inline (Set_Parent);
121 procedure Set_Right (Node : Node_Access; Right : Node_Access);
122 pragma Inline (Set_Right);
124 --------------------------
125 -- Local Instantiations --
126 --------------------------
128 procedure Free_Element is
129 new Ada.Unchecked_Deallocation (Element_Type, Element_Access);
131 package Tree_Operations is
132 new Red_Black_Trees.Generic_Operations (Tree_Types);
134 procedure Delete_Tree is
135 new Tree_Operations.Generic_Delete_Tree (Free);
137 function Copy_Tree is
138 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
142 package Element_Keys is
143 new Red_Black_Trees.Generic_Keys
144 (Tree_Operations => Tree_Operations,
145 Key_Type => Element_Type,
146 Is_Less_Key_Node => Is_Less_Element_Node,
147 Is_Greater_Key_Node => Is_Greater_Element_Node);
150 new Generic_Set_Operations
151 (Tree_Operations => Tree_Operations,
152 Insert_With_Hint => Insert_With_Hint,
153 Copy_Tree => Copy_Tree,
154 Delete_Tree => Delete_Tree,
155 Is_Less => Is_Less_Node_Node,
162 function "<" (Left, Right : Cursor) return Boolean is
164 if Left.Node = null then
165 raise Constraint_Error with "Left cursor equals No_Element";
168 if Right.Node = null then
169 raise Constraint_Error with "Right cursor equals No_Element";
172 if Left.Node.Element = null then
173 raise Program_Error with "Left cursor is bad";
176 if Right.Node.Element = null then
177 raise Program_Error with "Right cursor is bad";
180 pragma Assert (Vet (Left.Container.Tree, Left.Node),
181 "bad Left cursor in ""<""");
183 pragma Assert (Vet (Right.Container.Tree, Right.Node),
184 "bad Right cursor in ""<""");
186 return Left.Node.Element.all < Right.Node.Element.all;
189 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
191 if Left.Node = null then
192 raise Constraint_Error with "Left cursor equals No_Element";
195 if Left.Node.Element = null then
196 raise Program_Error with "Left cursor is bad";
199 pragma Assert (Vet (Left.Container.Tree, Left.Node),
200 "bad Left cursor in ""<""");
202 return Left.Node.Element.all < Right;
205 function "<" (Left : Element_Type; Right : Cursor) return Boolean is
207 if Right.Node = null then
208 raise Constraint_Error with "Right cursor equals No_Element";
211 if Right.Node.Element = null then
212 raise Program_Error with "Right cursor is bad";
215 pragma Assert (Vet (Right.Container.Tree, Right.Node),
216 "bad Right cursor in ""<""");
218 return Left < Right.Node.Element.all;
225 function "=" (Left, Right : Set) return Boolean is
227 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
228 pragma Inline (Is_Equal_Node_Node);
231 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
233 ------------------------
234 -- Is_Equal_Node_Node --
235 ------------------------
237 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
239 return L.Element.all = R.Element.all;
240 end Is_Equal_Node_Node;
242 -- Start of processing for "="
245 return Is_Equal (Left.Tree, Right.Tree);
252 function ">" (Left, Right : Cursor) return Boolean is
254 if Left.Node = null then
255 raise Constraint_Error with "Left cursor equals No_Element";
258 if Right.Node = null then
259 raise Constraint_Error with "Right cursor equals No_Element";
262 if Left.Node.Element = null then
263 raise Program_Error with "Left cursor is bad";
266 if Right.Node.Element = null then
267 raise Program_Error with "Right cursor is bad";
270 pragma Assert (Vet (Left.Container.Tree, Left.Node),
271 "bad Left cursor in "">""");
273 pragma Assert (Vet (Right.Container.Tree, Right.Node),
274 "bad Right cursor in "">""");
276 -- L > R same as R < L
278 return Right.Node.Element.all < Left.Node.Element.all;
281 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
283 if Left.Node = null then
284 raise Constraint_Error with "Left cursor equals No_Element";
287 if Left.Node.Element = null then
288 raise Program_Error with "Left cursor is bad";
291 pragma Assert (Vet (Left.Container.Tree, Left.Node),
292 "bad Left cursor in "">""");
294 return Right < Left.Node.Element.all;
297 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
299 if Right.Node = null then
300 raise Constraint_Error with "Right cursor equals No_Element";
303 if Right.Node.Element = null then
304 raise Program_Error with "Right cursor is bad";
307 pragma Assert (Vet (Right.Container.Tree, Right.Node),
308 "bad Right cursor in "">""");
310 return Right.Node.Element.all < Left;
318 new Tree_Operations.Generic_Adjust (Copy_Tree);
320 procedure Adjust (Container : in out Set) is
322 Adjust (Container.Tree);
329 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
330 Node : constant Node_Access :=
331 Element_Keys.Ceiling (Container.Tree, Item);
338 return Cursor'(Container'Unrestricted_Access, Node);
346 new Tree_Operations.Generic_Clear (Delete_Tree);
348 procedure Clear (Container : in out Set) is
350 Clear (Container.Tree);
357 function Color (Node : Node_Access) return Color_Type is
366 function Contains (Container : Set; Item : Element_Type) return Boolean is
368 return Find (Container, Item) /= No_Element;
375 function Copy_Node (Source : Node_Access) return Node_Access is
376 Element : Element_Access := new Element_Type'(Source.Element.all);
379 return new Node_Type'(Parent => null,
382 Color => Source.Color,
386 Free_Element (Element);
394 procedure Delete (Container : in out Set; Position : in out Cursor) is
396 if Position.Node = null then
397 raise Constraint_Error with "Position cursor equals No_Element";
400 if Position.Node.Element = null then
401 raise Program_Error with "Position cursor is bad";
404 if Position.Container /= Container'Unrestricted_Access then
405 raise Program_Error with "Position cursor designates wrong set";
408 pragma Assert (Vet (Container.Tree, Position.Node),
409 "bad cursor in Delete");
411 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
412 Free (Position.Node);
413 Position.Container := null;
416 procedure Delete (Container : in out Set; Item : Element_Type) is
418 Element_Keys.Find (Container.Tree, Item);
422 raise Constraint_Error with "attempt to delete element not in set";
425 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
433 procedure Delete_First (Container : in out Set) is
434 Tree : Tree_Type renames Container.Tree;
435 X : Node_Access := Tree.First;
439 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
448 procedure Delete_Last (Container : in out Set) is
449 Tree : Tree_Type renames Container.Tree;
450 X : Node_Access := Tree.Last;
454 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
463 procedure Difference (Target : in out Set; Source : Set) is
465 Set_Ops.Difference (Target.Tree, Source.Tree);
468 function Difference (Left, Right : Set) return Set is
469 Tree : constant Tree_Type :=
470 Set_Ops.Difference (Left.Tree, Right.Tree);
472 return Set'(Controlled with Tree);
479 function Element (Position : Cursor) return Element_Type is
481 if Position.Node = null then
482 raise Constraint_Error with "Position cursor equals No_Element";
485 if Position.Node.Element = null then
486 raise Program_Error with "Position cursor is bad";
489 pragma Assert (Vet (Position.Container.Tree, Position.Node),
490 "bad cursor in Element");
492 return Position.Node.Element.all;
495 -------------------------
496 -- Equivalent_Elements --
497 -------------------------
499 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
508 end Equivalent_Elements;
510 ---------------------
511 -- Equivalent_Sets --
512 ---------------------
514 function Equivalent_Sets (Left, Right : Set) return Boolean is
516 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
517 pragma Inline (Is_Equivalent_Node_Node);
519 function Is_Equivalent is
520 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
522 -----------------------------
523 -- Is_Equivalent_Node_Node --
524 -----------------------------
526 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
528 if L.Element.all < R.Element.all then
530 elsif R.Element.all < L.Element.all then
535 end Is_Equivalent_Node_Node;
537 -- Start of processing for Equivalent_Sets
540 return Is_Equivalent (Left.Tree, Right.Tree);
547 procedure Exclude (Container : in out Set; Item : Element_Type) is
549 Element_Keys.Find (Container.Tree, Item);
553 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
562 function Find (Container : Set; Item : Element_Type) return Cursor is
563 Node : constant Node_Access :=
564 Element_Keys.Find (Container.Tree, Item);
571 return Cursor'(Container'Unrestricted_Access, Node);
578 function First (Container : Set) return Cursor is
580 if Container.Tree.First = null then
584 return Cursor'(Container'Unrestricted_Access, Container.Tree.First);
587 function First (Object : Iterator) return Cursor is
590 Object.Container.all'Unrestricted_Access, Object.Container.Tree.First);
597 function First_Element (Container : Set) return Element_Type is
599 if Container.Tree.First = null then
600 raise Constraint_Error with "set is empty";
602 return Container.Tree.First.Element.all;
610 function Floor (Container : Set; Item : Element_Type) return Cursor is
611 Node : constant Node_Access :=
612 Element_Keys.Floor (Container.Tree, Item);
617 return Cursor'(Container'Unrestricted_Access, Node);
625 procedure Free (X : in out Node_Access) is
626 procedure Deallocate is
627 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
639 Free_Element (X.Element);
654 package body Generic_Keys is
656 -----------------------
657 -- Local Subprograms --
658 -----------------------
660 function Is_Greater_Key_Node
662 Right : Node_Access) return Boolean;
663 pragma Inline (Is_Greater_Key_Node);
665 function Is_Less_Key_Node
667 Right : Node_Access) return Boolean;
668 pragma Inline (Is_Less_Key_Node);
670 --------------------------
671 -- Local Instantiations --
672 --------------------------
675 new Red_Black_Trees.Generic_Keys
676 (Tree_Operations => Tree_Operations,
677 Key_Type => Key_Type,
678 Is_Less_Key_Node => Is_Less_Key_Node,
679 Is_Greater_Key_Node => Is_Greater_Key_Node);
685 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
686 Node : constant Node_Access :=
687 Key_Keys.Ceiling (Container.Tree, Key);
694 return Cursor'(Container'Unrestricted_Access, Node);
701 function Contains (Container : Set; Key : Key_Type) return Boolean is
703 return Find (Container, Key) /= No_Element;
710 procedure Delete (Container : in out Set; Key : Key_Type) is
711 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
715 raise Constraint_Error with "attempt to delete key not in set";
718 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
726 function Element (Container : Set; Key : Key_Type) return Element_Type is
727 Node : constant Node_Access :=
728 Key_Keys.Find (Container.Tree, Key);
732 raise Constraint_Error with "key not in set";
735 return Node.Element.all;
738 ---------------------
739 -- Equivalent_Keys --
740 ---------------------
742 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
757 procedure Exclude (Container : in out Set; Key : Key_Type) is
758 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
762 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
771 function Find (Container : Set; Key : Key_Type) return Cursor is
772 Node : constant Node_Access :=
773 Key_Keys.Find (Container.Tree, Key);
780 return Cursor'(Container'Unrestricted_Access, Node);
787 function Floor (Container : Set; Key : Key_Type) return Cursor is
788 Node : constant Node_Access :=
789 Key_Keys.Floor (Container.Tree, Key);
796 return Cursor'(Container'Unrestricted_Access, Node);
799 -------------------------
800 -- Is_Greater_Key_Node --
801 -------------------------
803 function Is_Greater_Key_Node
805 Right : Node_Access) return Boolean is
807 return Key (Right.Element.all) < Left;
808 end Is_Greater_Key_Node;
810 ----------------------
811 -- Is_Less_Key_Node --
812 ----------------------
814 function Is_Less_Key_Node
816 Right : Node_Access) return Boolean is
818 return Left < Key (Right.Element.all);
819 end Is_Less_Key_Node;
825 function Key (Position : Cursor) return Key_Type is
827 if Position.Node = null then
828 raise Constraint_Error with
829 "Position cursor equals No_Element";
832 if Position.Node.Element = null then
833 raise Program_Error with
834 "Position cursor is bad";
837 pragma Assert (Vet (Position.Container.Tree, Position.Node),
838 "bad cursor in Key");
840 return Key (Position.Node.Element.all);
848 (Container : in out Set;
850 New_Item : Element_Type)
852 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
856 raise Constraint_Error with
857 "attempt to replace key not in set";
860 Replace_Element (Container.Tree, Node, New_Item);
863 -----------------------------------
864 -- Update_Element_Preserving_Key --
865 -----------------------------------
867 procedure Update_Element_Preserving_Key
868 (Container : in out Set;
870 Process : not null access
871 procedure (Element : in out Element_Type))
873 Tree : Tree_Type renames Container.Tree;
876 if Position.Node = null then
877 raise Constraint_Error with "Position cursor equals No_Element";
880 if Position.Node.Element = null then
881 raise Program_Error with "Position cursor is bad";
884 if Position.Container /= Container'Unrestricted_Access then
885 raise Program_Error with "Position cursor designates wrong set";
888 pragma Assert (Vet (Container.Tree, Position.Node),
889 "bad cursor in Update_Element_Preserving_Key");
892 E : Element_Type renames Position.Node.Element.all;
893 K : constant Key_Type := Key (E);
895 B : Natural renames Tree.Busy;
896 L : Natural renames Tree.Lock;
914 if Equivalent_Keys (K, Key (E)) then
920 X : Node_Access := Position.Node;
922 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
926 raise Program_Error with "key was modified";
927 end Update_Element_Preserving_Key;
935 function Has_Element (Position : Cursor) return Boolean is
937 return Position /= No_Element;
944 procedure Include (Container : in out Set; New_Item : Element_Type) is
951 Insert (Container, New_Item, Position, Inserted);
954 if Container.Tree.Lock > 0 then
955 raise Program_Error with
956 "attempt to tamper with elements (set is locked)";
959 X := Position.Node.Element;
960 Position.Node.Element := new Element_Type'(New_Item);
970 (Container : in out Set;
971 New_Item : Element_Type;
972 Position : out Cursor;
973 Inserted : out Boolean)
982 Position.Container := Container'Unrestricted_Access;
985 procedure Insert (Container : in out Set; New_Item : Element_Type) is
987 pragma Unreferenced (Position);
992 Insert (Container, New_Item, Position, Inserted);
995 raise Constraint_Error with
996 "attempt to insert element already in set";
1000 ----------------------
1001 -- Insert_Sans_Hint --
1002 ----------------------
1004 procedure Insert_Sans_Hint
1005 (Tree : in out Tree_Type;
1006 New_Item : Element_Type;
1007 Node : out Node_Access;
1008 Inserted : out Boolean)
1010 function New_Node return Node_Access;
1011 pragma Inline (New_Node);
1013 procedure Insert_Post is
1014 new Element_Keys.Generic_Insert_Post (New_Node);
1016 procedure Conditional_Insert_Sans_Hint is
1017 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1023 function New_Node return Node_Access is
1024 Element : Element_Access := new Element_Type'(New_Item);
1027 return new Node_Type'(Parent => null,
1030 Color => Red_Black_Trees.Red,
1031 Element => Element);
1034 Free_Element (Element);
1038 -- Start of processing for Insert_Sans_Hint
1041 Conditional_Insert_Sans_Hint
1046 end Insert_Sans_Hint;
1048 ----------------------
1049 -- Insert_With_Hint --
1050 ----------------------
1052 procedure Insert_With_Hint
1053 (Dst_Tree : in out Tree_Type;
1054 Dst_Hint : Node_Access;
1055 Src_Node : Node_Access;
1056 Dst_Node : out Node_Access)
1059 pragma Unreferenced (Success);
1061 function New_Node return Node_Access;
1063 procedure Insert_Post is
1064 new Element_Keys.Generic_Insert_Post (New_Node);
1066 procedure Insert_Sans_Hint is
1067 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1069 procedure Insert_With_Hint is
1070 new Element_Keys.Generic_Conditional_Insert_With_Hint
1078 function New_Node return Node_Access is
1079 Element : Element_Access :=
1080 new Element_Type'(Src_Node.Element.all);
1085 Node := new Node_Type;
1088 Free_Element (Element);
1092 Node.Element := Element;
1096 -- Start of processing for Insert_With_Hint
1102 Src_Node.Element.all,
1105 end Insert_With_Hint;
1111 procedure Intersection (Target : in out Set; Source : Set) is
1113 Set_Ops.Intersection (Target.Tree, Source.Tree);
1116 function Intersection (Left, Right : Set) return Set is
1117 Tree : constant Tree_Type :=
1118 Set_Ops.Intersection (Left.Tree, Right.Tree);
1120 return Set'(Controlled with Tree);
1127 function Is_Empty (Container : Set) return Boolean is
1129 return Container.Tree.Length = 0;
1132 -----------------------------
1133 -- Is_Greater_Element_Node --
1134 -----------------------------
1136 function Is_Greater_Element_Node
1137 (Left : Element_Type;
1138 Right : Node_Access) return Boolean is
1140 -- e > node same as node < e
1142 return Right.Element.all < Left;
1143 end Is_Greater_Element_Node;
1145 --------------------------
1146 -- Is_Less_Element_Node --
1147 --------------------------
1149 function Is_Less_Element_Node
1150 (Left : Element_Type;
1151 Right : Node_Access) return Boolean is
1153 return Left < Right.Element.all;
1154 end Is_Less_Element_Node;
1156 -----------------------
1157 -- Is_Less_Node_Node --
1158 -----------------------
1160 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1162 return L.Element.all < R.Element.all;
1163 end Is_Less_Node_Node;
1169 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1171 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1180 Process : not null access procedure (Position : Cursor))
1182 procedure Process_Node (Node : Node_Access);
1183 pragma Inline (Process_Node);
1185 procedure Local_Iterate is
1186 new Tree_Operations.Generic_Iteration (Process_Node);
1192 procedure Process_Node (Node : Node_Access) is
1194 Process (Cursor'(Container'Unrestricted_Access, Node));
1197 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1198 B : Natural renames T.Busy;
1200 -- Start of processing for Iterate
1218 return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
1220 It : constant Iterator :=
1221 (Container'Unchecked_Access, Container.Tree.First);
1229 return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
1231 It : constant Iterator := (Container'Unchecked_Access, Start.Node);
1240 function Last (Container : Set) return Cursor is
1242 if Container.Tree.Last = null then
1245 return Cursor'(Container'Unrestricted_Access, Container.Tree.Last);
1249 function Last (Object : Iterator) return Cursor is
1251 if Object.Container.Tree.Last = null then
1255 Object.Container.all'Unrestricted_Access,
1256 Object.Container.Tree.Last);
1264 function Last_Element (Container : Set) return Element_Type is
1266 if Container.Tree.Last = null then
1267 raise Constraint_Error with "set is empty";
1269 return Container.Tree.Last.Element.all;
1277 function Left (Node : Node_Access) return Node_Access is
1286 function Length (Container : Set) return Count_Type is
1288 return Container.Tree.Length;
1296 new Tree_Operations.Generic_Move (Clear);
1298 procedure Move (Target : in out Set; Source : in out Set) is
1300 Move (Target => Target.Tree, Source => Source.Tree);
1307 procedure Next (Position : in out Cursor) is
1309 Position := Next (Position);
1312 function Next (Position : Cursor) return Cursor is
1314 if Position = No_Element then
1318 if Position.Node.Element = null then
1319 raise Program_Error with "Position cursor is bad";
1322 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1323 "bad cursor in Next");
1326 Node : constant Node_Access :=
1327 Tree_Operations.Next (Position.Node);
1334 return Cursor'(Position.Container, Node);
1340 Position : Cursor) return Cursor
1342 pragma Unreferenced (Object);
1344 return Next (Position);
1351 function Overlap (Left, Right : Set) return Boolean is
1353 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1360 function Parent (Node : Node_Access) return Node_Access is
1369 procedure Previous (Position : in out Cursor) is
1371 Position := Previous (Position);
1374 function Previous (Position : Cursor) return Cursor is
1376 if Position = No_Element then
1380 if Position.Node.Element = null then
1381 raise Program_Error with "Position cursor is bad";
1384 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1385 "bad cursor in Previous");
1388 Node : constant Node_Access :=
1389 Tree_Operations.Previous (Position.Node);
1396 return Cursor'(Position.Container, Node);
1402 Position : Cursor) return Cursor
1404 pragma Unreferenced (Object);
1406 return Previous (Position);
1413 procedure Query_Element
1415 Process : not null access procedure (Element : Element_Type))
1418 if Position.Node = null then
1419 raise Constraint_Error with "Position cursor equals No_Element";
1422 if Position.Node.Element = null then
1423 raise Program_Error with "Position cursor is bad";
1426 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1427 "bad cursor in Query_Element");
1430 T : Tree_Type renames Position.Container.Tree;
1432 B : Natural renames T.Busy;
1433 L : Natural renames T.Lock;
1440 Process (Position.Node.Element.all);
1458 (Stream : not null access Root_Stream_Type'Class;
1459 Container : out Set)
1462 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1463 pragma Inline (Read_Node);
1466 new Tree_Operations.Generic_Read (Clear, Read_Node);
1473 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1475 Node : Node_Access := new Node_Type;
1478 Node.Element := new Element_Type'(Element_Type'Input (Stream));
1483 Free (Node); -- Note that Free deallocates elem too
1487 -- Start of processing for Read
1490 Read (Stream, Container.Tree);
1494 (Stream : not null access Root_Stream_Type'Class;
1498 raise Program_Error with "attempt to stream set cursor";
1502 (Stream : not null access Root_Stream_Type'Class;
1503 Item : out Reference_Type)
1506 raise Program_Error with "attempt to stream reference";
1510 (Stream : not null access Root_Stream_Type'Class;
1511 Item : out Constant_Reference_Type)
1514 raise Program_Error with "attempt to stream reference";
1521 function Constant_Reference (Container : Set; Position : Cursor)
1522 return Constant_Reference_Type
1524 pragma Unreferenced (Container);
1526 if Position.Container = null then
1527 raise Constraint_Error with "Position cursor has no element";
1530 return (Element => Position.Node.Element.all'Access);
1531 end Constant_Reference;
1533 function Reference (Container : Set; Position : Cursor)
1534 return Reference_Type
1536 pragma Unreferenced (Container);
1538 if Position.Container = null then
1539 raise Constraint_Error with "Position cursor has no element";
1542 return (Element => Position.Node.Element.all'Access);
1549 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1550 Node : constant Node_Access :=
1551 Element_Keys.Find (Container.Tree, New_Item);
1554 pragma Warnings (Off, X);
1558 raise Constraint_Error with "attempt to replace element not in set";
1561 if Container.Tree.Lock > 0 then
1562 raise Program_Error with
1563 "attempt to tamper with elements (set is locked)";
1567 Node.Element := new Element_Type'(New_Item);
1571 ---------------------
1572 -- Replace_Element --
1573 ---------------------
1575 procedure Replace_Element
1576 (Tree : in out Tree_Type;
1578 Item : Element_Type)
1580 pragma Assert (Node /= null);
1581 pragma Assert (Node.Element /= null);
1583 function New_Node return Node_Access;
1584 pragma Inline (New_Node);
1586 procedure Local_Insert_Post is
1587 new Element_Keys.Generic_Insert_Post (New_Node);
1589 procedure Local_Insert_Sans_Hint is
1590 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1592 procedure Local_Insert_With_Hint is
1593 new Element_Keys.Generic_Conditional_Insert_With_Hint
1595 Local_Insert_Sans_Hint);
1601 function New_Node return Node_Access is
1603 Node.Element := new Element_Type'(Item); -- OK if fails
1605 Node.Parent := null;
1613 Result : Node_Access;
1616 X : Element_Access := Node.Element;
1618 -- Start of processing for Replace_Element
1621 if Item < Node.Element.all
1622 or else Node.Element.all < Item
1627 if Tree.Lock > 0 then
1628 raise Program_Error with
1629 "attempt to tamper with elements (set is locked)";
1632 Node.Element := new Element_Type'(Item);
1638 Hint := Element_Keys.Ceiling (Tree, Item);
1643 elsif Item < Hint.Element.all then
1645 if Tree.Lock > 0 then
1646 raise Program_Error with
1647 "attempt to tamper with elements (set is locked)";
1650 Node.Element := new Element_Type'(Item);
1657 pragma Assert (not (Hint.Element.all < Item));
1658 raise Program_Error with "attempt to replace existing element";
1661 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1663 Local_Insert_With_Hint
1668 Inserted => Inserted);
1670 pragma Assert (Inserted);
1671 pragma Assert (Result = Node);
1674 end Replace_Element;
1676 procedure Replace_Element
1677 (Container : in out Set;
1679 New_Item : Element_Type)
1682 if Position.Node = null then
1683 raise Constraint_Error with "Position cursor equals No_Element";
1686 if Position.Node.Element = null then
1687 raise Program_Error with "Position cursor is bad";
1690 if Position.Container /= Container'Unrestricted_Access then
1691 raise Program_Error with "Position cursor designates wrong set";
1694 pragma Assert (Vet (Container.Tree, Position.Node),
1695 "bad cursor in Replace_Element");
1697 Replace_Element (Container.Tree, Position.Node, New_Item);
1698 end Replace_Element;
1700 ---------------------
1701 -- Reverse_Iterate --
1702 ---------------------
1704 procedure Reverse_Iterate
1706 Process : not null access procedure (Position : Cursor))
1708 procedure Process_Node (Node : Node_Access);
1709 pragma Inline (Process_Node);
1711 procedure Local_Reverse_Iterate is
1712 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1718 procedure Process_Node (Node : Node_Access) is
1720 Process (Cursor'(Container'Unrestricted_Access, Node));
1723 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1724 B : Natural renames T.Busy;
1726 -- Start of processing for Reverse_Iterate
1732 Local_Reverse_Iterate (T);
1740 end Reverse_Iterate;
1746 function Right (Node : Node_Access) return Node_Access is
1755 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1757 Node.Color := Color;
1764 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1773 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1775 Node.Parent := Parent;
1782 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1784 Node.Right := Right;
1787 --------------------------
1788 -- Symmetric_Difference --
1789 --------------------------
1791 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1793 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1794 end Symmetric_Difference;
1796 function Symmetric_Difference (Left, Right : Set) return Set is
1797 Tree : constant Tree_Type :=
1798 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1800 return Set'(Controlled with Tree);
1801 end Symmetric_Difference;
1807 function To_Set (New_Item : Element_Type) return Set is
1812 pragma Unreferenced (Node, Inserted);
1815 Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
1816 return Set'(Controlled with Tree);
1823 procedure Union (Target : in out Set; Source : Set) is
1825 Set_Ops.Union (Target.Tree, Source.Tree);
1828 function Union (Left, Right : Set) return Set is
1829 Tree : constant Tree_Type :=
1830 Set_Ops.Union (Left.Tree, Right.Tree);
1832 return Set'(Controlled with Tree);
1840 (Stream : not null access Root_Stream_Type'Class;
1843 procedure Write_Node
1844 (Stream : not null access Root_Stream_Type'Class;
1845 Node : Node_Access);
1846 pragma Inline (Write_Node);
1849 new Tree_Operations.Generic_Write (Write_Node);
1855 procedure Write_Node
1856 (Stream : not null access Root_Stream_Type'Class;
1860 Element_Type'Output (Stream, Node.Element.all);
1863 -- Start of processing for Write
1866 Write (Stream, Container.Tree);
1870 (Stream : not null access Root_Stream_Type'Class;
1874 raise Program_Error with "attempt to stream set cursor";
1878 (Stream : not null access Root_Stream_Type'Class;
1879 Item : Reference_Type)
1882 raise Program_Error with "attempt to stream reference";
1886 (Stream : not null access Root_Stream_Type'Class;
1887 Item : Constant_Reference_Type)
1890 raise Program_Error with "attempt to stream reference";
1893 end Ada.Containers.Indefinite_Ordered_Sets;