1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- A D A . C O N T A I N E R S . O R D E R E D _ S E T S --
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.Unchecked_Deallocation;
32 with Ada.Containers.Red_Black_Trees.Generic_Operations;
33 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Operations);
35 with Ada.Containers.Red_Black_Trees.Generic_Keys;
36 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Keys);
38 with Ada.Containers.Red_Black_Trees.Generic_Set_Operations;
39 pragma Elaborate_All (Ada.Containers.Red_Black_Trees.Generic_Set_Operations);
41 with System; use type System.Address;
43 package body Ada.Containers.Ordered_Sets is
46 Ordered_Set_Iterator_Interfaces.Reversible_Iterator with record
47 Container : access constant Set;
51 overriding function First (Object : Iterator) return Cursor;
53 overriding function Last (Object : Iterator) return Cursor;
55 overriding function Next
57 Position : Cursor) return Cursor;
59 overriding function Previous
61 Position : Cursor) return Cursor;
63 ------------------------------
64 -- Access to Fields of Node --
65 ------------------------------
67 -- These subprograms provide functional notation for access to fields
68 -- of a node, and procedural notation for modifying these fields.
70 function Color (Node : Node_Access) return Color_Type;
71 pragma Inline (Color);
73 function Left (Node : Node_Access) return Node_Access;
76 function Parent (Node : Node_Access) return Node_Access;
77 pragma Inline (Parent);
79 function Right (Node : Node_Access) return Node_Access;
80 pragma Inline (Right);
82 procedure Set_Color (Node : Node_Access; Color : Color_Type);
83 pragma Inline (Set_Color);
85 procedure Set_Left (Node : Node_Access; Left : Node_Access);
86 pragma Inline (Set_Left);
88 procedure Set_Right (Node : Node_Access; Right : Node_Access);
89 pragma Inline (Set_Right);
91 procedure Set_Parent (Node : Node_Access; Parent : Node_Access);
92 pragma Inline (Set_Parent);
94 -----------------------
95 -- Local Subprograms --
96 -----------------------
98 function Copy_Node (Source : Node_Access) return Node_Access;
99 pragma Inline (Copy_Node);
101 procedure Free (X : in out Node_Access);
103 procedure Insert_Sans_Hint
104 (Tree : in out Tree_Type;
105 New_Item : Element_Type;
106 Node : out Node_Access;
107 Inserted : out Boolean);
109 procedure Insert_With_Hint
110 (Dst_Tree : in out Tree_Type;
111 Dst_Hint : Node_Access;
112 Src_Node : Node_Access;
113 Dst_Node : out Node_Access);
115 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean;
116 pragma Inline (Is_Equal_Node_Node);
118 function Is_Greater_Element_Node
119 (Left : Element_Type;
120 Right : Node_Access) return Boolean;
121 pragma Inline (Is_Greater_Element_Node);
123 function Is_Less_Element_Node
124 (Left : Element_Type;
125 Right : Node_Access) return Boolean;
126 pragma Inline (Is_Less_Element_Node);
128 function Is_Less_Node_Node (L, R : Node_Access) return Boolean;
129 pragma Inline (Is_Less_Node_Node);
131 procedure Replace_Element
132 (Tree : in out Tree_Type;
134 Item : Element_Type);
136 --------------------------
137 -- Local Instantiations --
138 --------------------------
140 package Tree_Operations is
141 new Red_Black_Trees.Generic_Operations (Tree_Types);
143 procedure Delete_Tree is
144 new Tree_Operations.Generic_Delete_Tree (Free);
146 function Copy_Tree is
147 new Tree_Operations.Generic_Copy_Tree (Copy_Node, Delete_Tree);
152 new Tree_Operations.Generic_Equal (Is_Equal_Node_Node);
154 package Element_Keys is
155 new Red_Black_Trees.Generic_Keys
156 (Tree_Operations => Tree_Operations,
157 Key_Type => Element_Type,
158 Is_Less_Key_Node => Is_Less_Element_Node,
159 Is_Greater_Key_Node => Is_Greater_Element_Node);
162 new Generic_Set_Operations
163 (Tree_Operations => Tree_Operations,
164 Insert_With_Hint => Insert_With_Hint,
165 Copy_Tree => Copy_Tree,
166 Delete_Tree => Delete_Tree,
167 Is_Less => Is_Less_Node_Node,
174 function "<" (Left, Right : Cursor) return Boolean is
176 if Left.Node = null then
177 raise Constraint_Error with "Left cursor equals No_Element";
180 if Right.Node = null then
181 raise Constraint_Error with "Right cursor equals No_Element";
184 pragma Assert (Vet (Left.Container.Tree, Left.Node),
185 "bad Left cursor in ""<""");
187 pragma Assert (Vet (Right.Container.Tree, Right.Node),
188 "bad Right cursor in ""<""");
190 return Left.Node.Element < Right.Node.Element;
193 function "<" (Left : Cursor; Right : Element_Type) return Boolean is
195 if Left.Node = null then
196 raise Constraint_Error with "Left cursor equals No_Element";
199 pragma Assert (Vet (Left.Container.Tree, Left.Node),
200 "bad Left cursor in ""<""");
202 return Left.Node.Element < 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 pragma Assert (Vet (Right.Container.Tree, Right.Node),
212 "bad Right cursor in ""<""");
214 return Left < Right.Node.Element;
221 function "=" (Left, Right : Set) return Boolean is
223 return Is_Equal (Left.Tree, Right.Tree);
230 function ">" (Left, Right : Cursor) return Boolean is
232 if Left.Node = null then
233 raise Constraint_Error with "Left cursor equals No_Element";
236 if Right.Node = null then
237 raise Constraint_Error with "Right cursor equals No_Element";
240 pragma Assert (Vet (Left.Container.Tree, Left.Node),
241 "bad Left cursor in "">""");
243 pragma Assert (Vet (Right.Container.Tree, Right.Node),
244 "bad Right cursor in "">""");
246 -- L > R same as R < L
248 return Right.Node.Element < Left.Node.Element;
251 function ">" (Left : Element_Type; Right : Cursor) return Boolean is
253 if Right.Node = null then
254 raise Constraint_Error with "Right cursor equals No_Element";
257 pragma Assert (Vet (Right.Container.Tree, Right.Node),
258 "bad Right cursor in "">""");
260 return Right.Node.Element < Left;
263 function ">" (Left : Cursor; Right : Element_Type) return Boolean is
265 if Left.Node = null then
266 raise Constraint_Error with "Left cursor equals No_Element";
269 pragma Assert (Vet (Left.Container.Tree, Left.Node),
270 "bad Left cursor in "">""");
272 return Right < Left.Node.Element;
279 procedure Adjust is new Tree_Operations.Generic_Adjust (Copy_Tree);
281 procedure Adjust (Container : in out Set) is
283 Adjust (Container.Tree);
290 procedure Assign (Target : in out Set; Source : Set) is
292 if Target'Address = Source'Address then
297 Target.Union (Source);
304 function Ceiling (Container : Set; Item : Element_Type) return Cursor is
305 Node : constant Node_Access :=
306 Element_Keys.Ceiling (Container.Tree, Item);
308 return (if Node = null then No_Element
309 else Cursor'(Container'Unrestricted_Access, Node));
316 procedure Clear is new Tree_Operations.Generic_Clear (Delete_Tree);
318 procedure Clear (Container : in out Set) is
320 Clear (Container.Tree);
327 function Color (Node : Node_Access) return Color_Type is
338 Item : Element_Type) return Boolean
341 return Find (Container, Item) /= No_Element;
348 function Copy (Source : Set) return Set is
350 return Target : Set do
351 Target.Assign (Source);
359 function Copy_Node (Source : Node_Access) return Node_Access is
360 Target : constant Node_Access :=
361 new Node_Type'(Parent => null,
364 Color => Source.Color,
365 Element => Source.Element);
374 procedure Delete (Container : in out Set; Position : in out Cursor) is
376 if Position.Node = null then
377 raise Constraint_Error with "Position cursor equals No_Element";
380 if Position.Container /= Container'Unrestricted_Access then
381 raise Program_Error with "Position cursor designates wrong set";
384 pragma Assert (Vet (Container.Tree, Position.Node),
385 "bad cursor in Delete");
387 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, Position.Node);
388 Free (Position.Node);
389 Position.Container := null;
392 procedure Delete (Container : in out Set; Item : Element_Type) is
393 X : Node_Access := Element_Keys.Find (Container.Tree, Item);
397 raise Constraint_Error with "attempt to delete element not in set";
400 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
408 procedure Delete_First (Container : in out Set) is
409 Tree : Tree_Type renames Container.Tree;
410 X : Node_Access := Tree.First;
413 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
422 procedure Delete_Last (Container : in out Set) is
423 Tree : Tree_Type renames Container.Tree;
424 X : Node_Access := Tree.Last;
427 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
436 procedure Difference (Target : in out Set; Source : Set) is
438 Set_Ops.Difference (Target.Tree, Source.Tree);
441 function Difference (Left, Right : Set) return Set is
442 Tree : constant Tree_Type :=
443 Set_Ops.Difference (Left.Tree, Right.Tree);
445 return Set'(Controlled with Tree);
452 function Element (Position : Cursor) return Element_Type is
454 if Position.Node = null then
455 raise Constraint_Error with "Position cursor equals No_Element";
458 pragma Assert (Vet (Position.Container.Tree, Position.Node),
459 "bad cursor in Element");
461 return Position.Node.Element;
464 -------------------------
465 -- Equivalent_Elements --
466 -------------------------
468 function Equivalent_Elements (Left, Right : Element_Type) return Boolean is
470 return (if Left < Right or else Right < Left then False else True);
471 end Equivalent_Elements;
473 ---------------------
474 -- Equivalent_Sets --
475 ---------------------
477 function Equivalent_Sets (Left, Right : Set) return Boolean is
478 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean;
479 pragma Inline (Is_Equivalent_Node_Node);
481 function Is_Equivalent is
482 new Tree_Operations.Generic_Equal (Is_Equivalent_Node_Node);
484 -----------------------------
485 -- Is_Equivalent_Node_Node --
486 -----------------------------
488 function Is_Equivalent_Node_Node (L, R : Node_Access) return Boolean is
490 return (if L.Element < R.Element then False
491 elsif R.Element < L.Element then False
493 end Is_Equivalent_Node_Node;
495 -- Start of processing for Equivalent_Sets
498 return Is_Equivalent (Left.Tree, Right.Tree);
505 procedure Exclude (Container : in out Set; Item : Element_Type) is
506 X : Node_Access := Element_Keys.Find (Container.Tree, Item);
510 Tree_Operations.Delete_Node_Sans_Free (Container.Tree, X);
519 function Find (Container : Set; Item : Element_Type) return Cursor is
520 Node : constant Node_Access :=
521 Element_Keys.Find (Container.Tree, Item);
523 return (if Node = null then No_Element
524 else Cursor'(Container'Unrestricted_Access, Node));
531 function First (Container : Set) return Cursor is
534 (if Container.Tree.First = null then No_Element
535 else Cursor'(Container'Unrestricted_Access, Container.Tree.First));
538 function First (Object : Iterator) return Cursor is
540 return (if Object.Container = null then No_Element
541 else Cursor'(Object.Container.all'Unrestricted_Access,
542 Object.Container.Tree.First));
549 function First_Element (Container : Set) return Element_Type is
551 if Container.Tree.First = null then
552 raise Constraint_Error with "set is empty";
555 return Container.Tree.First.Element;
562 function Floor (Container : Set; Item : Element_Type) return Cursor is
563 Node : constant Node_Access :=
564 Element_Keys.Floor (Container.Tree, Item);
566 return (if Node = null then No_Element
567 else Cursor'(Container'Unrestricted_Access, Node));
574 procedure Free (X : in out Node_Access) is
575 procedure Deallocate is
576 new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
590 package body Generic_Keys is
592 -----------------------
593 -- Local Subprograms --
594 -----------------------
596 function Is_Greater_Key_Node
598 Right : Node_Access) return Boolean;
599 pragma Inline (Is_Greater_Key_Node);
601 function Is_Less_Key_Node
603 Right : Node_Access) return Boolean;
604 pragma Inline (Is_Less_Key_Node);
606 --------------------------
607 -- Local Instantiations --
608 --------------------------
611 new Red_Black_Trees.Generic_Keys
612 (Tree_Operations => Tree_Operations,
613 Key_Type => Key_Type,
614 Is_Less_Key_Node => Is_Less_Key_Node,
615 Is_Greater_Key_Node => Is_Greater_Key_Node);
621 function Ceiling (Container : Set; Key : Key_Type) return Cursor is
622 Node : constant Node_Access :=
623 Key_Keys.Ceiling (Container.Tree, Key);
625 return (if Node = null then No_Element
626 else Cursor'(Container'Unrestricted_Access, Node));
633 function Contains (Container : Set; Key : Key_Type) return Boolean is
635 return Find (Container, Key) /= No_Element;
642 procedure Delete (Container : in out Set; Key : Key_Type) is
643 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
647 raise Constraint_Error with "attempt to delete key not in set";
650 Delete_Node_Sans_Free (Container.Tree, X);
658 function Element (Container : Set; Key : Key_Type) return Element_Type is
659 Node : constant Node_Access :=
660 Key_Keys.Find (Container.Tree, Key);
664 raise Constraint_Error with "key not in set";
670 ---------------------
671 -- Equivalent_Keys --
672 ---------------------
674 function Equivalent_Keys (Left, Right : Key_Type) return Boolean is
676 return (if Left < Right or else Right < Left then False else True);
683 procedure Exclude (Container : in out Set; Key : Key_Type) is
684 X : Node_Access := Key_Keys.Find (Container.Tree, Key);
687 Delete_Node_Sans_Free (Container.Tree, X);
696 function Find (Container : Set; Key : Key_Type) return Cursor is
697 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
699 return (if Node = null then No_Element
700 else Cursor'(Container'Unrestricted_Access, Node));
707 function Floor (Container : Set; Key : Key_Type) return Cursor is
708 Node : constant Node_Access := Key_Keys.Floor (Container.Tree, Key);
710 return (if Node = null then No_Element
711 else Cursor'(Container'Unrestricted_Access, Node));
714 -------------------------
715 -- Is_Greater_Key_Node --
716 -------------------------
718 function Is_Greater_Key_Node
720 Right : Node_Access) return Boolean
723 return Key (Right.Element) < Left;
724 end Is_Greater_Key_Node;
726 ----------------------
727 -- Is_Less_Key_Node --
728 ----------------------
730 function Is_Less_Key_Node
732 Right : Node_Access) return Boolean
735 return Left < Key (Right.Element);
736 end Is_Less_Key_Node;
742 function Key (Position : Cursor) return Key_Type is
744 if Position.Node = null then
745 raise Constraint_Error with
746 "Position cursor equals No_Element";
749 pragma Assert (Vet (Position.Container.Tree, Position.Node),
750 "bad cursor in Key");
752 return Key (Position.Node.Element);
760 (Container : in out Set;
762 New_Item : Element_Type)
764 Node : constant Node_Access := Key_Keys.Find (Container.Tree, Key);
768 raise Constraint_Error with
769 "attempt to replace key not in set";
772 Replace_Element (Container.Tree, Node, New_Item);
775 -----------------------------------
776 -- Update_Element_Preserving_Key --
777 -----------------------------------
779 procedure Update_Element_Preserving_Key
780 (Container : in out Set;
782 Process : not null access procedure (Element : in out Element_Type))
784 Tree : Tree_Type renames Container.Tree;
787 if Position.Node = null then
788 raise Constraint_Error with
789 "Position cursor equals No_Element";
792 if Position.Container /= Container'Unrestricted_Access then
793 raise Program_Error with
794 "Position cursor designates wrong set";
797 pragma Assert (Vet (Container.Tree, Position.Node),
798 "bad cursor in Update_Element_Preserving_Key");
801 E : Element_Type renames Position.Node.Element;
802 K : constant Key_Type := Key (E);
804 B : Natural renames Tree.Busy;
805 L : Natural renames Tree.Lock;
823 if Equivalent_Keys (K, Key (E)) then
829 X : Node_Access := Position.Node;
831 Tree_Operations.Delete_Node_Sans_Free (Tree, X);
835 raise Program_Error with "key was modified";
836 end Update_Element_Preserving_Key;
838 function Reference_Preserving_Key
839 (Container : aliased in out Set;
840 Key : Key_Type) return Constant_Reference_Type
842 Position : constant Cursor := Find (Container, Key);
845 if Position.Container = null then
846 raise Constraint_Error with "Position cursor has no element";
849 return (Element => Position.Node.Element'Access);
850 end Reference_Preserving_Key;
852 function Reference_Preserving_Key
853 (Container : aliased in out Set;
854 Key : Key_Type) return Reference_Type
856 Position : constant Cursor := Find (Container, Key);
859 if Position.Container = null then
860 raise Constraint_Error with "Position cursor has no element";
863 return (Element => Position.Node.Element'Access);
864 end Reference_Preserving_Key;
867 (Stream : not null access Root_Stream_Type'Class;
868 Item : out Reference_Type)
871 raise Program_Error with "attempt to stream reference";
875 (Stream : not null access Root_Stream_Type'Class;
876 Item : Reference_Type)
879 raise Program_Error with "attempt to stream reference";
888 function Has_Element (Position : Cursor) return Boolean is
890 return Position /= No_Element;
897 procedure Include (Container : in out Set; New_Item : Element_Type) is
902 Insert (Container, New_Item, Position, Inserted);
905 if Container.Tree.Lock > 0 then
906 raise Program_Error with
907 "attempt to tamper with elements (set is locked)";
910 Position.Node.Element := New_Item;
919 (Container : in out Set;
920 New_Item : Element_Type;
921 Position : out Cursor;
922 Inserted : out Boolean)
931 Position.Container := Container'Unrestricted_Access;
935 (Container : in out Set;
936 New_Item : Element_Type)
939 pragma Unreferenced (Position);
944 Insert (Container, New_Item, Position, Inserted);
947 raise Constraint_Error with
948 "attempt to insert element already in set";
952 ----------------------
953 -- Insert_Sans_Hint --
954 ----------------------
956 procedure Insert_Sans_Hint
957 (Tree : in out Tree_Type;
958 New_Item : Element_Type;
959 Node : out Node_Access;
960 Inserted : out Boolean)
962 function New_Node return Node_Access;
963 pragma Inline (New_Node);
965 procedure Insert_Post is
966 new Element_Keys.Generic_Insert_Post (New_Node);
968 procedure Conditional_Insert_Sans_Hint is
969 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
975 function New_Node return Node_Access is
977 return new Node_Type'(Parent => null,
980 Color => Red_Black_Trees.Red,
981 Element => New_Item);
984 -- Start of processing for Insert_Sans_Hint
987 Conditional_Insert_Sans_Hint
992 end Insert_Sans_Hint;
994 ----------------------
995 -- Insert_With_Hint --
996 ----------------------
998 procedure Insert_With_Hint
999 (Dst_Tree : in out Tree_Type;
1000 Dst_Hint : Node_Access;
1001 Src_Node : Node_Access;
1002 Dst_Node : out Node_Access)
1005 pragma Unreferenced (Success);
1007 function New_Node return Node_Access;
1008 pragma Inline (New_Node);
1010 procedure Insert_Post is
1011 new Element_Keys.Generic_Insert_Post (New_Node);
1013 procedure Insert_Sans_Hint is
1014 new Element_Keys.Generic_Conditional_Insert (Insert_Post);
1016 procedure Local_Insert_With_Hint is
1017 new Element_Keys.Generic_Conditional_Insert_With_Hint
1025 function New_Node return Node_Access is
1026 Node : constant Node_Access :=
1027 new Node_Type'(Parent => null,
1031 Element => Src_Node.Element);
1036 -- Start of processing for Insert_With_Hint
1039 Local_Insert_With_Hint
1045 end Insert_With_Hint;
1051 procedure Intersection (Target : in out Set; Source : Set) is
1053 Set_Ops.Intersection (Target.Tree, Source.Tree);
1056 function Intersection (Left, Right : Set) return Set is
1057 Tree : constant Tree_Type :=
1058 Set_Ops.Intersection (Left.Tree, Right.Tree);
1060 return Set'(Controlled with Tree);
1067 function Is_Empty (Container : Set) return Boolean is
1069 return Container.Tree.Length = 0;
1072 ------------------------
1073 -- Is_Equal_Node_Node --
1074 ------------------------
1076 function Is_Equal_Node_Node (L, R : Node_Access) return Boolean is
1078 return L.Element = R.Element;
1079 end Is_Equal_Node_Node;
1081 -----------------------------
1082 -- Is_Greater_Element_Node --
1083 -----------------------------
1085 function Is_Greater_Element_Node
1086 (Left : Element_Type;
1087 Right : Node_Access) return Boolean
1090 -- Compute e > node same as node < e
1092 return Right.Element < Left;
1093 end Is_Greater_Element_Node;
1095 --------------------------
1096 -- Is_Less_Element_Node --
1097 --------------------------
1099 function Is_Less_Element_Node
1100 (Left : Element_Type;
1101 Right : Node_Access) return Boolean
1104 return Left < Right.Element;
1105 end Is_Less_Element_Node;
1107 -----------------------
1108 -- Is_Less_Node_Node --
1109 -----------------------
1111 function Is_Less_Node_Node (L, R : Node_Access) return Boolean is
1113 return L.Element < R.Element;
1114 end Is_Less_Node_Node;
1120 function Is_Subset (Subset : Set; Of_Set : Set) return Boolean is
1122 return Set_Ops.Is_Subset (Subset => Subset.Tree, Of_Set => Of_Set.Tree);
1131 Process : not null access procedure (Position : Cursor))
1133 procedure Process_Node (Node : Node_Access);
1134 pragma Inline (Process_Node);
1136 procedure Local_Iterate is
1137 new Tree_Operations.Generic_Iteration (Process_Node);
1143 procedure Process_Node (Node : Node_Access) is
1145 Process (Cursor'(Container'Unrestricted_Access, Node));
1148 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1149 B : Natural renames T.Busy;
1151 -- Start of processing for Iterate
1167 function Iterate (Container : Set)
1168 return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
1171 if Container.Length = 0 then
1172 return Iterator'(null, null);
1174 return Iterator'(Container'Unchecked_Access, Container.Tree.First);
1178 function Iterate (Container : Set; Start : Cursor)
1179 return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
1181 It : constant Iterator := (Container'Unchecked_Access, Start.Node);
1190 function Last (Container : Set) return Cursor is
1193 (if Container.Tree.Last = null then No_Element
1194 else Cursor'(Container'Unrestricted_Access, Container.Tree.Last));
1197 function Last (Object : Iterator) return Cursor is
1199 return (if Object.Container = null then No_Element
1200 else Cursor'(Object.Container.all'Unrestricted_Access,
1201 Object.Container.Tree.Last));
1208 function Last_Element (Container : Set) return Element_Type is
1210 if Container.Tree.Last = null then
1211 raise Constraint_Error with "set is empty";
1213 return Container.Tree.Last.Element;
1221 function Left (Node : Node_Access) return Node_Access is
1230 function Length (Container : Set) return Count_Type is
1232 return Container.Tree.Length;
1239 procedure Move is new Tree_Operations.Generic_Move (Clear);
1241 procedure Move (Target : in out Set; Source : in out Set) is
1243 Move (Target => Target.Tree, Source => Source.Tree);
1250 function Next (Position : Cursor) return Cursor is
1252 if Position = No_Element then
1256 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1257 "bad cursor in Next");
1260 Node : constant Node_Access :=
1261 Tree_Operations.Next (Position.Node);
1263 return (if Node = null then No_Element
1264 else Cursor'(Position.Container, Node));
1268 procedure Next (Position : in out Cursor) is
1270 Position := Next (Position);
1273 function Next (Object : Iterator; Position : Cursor) return Cursor is
1274 pragma Unreferenced (Object);
1276 return Next (Position);
1283 function Overlap (Left, Right : Set) return Boolean is
1285 return Set_Ops.Overlap (Left.Tree, Right.Tree);
1292 function Parent (Node : Node_Access) return Node_Access is
1301 function Previous (Position : Cursor) return Cursor is
1303 if Position = No_Element then
1307 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1308 "bad cursor in Previous");
1311 Node : constant Node_Access :=
1312 Tree_Operations.Previous (Position.Node);
1314 return (if Node = null then No_Element
1315 else Cursor'(Position.Container, Node));
1319 procedure Previous (Position : in out Cursor) is
1321 Position := Previous (Position);
1324 function Previous (Object : Iterator; Position : Cursor) return Cursor is
1325 pragma Unreferenced (Object);
1327 return Previous (Position);
1334 procedure Query_Element
1336 Process : not null access procedure (Element : Element_Type))
1339 if Position.Node = null then
1340 raise Constraint_Error with "Position cursor equals No_Element";
1343 pragma Assert (Vet (Position.Container.Tree, Position.Node),
1344 "bad cursor in Query_Element");
1347 T : Tree_Type renames Position.Container.Tree;
1349 B : Natural renames T.Busy;
1350 L : Natural renames T.Lock;
1357 Process (Position.Node.Element);
1375 (Stream : not null access Root_Stream_Type'Class;
1376 Container : out Set)
1379 (Stream : not null access Root_Stream_Type'Class) return Node_Access;
1380 pragma Inline (Read_Node);
1383 new Tree_Operations.Generic_Read (Clear, Read_Node);
1390 (Stream : not null access Root_Stream_Type'Class) return Node_Access
1392 Node : Node_Access := new Node_Type;
1394 Element_Type'Read (Stream, Node.Element);
1402 -- Start of processing for Read
1405 Read (Stream, Container.Tree);
1409 (Stream : not null access Root_Stream_Type'Class;
1413 raise Program_Error with "attempt to stream set cursor";
1417 (Stream : not null access Root_Stream_Type'Class;
1418 Item : out Constant_Reference_Type)
1421 raise Program_Error with "attempt to stream reference";
1428 function Constant_Reference (Container : Set; Position : Cursor)
1429 return Constant_Reference_Type
1431 pragma Unreferenced (Container);
1433 if Position.Container = null then
1434 raise Constraint_Error with "Position cursor has no element";
1437 return (Element => Position.Node.Element'Access);
1438 end Constant_Reference;
1444 procedure Replace (Container : in out Set; New_Item : Element_Type) is
1445 Node : constant Node_Access :=
1446 Element_Keys.Find (Container.Tree, New_Item);
1450 raise Constraint_Error with
1451 "attempt to replace element not in set";
1454 if Container.Tree.Lock > 0 then
1455 raise Program_Error with
1456 "attempt to tamper with elements (set is locked)";
1459 Node.Element := New_Item;
1462 ---------------------
1463 -- Replace_Element --
1464 ---------------------
1466 procedure Replace_Element
1467 (Tree : in out Tree_Type;
1469 Item : Element_Type)
1471 pragma Assert (Node /= null);
1473 function New_Node return Node_Access;
1474 pragma Inline (New_Node);
1476 procedure Local_Insert_Post is
1477 new Element_Keys.Generic_Insert_Post (New_Node);
1479 procedure Local_Insert_Sans_Hint is
1480 new Element_Keys.Generic_Conditional_Insert (Local_Insert_Post);
1482 procedure Local_Insert_With_Hint is
1483 new Element_Keys.Generic_Conditional_Insert_With_Hint
1485 Local_Insert_Sans_Hint);
1491 function New_Node return Node_Access is
1493 Node.Element := Item;
1495 Node.Parent := null;
1502 Result : Node_Access;
1505 -- Start of processing for Replace_Element
1508 if Item < Node.Element or else Node.Element < Item then
1512 if Tree.Lock > 0 then
1513 raise Program_Error with
1514 "attempt to tamper with elements (set is locked)";
1517 Node.Element := Item;
1521 Hint := Element_Keys.Ceiling (Tree, Item);
1526 elsif Item < Hint.Element then
1528 if Tree.Lock > 0 then
1529 raise Program_Error with
1530 "attempt to tamper with elements (set is locked)";
1533 Node.Element := Item;
1538 pragma Assert (not (Hint.Element < Item));
1539 raise Program_Error with "attempt to replace existing element";
1542 Tree_Operations.Delete_Node_Sans_Free (Tree, Node); -- Checks busy-bit
1544 Local_Insert_With_Hint
1549 Inserted => Inserted);
1551 pragma Assert (Inserted);
1552 pragma Assert (Result = Node);
1553 end Replace_Element;
1555 procedure Replace_Element
1556 (Container : in out Set;
1558 New_Item : Element_Type)
1561 if Position.Node = null then
1562 raise Constraint_Error with
1563 "Position cursor equals No_Element";
1566 if Position.Container /= Container'Unrestricted_Access then
1567 raise Program_Error with
1568 "Position cursor designates wrong set";
1571 pragma Assert (Vet (Container.Tree, Position.Node),
1572 "bad cursor in Replace_Element");
1574 Replace_Element (Container.Tree, Position.Node, New_Item);
1575 end Replace_Element;
1577 ---------------------
1578 -- Reverse_Iterate --
1579 ---------------------
1581 procedure Reverse_Iterate
1583 Process : not null access procedure (Position : Cursor))
1585 procedure Process_Node (Node : Node_Access);
1586 pragma Inline (Process_Node);
1588 procedure Local_Reverse_Iterate is
1589 new Tree_Operations.Generic_Reverse_Iteration (Process_Node);
1595 procedure Process_Node (Node : Node_Access) is
1597 Process (Cursor'(Container'Unrestricted_Access, Node));
1600 T : Tree_Type renames Container.Tree'Unrestricted_Access.all;
1601 B : Natural renames T.Busy;
1603 -- Start of processing for Reverse_Iterate
1609 Local_Reverse_Iterate (T);
1617 end Reverse_Iterate;
1623 function Right (Node : Node_Access) return Node_Access is
1632 procedure Set_Color (Node : Node_Access; Color : Color_Type) is
1634 Node.Color := Color;
1641 procedure Set_Left (Node : Node_Access; Left : Node_Access) is
1650 procedure Set_Parent (Node : Node_Access; Parent : Node_Access) is
1652 Node.Parent := Parent;
1659 procedure Set_Right (Node : Node_Access; Right : Node_Access) is
1661 Node.Right := Right;
1664 --------------------------
1665 -- Symmetric_Difference --
1666 --------------------------
1668 procedure Symmetric_Difference (Target : in out Set; Source : Set) is
1670 Set_Ops.Symmetric_Difference (Target.Tree, Source.Tree);
1671 end Symmetric_Difference;
1673 function Symmetric_Difference (Left, Right : Set) return Set is
1674 Tree : constant Tree_Type :=
1675 Set_Ops.Symmetric_Difference (Left.Tree, Right.Tree);
1677 return Set'(Controlled with Tree);
1678 end Symmetric_Difference;
1684 function To_Set (New_Item : Element_Type) return Set is
1688 pragma Unreferenced (Node, Inserted);
1690 Insert_Sans_Hint (Tree, New_Item, Node, Inserted);
1691 return Set'(Controlled with Tree);
1698 procedure Union (Target : in out Set; Source : Set) is
1700 Set_Ops.Union (Target.Tree, Source.Tree);
1703 function Union (Left, Right : Set) return Set is
1704 Tree : constant Tree_Type :=
1705 Set_Ops.Union (Left.Tree, Right.Tree);
1707 return Set'(Controlled with Tree);
1715 (Stream : not null access Root_Stream_Type'Class;
1718 procedure Write_Node
1719 (Stream : not null access Root_Stream_Type'Class;
1720 Node : Node_Access);
1721 pragma Inline (Write_Node);
1724 new Tree_Operations.Generic_Write (Write_Node);
1730 procedure Write_Node
1731 (Stream : not null access Root_Stream_Type'Class;
1735 Element_Type'Write (Stream, Node.Element);
1738 -- Start of processing for Write
1741 Write (Stream, Container.Tree);
1745 (Stream : not null access Root_Stream_Type'Class;
1749 raise Program_Error with "attempt to stream set cursor";
1753 (Stream : not null access Root_Stream_Type'Class;
1754 Item : Constant_Reference_Type)
1757 raise Program_Error with "attempt to stream reference";
1760 end Ada.Containers.Ordered_Sets;